施行微服务架构后,原先繁多的系统结构统变成了数量泛滥的微服务利用,开发、测试、运维部署等都会面临不少挑战。在微服务架构下如何进步工程研发效率,确保开发、测试、运维部署等流程上的顺畅,是微服务技术体系可能真正落地产生效益的要害。
要实现上述指标就须要基于 DevOps(开发运维)思维构建一套高度自动化的公布零碎,在该零碎中开发人员能够随时随地构建代码并将其公布至指定的运行环境中,这个过程也就是咱们通常所说的 CI/CD(继续集成 / 继续交付)流程。
对于 DevOps 的具体实际,不同的公司个别会依据本身的倒退阶段和理论须要来抉择具体落地的计划。具备条件的公司能够研发功能丰富的可视化公布零碎,而条件无限的守业公司则能够通过开源或现有的技术组件(如 GitLab、Jenkins 等)来实现操作绝对简陋但性能齐备的自动化公布零碎。
在本篇文章中我将以 Spring Cloud 微服务技术体系为背景,通过 GitLab 自带的 CI/CD 机制并基于 Kubernetes 容器化技术来实现一套具备绝对残缺 CI/CD 流程的自动化公布零碎。
CI/CD 流程概述
实际上 DevOps 并不是微服务架构风行之后才产生的概念,而是业界在多年软件开发实际中积攒的实践、工具的汇合。本文所要探讨的自动化公布零碎实际上是要通过搭建 CI/CD 流水线来建设一套应用程序构建、测试、打包及公布的高效自动化办法。对于 CI(继续集成)/CD(继续交付)的概念并不是指某一种具体的技术,而是一种软件工程文化加一系列操作准则和具体实际的汇合。
其中 CI(继续集成)的次要指标是通过建设统一的自动化构建办法来打包程序代码,使得团队成员可能以更频繁地动作提交代码、更早地进行代码集成,以及时发现和解决代码中的问题、进步合作开发效率及软件交付品质。可继续集成(CI)的根本流程如图所示:
从实现流程上来说 CI 的次要过程就是将开发人员提交的代码以高度自动化的形式打包成能够在具体基础架构环境运行的程序包(例如 Docker 镜像)。而这个过程能够由一组工具如 GitLab Runner(CI Pipeline)、Sonar(代码检测工具)等去实现,具体构建 CI 流程时依据理论须要集成使用即可。
继续交付(CD)的次要逻辑则是将 CI 流程中构建的程序镜像从镜像仓库主动公布到具体的基础架构环境(如测试 / 生产 Kubernetes 集群),实现 CD 的工具次要有 GitLab Runner(CD Pipeline)、Helm(Kubernetes 软件包管理工具)等。
实际上 CD 的外围就是通过输出的各种用户参数(如 yaml 文件、环境配置参数等)最终主动生成具体的公布指令(如 Helm 指令),并依据参数中设置的相应信息来配置程序的具体运行环境。可继续交付(CD)的根本运行流程如下图所示:
以上就是 CI/CD 的基本概念及流程,也是自动化公布零碎的实现的根据。在前面的内容中将次要围绕这两个阶段来实现自动化公布零碎的根本流程逻辑。
零碎的根本组成
本文所要形容的自动化公布零碎次要是利用 GitLab 提供的 GitLab CI 机制,实现当代码产生提交或合并等事件时主动触发预设的 CI/CD 流程。其中 CI 流程次要包含根本的代码编译、构建、打包等阶段,并在实现上述步骤后将打包好的利用 Docker 镜像公布至镜像仓库。
而 CD 阶段则是从镜像仓库拉取利用 Docker 镜像,并依据设置的 CD 流程将利用公布至指定的 Kubernetes 集群。具体系统结构如下图所示:
如上图所示,该自动化公布零碎次要由 GitLab、Harbor 镜像仓库及 Kubernetes 集群组成。其中 GitLab 次要承当代码版本的治理,以及 CI/CD 流程定义和触发,Harbor 负责利用 Docker 镜像的存储和散发,而 Kubernetes 集群则是利用容器运行的基础架构环境。
GitLab-CI 自动化公布零碎的要害实现
后面咱们形容了基于 GitLab-CI 机制实现自动化公布零碎的根本组成,要具体实现这套零碎你须要装置部署 GitLab 服务器并配置 GItLab Runner 性能,公有镜像仓库服务(Harbor 或 JFrog)以及 Kubernetes 集群(具体可参见本专栏的其余文章)。
因为 GitLab 服务器是 CI/CD 流程执行的次要承载点,如果你的服务是基于 Maven 构建的 Java 服务,那么还须要在 GitLab 服务器中装置 Maven 客户端,并配置 Maven 私服的地址,以进步构建速度。此外 GitLab 服务器在 CI/CD 流程执行中还会运行 Docker 镜像打包构建,将镜像 push 到 Docker 镜像仓库以及将 Docker 镜像从公有仓库公布至 Kubernetes 集群等逻辑,所以 GitLab 服务器还须要装置 Docker 环境及 kubelet 客户端。
如果环境都 OK,那么咱们就能够在 Gitlab 我的项目根目录代码中创立“.gitlab-ci.yml”文件并定义具体的 CI/CD 流程了。但在具体定义之前,咱们须要在 Maven 我的项目中增加利用 Docker 镜像打包的插件配置及 Dockerfile 文件定义,具体如下:
<!-- 增加 Docker 镜像 Maven 打包插件 -->
<plugin>
<groupId>com.spotify</groupId>
<artifactId>dockerfile-maven-plugin</artifactId>
<version>1.4.13</version>
<executions>
<execution>
<id>build-image</id>
<phase>package</phase>
<goals>
<goal>build</goal>
</goals>
</execution>
</executions>
<configuration>
<!-- 指定 Dockerfile 文件地位 -->
<dockerfile>docker/Dockerfile</dockerfile>
<!-- 指定 Docker 镜像仓库门路 -->
<repository>${docker.repository}/springcloud-action/${app.name}</repository>
<buildArgs>
<!-- 提供参数向 Dockerfile 传递 -->
<JAR_FILE>target/${project.build.finalName}.jar</JAR_FILE>
</buildArgs>
</configuration>
</plugin>
在我的项目工程 pom.xml 文件中增加“dockerfile-maven-plugin”插件,该插件是晚期“docker-maven-plugin”插件的替代品,反对将 Maven 我的项目构建打包为 Docker 镜像。上述配置中,针对 Docker 镜像的具体构建形式,是通过在 <configuration> 标签中指定 Dockerfile 文件来实现的。具体可在我的项目工程中创立 docker 目录,并创立 Dockerfile 文件,内容如下:
FROM openjdk:8u191-jre-alpine3.9
ENTRYPOINT ["/usr/bin/java", "-jar", "/app.jar"]
ARG JAR_FILE
ADD ${JAR_FILE} /app.jar
EXPOSE 8080
配置好 Maven 打包插件后,就能反对通过 Maven 打包命令,将利用代码打包成 Docker 镜像了。此时咱们在 ”.gitlab-ci.yml” 文件中定义具体的 CI/CD 构建 Stages,示例如下:
# 环境参数信息
variables:
#Docker 镜像仓库地址 & 账号密码信息
DOCKER_REPO_URL: "10.211.55.11:8088"
DOCKER_REPO_USERNAME: admin
DOCKER_REPO_PASSWORD: Harbor12345
#Kubernetes 相干信息配置 (空间与服务端口)
K8S_NAMESPACE: "wudimanong"
PORT: "8080"
#定义 CI/CD 阶段
stages:
- test
- build
- push
- deploy
#执行单元测试阶段
maven-test:
stage: test
script:
- mvn clean test
#代码编译打包镜像阶段
maven-build:
stage: build
script:
- mvn clean package -DskipTests
#将打包的 Docker 镜像上传至公有镜像仓库
docker-push:
stage: push
script:
#对打包的镜像进行 tag
- docker tag $DOCKER_REPO_URL/$CI_PROJECT_PATH $DOCKER_REPO_URL/$CI_PROJECT_PATH/$CI_BUILD_REF_NAME:${CI_COMMIT_SHA:0:8}
#登录公有镜像仓库
- docker login $DOCKER_REPO_URL -u $DOCKER_REPO_USERNAME -p $DOCKER_REPO_PASSWORD
#上传利用镜像至镜像仓库
- docker push $DOCKER_REPO_URL/$CI_PROJECT_PATH/$CI_BUILD_REF_NAME:${CI_COMMIT_SHA:0:8}
- docker rmi $DOCKER_REPO_URL/$CI_PROJECT_PATH/$CI_BUILD_REF_NAME:${CI_COMMIT_SHA:0:8}
- docker rmi $DOCKER_REPO_URL/$CI_PROJECT_PATH
#将利用公布至 Kubernetes 测试集群(这里指定为手动确认形式)deploy-test:
stage: deploy
when: manual
script:
- kubectl config use-context kubernetes-admin@kubernetes
- sed -e "s/__REPLICAS__/1/; s/__PORT__/$PORT/; s/__APP_NAME__/$CI_PROJECT_NAME/; s/__PROFILE__/test/; s/__IMAGE__/$DOCKER_REPO_URL\/${CI_PROJECT_PATH//\//\\/}\/${CI_BUILD_REF_NAME//\//\\/}:${CI_COMMIT_SHA:0:8}/" kubernetes/deploy.yaml | kubectl -n ${K8S_NAMESPACE} apply -f -
如上所述,咱们在“.gitlab-ci.yml”文件中定义了”test、build、push、deploy”这 4 个 stages 阶段。这几个 stages 的具体阐明如下:
- test:执行单元测试代码;
- build:执行构建打包指令,将利用构建打包为 Docker 镜像;
- push:该阶段次要是将 build 构建的本地 Docker 镜像通过 tag 解决后上传至 Harbor 镜像仓库,并在胜利后清理掉本地镜像文件;
- deploy:该阶段次要是执行 Kubernetes 指令,依据 Kubernetes 公布部署文件的配置,将容器镜像部署公布至 Kubernetes 集群;
在 deploy 阶段,是将 Docker 镜像公布运行至 Kubernetes 集群,其中波及编写 Kubernetes 部署公布 yaml 文件,具体示例如下:
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: __APP_NAME__
spec:
replicas: __REPLICAS__
selector:
matchLabels:
app: __APP_NAME__
strategy:
type: RollingUpdate
template:
metadata:
labels:
app: __APP_NAME__
spec:
imagePullSecrets:
- name: wudimanong-ecr
containers:
- name: __APP_NAME__
image: __IMAGE__
resources:
requests:
memory: "1000M"
limits:
memory: "1000M"
volumeMounts:
- name: time-zone
mountPath: /etc/localtime
- name: java-logs
mountPath: /opt/logs
ports:
- containerPort: __PORT__
env:
- name: SPRING_PROFILES_ACTIVE
value: __PROFILE__
- name: JAVA_OPTS
value: -Xms1G -Xmx1G -Dapp.home=/opt/
volumes:
- name: time-zone
hostPath:
path: /etc/localtime
- name: java-logs
hostPath:
path: /data/app/deployment/logs
如果所有筹备得当,此时你向 GitLab 仓库提交代码将主动触发构建 Pipeline,而 Pipeline 将主动运行你在“.gitlab-ci.yml”文件中定义的具体 CI/CD 流水线逻辑,从而实现利用的自动化公布成果。
基于 GitLab-CI 机制的自动化公布零碎因为其构建形式比较简单,不须要太多的开发工作,因而目前不少守业公司中都采纳了此类计划来实现微服务的自动化构建和交付。