EOF exit 1 fiDEPLOY_VERSION=$1
RP_FILES=(subproject1/kube-rc.yaml subproject1/pom.xml subproject1/Makefile) if [ -z $(git branch -a | grep -e /${DEPLOY_VERSION}$) ]; then git branch ${DEPLOY_VERSION} git checkout ${DEPLOY_VERSION} else
git checkout ${DEPLOY_VERSION} git pull
fi
#替换k8s配置文件中环境指向,从开发切换到测试 #替换掉pom.xml文件中的SNAPSHOT为release版本号
#替换掉makefile中发布的镜像Tag的latest为release版本号 for f in ${RP_FILES[@]}; do
sed -i -e \"s#api.devproject.com#api.testproject.com#g\" \\
-e \"s#0.0.1-SNAPSHOT#${DEPLOY_VERSION}-SNAPSHOT#g\" \\ -e \"s#latest#${DEPLOY_VERSION}#g\" $f done
git commit -a -m \"Create Branch ${DEPLOY_VERSION}\" git push origin ${DEPLOY_VERSION}
b) Dockerfile示例文件,将Java dubbo服务发布为镜像为例,示例见附件2:
FROM registry.xcompany.com/java:openjdk-7-jre
MAINTAINER zhangsan
ENV spring.profiles.active=\"production\" ENV JAVA_OPTS=\"-Xmx1024m\" RUN mkdir -p /app
COPY target/subproject1.war /app/ COPY ./startup.sh /app/ RUN chmod +x /app/startup.sh WORKDIR /app CMD [\"./startup.sh\"] EXPOSE 8080
c) Makefile文件: 包括编译项目、将项目打包成Docker镜像、将镜像Push到镜像仓库、在K8s上创建ReplicationController、在K8s上创建service的命令脚本:
IMAGE_PREFIX = registry.xcompany.com/project1/
COMPONENT = subproject1 ifndef BUILD_TAG BUILD_TAG = latest endif
IMAGE = $(IMAGE_PREFIX)$(COMPONENT):$(BUILD_TAG) ifndef KUBE_OPS
KUBE_OPS = --server=https://api.devproject.com --namespace=project1 endif
clean: mvn clean compile: clean
mvn -U -DskipTests=true -Dmaven.javadoc.skip=true package #将当前程序打包成Docker镜像 build:
docker build -t $(IMAGE) . #将当前镜像Push到镜像仓库 push:
docker push $(IMAGE) run:
docker run --rm -it -e spring.profiles.active=application -p 8080:8080 $(IMAGE) #部署RelicationController deploy:
kubectl create -f kube-rc.yaml $(KUBE_OPS) redeploy:
kubectl replace -f kube-rc.yaml $(KUBE_OPS) undeploy:
kubectl delete -f kube-rc.yaml $(KUBE_OPS) #创建service deploy-svc:
kubectl create -f kube-svc.yaml $(KUBE_OPS) undeploy-svc:
kubectl delete -f kube-svc.yaml $(KUBE_OPS)
d) K8s部署配置文件,创建ReplicationController、创建service示例见附件4:
#创建ReplicationController apiVersion: v1
kind: ReplicationController metadata:
name: subproject1 spec:
replicas: 1 selector:
name: subproject1 template:
metadata: labels:
name: subproject1 spec:
containers:
- name: subproject1
image: registry.xcompany.com/project1/subproject1:latest imagePullPolicy: Always env:
- name: DUBBO_REGISTRY_ADDRESS value: \"kube://zookeeper:2181\" - name: DUBBO_REGISTRY_REGISTER value: \"true\" ports:
- containerPort: 8888 #创建Service apiVersion: v1 kind: Service metadata:
name: subproject1 labels:
component: subproject1 spec: ports:
- port: 8888
nodePort: 16888 selector:
name: svc-subproject1 type: NodePor
e) 配置管理员在Jenkins上配置自动或手动触发的任务,在jenkins任务中配置shell脚本,可实现应用的一键部署,示例见附件5。
#!/bin/bash -e
IMAGE=registry.xcompay.com/project1/sub-project1:$IMAGE_VERSION make compile
if [ $build = \"true\" ]; then echo \"docker build -t $IMAGE\" docker build -t $IMAGE . echo \"docker push $IMAGE\" docker push $IMAGE fi
if [ $undeploy = \"true\" ]; then make undeploy fi
if [ $deploy = \"true\" ]; then make deploy fi
if [ $deploysvc = \"true\" ]; then make deploy-svc fi
具体的过程说如下:
i. 从Git上拉取代码,编译、发布项目; ii. 将编译好的程序包,打包成Docker镜像; iii. 将打包好的Docker镜像Push到镜像仓库;
iv. Jenkins执行Shell脚本命令,从镜像仓库拉取镜像在K8s环境中创建pod和RC,将应用程序及其运行环境所在的容器在K8s平台上运行起来。
测试与发版:
从图中可以看到,项目的开发环境和测试环境是相互隔离的两套环境。
a) 部署在开发环境的应用代码,来自develop分支,对应的Docker镜像Tag用latest,供开发人员调试、以及测试人员随时协助做集成测试;
b) 部署在测是环境的应用代码,来自每到一个Sprint阶段发版测试时配置管理员从develop分支中打出的测试发版分支,分支名对应的版本号不同,相应的Docker镜像的tag也会随是版本号改变。测试环境中部署的应用主要用于测试验证。
部署联调:
项目分为四层:前端UI、WEB层有若干个web应用、Service层包括若干个分布式服务、基础底层。这里简要说明一下各层之间的调试方式:
a) 前端和Web层联调:前端开发人员本地启动一个Nginx,配置nginx.conf文件将localhost代理指向web server的地址,即可在本地调试与动态Web端的交互。
b) WEB层与服务层联调、服务层之间联调、服务层与基础层联调,分为两种方式: 本地调试:部署一个专用的zookeeper注册中心,开发者可以把本机地址注册到注册中心,供相关人员临时调用服务调试。
集成环境调试:提交代码触发Jenkins任务,将服务打包成容器镜像,部署到K8s上在完整的系统运行环境中联合调试。具体的集成环境编排依赖于k8s完成。
微服务的分层和服务交互设计
关于微服架构的利弊以及设计原则有很多著名的文章有介绍,例如MarinFowler的博文《Microservices:a definition of this new architectural term》和来自DZone community社区的《Microservices in Practice: From Architecture to Deployment》在InfoQ等技术网站都有中文翻译,本文就不对概念和设计原则做过多赘述。本小节主要是说明关于项目的逻辑分层结构和服务交互方面的设计。
本项目遵守以下微服务架构的主要基本原则,但是也会根据具体项目情况有所保留。 i. 单一责任原则(Single Responsibility Principle,SRP) ii. 保证微服务设计能支持服务的敏捷/地开发和部署。
图 2分层结构及通信机制
架构分层设计
如图2所示,项目的架构是分为四层:静态UI层、动态WEB层、业务服务层、基础业务层。 i. 静态UI层,直接面向用户的操作展示界面,包括静态UI设计和JS交互代码,主要采用Angulars框架;
ii.动态WEB层是各业务服务的“门面”,根据前端设计的需要调用、组装业务服务层的API,相对来说,这一层变动的频率较高,例如系统需要进行流程优化或者前端UE改造,相应的都要变更这一层。动态WEB层采用Java Spring或者python Django框架实现;
iii.业务服务层,根据业务需求按照功能对基础服务层进行扩展和包装,采用Dubbo分布式服务框架实现,具体版本是当当扩展过的Dubbox,支持REST API,并且对Spring的支持升级到了3.x;
iv. 基础服务层比较稳定,提供一些基础功能,采用Go语言/Ruby/Java/Python等多种语言实现的。