实施微服务架构后,原先单一的系统结构统变成了数量众多的微服务应用,开发、测试、运维部署等都会面临不少挑战。在微服务架构下如何提高工程研发效率,确保开发、测试、运维部署等流程上的顺畅,是微服务技术体系能够真正落地产生效益的关键。

要实现上述目标就需要基于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镜像的具体构建方式,是通过在标签中指定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机制的自动化发布系统由于其构建方式比较简单,不需要太多的开发工作,因此目前不少创业公司中都采用了此类方案来实现微服务的自动化构建和交付。

详解Kubernetes微服务自动化发布系统的更多相关文章

  1. 通过Dapr实现一个简单的基于.net的微服务电商系统(四)——一步一步教你如何撸Dapr之订阅发布

    之前的章节我们介绍了如何通过dapr发起一个服务调用,相信看过前几章的小伙伴已经对dapr有一个基本的了解了,今天我们来聊一聊dapr的另外一个功能--订阅发布 目录:一.通过Dapr实现一个简单的基 ...

  2. kubernetes 微服务西游记(持续更新中...)

    随着微服务架构的流行,迈向云原生的趋势,容器化微服务就成为了持续集成最好的手段,镜像成为了持续交付最好的产物,容器成为了镜像运行最好的环境,kubernetes成了部署容器最好的生态系统和规范.实践出 ...

  3. 通过Dapr实现一个简单的基于.net的微服务电商系统(三)——一步一步教你如何撸Dapr

    目录:一.通过Dapr实现一个简单的基于.net的微服务电商系统 二.通过Dapr实现一个简单的基于.net的微服务电商系统(二)--通讯框架讲解 三.通过Dapr实现一个简单的基于.net的微服务电 ...

  4. 通过Dapr实现一个简单的基于.net的微服务电商系统(十三)——istio+dapr构建多运行时服务网格之生产环境部署

    之前所有的演示都是在docker for windows上进行部署的,没有真正模拟生产环境,今天我们模拟真实环境在公有云上用linux操作如何实现istio+dapr+电商demo的部署. 目录:一. ...

  5. 通过Dapr实现一个简单的基于.net的微服务电商系统(二十)——Saga框架实现思路分享

    今天这篇博文的主要目的是分享一下我设计Saga的实现思路来抛砖引玉,其实Saga本身非常的类似于一个简单的工作流体系,相比工作流不一样的部分在于它没有工作流的复杂逻辑处理机制(比如会签),没有条件分支 ...

  6. 通过Dapr实现一个简单的基于.net的微服务电商系统

    本来想在Dpar 1.0GA时发布这篇文章,由于其他事情耽搁了放到现在.时下微服务和云原生技术如何如荼,微软也不甘示弱的和阿里一起适时推出了Dapr(https://dapr.io/),园子里关于da ...

  7. 通过Dapr实现一个简单的基于.net的微服务电商系统(八)——一步一步教你如何撸Dapr之链路追踪

    Dapr提供了一些开箱即用的分布式链路追踪解决方案,今天我们来讲一讲如何通过dapr的configuration来实现非侵入式链路追踪的 目录:一.通过Dapr实现一个简单的基于.net的微服务电商系 ...

  8. 通过Dapr实现一个简单的基于.net的微服务电商系统(九)——一步一步教你如何撸Dapr之OAuth2授权

    Oauth2授权,熟悉微信开发的同学对这个东西应该不陌生吧.当我们的应用系统需要集成第三方授权时一般都会做oauth集成,今天就来看看在Dapr的语境下我们如何仅通过配置无需修改应用程序的方式让第三方 ...

  9. 通过Dapr实现一个简单的基于.net的微服务电商系统(十)——一步一步教你如何撸Dapr之绑定

    如果说Actor是dapr有状态服务的内部体现的话,那绑定应该是dapr对serverless这部分的体现了.我们可以通过绑定极大的扩展应用的能力,甚至未来会成为serverless的基础.最开始接触 ...

随机推荐

  1. ASP.NET Core 配置与获取

    目录 1,来自字典 2,来自配置文件 3,层次结构 4,映射 ASP.NET Core 中,可以使用 ConfigurationBuilder 对象来构建. 主要分为三部:配置数据源 -> Co ...

  2. matplotlib | Python强大的作图工具,让你从此驾驭图表(二)

    今天是数据处理专题的第10篇文章,我们继续来聊聊matplot这个工具库. 在上周的文章当中我们介绍了matplot的基本用法,以及展示了一些简单的例子,让大家直观地了解这个工具包.我们可以简单地将它 ...

  3. ⏰ Moment.js 宣布停止开发,现在该用什么?

    本文整理自 Monent.js 官方英文公告 https://momentjs.com/docs/#/-project-status/ Moment.js 宣布停止开发,进入维护状态. 这是一个大而全 ...

  4. docker 部署 zabbix

    docker部署zabbix   我相信大家都已经会再物理机上跑zabbix并且监控了,那么有没有想过在docker中跑zabbix?下面咱们来看看如何在docker中搭建zabbix并且监控 部署环 ...

  5. Pandas 中的遍历与并行处理

    使用 pandas 处理数据时,遍历和并行处理是比较常见的操作了本文总结了几种不同样式的操作和并行处理方法. 1. 准备示例数据 import pandas as pd import numpy as ...

  6. 【答疑解惑】为什么你的 Charles 会抓包失败?

    作为一名 Web 开发工程师,天天都会和网络打交道.Charles 作为一款网络抓包工具,几乎成了 Web 开发的标配. 本文是我深度使用 Charles 后总结而成,不同于其它介绍 Charles ...

  7. leetcode1552题解【二分+贪心】

    leetcode1552.两球之间的磁力 题目链接 算法 二分+贪心 时间复杂度O(nlogn + nlogm) 1.根据题意描述,我们需要将m个球放入到n个篮子中,根据题目中数据范围描述发现m &l ...

  8. 刷题[BJDCTF 2nd]简单注入

    解题思路 打开发现登陆框,随机输入一些,发现有waf,然后回显都是同样的字符串.fuzz一波,发现禁了挺多东西的. select union 等 这里猜测是布尔盲注,错误的话显示的是:You konw ...

  9. 基于Scrapy的交互式漫画爬虫

    Github项目地址 前言 该项目始于个人兴趣,本意为给无代码经验的朋友做到能开箱即用 阅读此文需要少量Scrapy,PyQt 知识,全文仅分享交流 摘要思路,如需可阅读源码,欢迎提 issue 一. ...

  10. Markdown 1.0.1

    简介 Markdown 是由 John Gruber 于2004年开发一种轻量级标记语言,它是一个面向web作者的 text-to-HTML 转换工具.Markdown编辑器允许您使用纯文本格式编写, ...