您可以捐助,支持我们的公益事业。

1元 10元 50元





认证码:  验证码,看不清楚?请点击刷新验证码 必填



  求知 文章 文库 Lib 视频 iPerson 课程 认证 咨询 工具 讲座 Model Center   Code  
会员   
   
 
     
   
 订阅
  捐助
落地微服务特色的 DevOps 管道,持续集成/部署到 Kubernetes
 
作者:DevOps时代
   次浏览      
 2020-5-28 
 
编辑推荐:
文章主要介绍了如何搭建一条成熟稳定、且符合微服务特色的高度自动化DevOps管道,希望对您的学习有所帮助。
本文来自于云社区,由火龙果软件Alice编辑推荐。

前言

2018年既是微服务架构火爆的一年,也是容器和Kubernetes收获赞誉盆满钵满的一年;在kubernetes的引领下,以容器为中心部署微服务已成为一种事实标准,并不断加速着微服务架构模式落地,持续地发挥着它的魔力。

企业,特别是互联网公司,为了快速响应前端用户的需求,缩短产品从需求到交付的周期,常常需要快速地、细腻度地迭代产品,以抢占市场先机;在微服务模式下,可以很好地满足这个要求,只发布变化的服务,从而最小化单次迭代的风险,实现敏捷开发和部署。

当采用微服务模式后,整个业务流程将被垂直拆分成多个小单元;每个小单元都是一个独立开发、独立部署和独立扩展的微处理服务,这样的灵活性非常适合敏捷开发模式,但也给开发和运维带来了固有的复杂性和难度。

对于开发者而言,由于微服务应用整体作为一个分布式系统提供服务,需要选择合适服务通讯协议,并处理潜在的网络分化瞬时故障等情况,除此之外,还需要建设服务发现、配置中心等基础设施;

对于运维人员,需要利用容器的可移植性,持续地集成和部署微服务到不同的集群环境,这些都要求运维人员具有非常全面的能力,比如:熟悉容器及k8s、能编写Linux Shell运维脚本、熟练一种持续集成部署工具(比如:gitlab、jenkins)等。

综上所述,如何搭建一条成熟稳定、且符合微服务特色的高度自动化DevOps管道又成为了另一个难题。

目标

以最小的学习成本,搭建一条成熟稳定、且符合微服务特色的高度自动化DevOps管道,按需地持续集成/部署微服务到kubernetes。

工具 - 最小的学习成本

kubernetes + gitlab + shell

方案 - 愿景

1. 持续集成 - CI

在kubernetes的master节点部署gitlab-runner,充当gitlab服务器的客户端;当提交或合并代码到指定的分支时,gitlab-runner自动从gitlab拉取代码,利用master主机提供的边缘计算能力来执行已编排好的DevOps CI管道=》编译代码、运行单元和集成测试、容器化微服务成镜像,最后上传到企业镜像仓库,这就是持续集成流程,该阶段交付的产物为镜像。

2. 持续部署 - CD

在kubernetes的master节点部署gitlab-runner,充当gitlab服务器的客户端,当持续集成阶段交付了新版本的镜像后,从企业镜像仓库拉取最新版本的镜像,利用master主机提供的边缘计算能力执行已编排好的DevOps CD管道=》同步服务配置信息到配置中心(k8s的ConfigMap),并滚动更新kubernetes集群镜像版本。

部署环境

安装目录:/root/gitrunner

工作目录:/home/devops/gitrunner

mkdir -p /root/gitrunner && mkdir -p /home/devops/gitrunner;

1. 部署gitlab-runner

在kubernetes的master节点部署gitlab-runner,命令如下:

> wget -O /root/gitrunner/gitlab-runner https://gitlab-runner-downloads.s3.amazonaws.com/latest/binaries/gitlab-runner-linux-amd64;
> cd /root/gitrunner;
> chmod +x gitlab-runner;
> # 注意:建议使用root用户进行安装,以避免不必要的权限问题。
> ./gitlab-runner install --user=root --working-directory=/home/devops/gitrunner;
> ./gitlab-runner start;

2. 注册gitlab-runner

gitlab支持注册两种类型的runner:

1.Specific Runners

这是隶属于特定项目的专有工人,不接受其他项目调遣。

2. Shared Runners

这是隶属于gitlab-server的工人,可以共享给所有的项目调遣。

这两种Runner各有千秋,如果为每一个项目都注册专用Runner,会显得比较繁琐和多余,而使用共享Runner就很省事,但是一个工人一次只能做一件事情,当同时调遣一个工人时,那么就会出现竞争等待,故大家还是实际情况来注册工人吧,只要不延误工期就行,嘿嘿。

注册runner

在开发、预生产、生产环境注册Runner,并贴上标签:build、staging、prod。

备注:后面搭建 DevOps 管道时,将根据标签来调遣工人。

步骤

1. 获取项目地址和注册token,依次查找路径:Settings => CI / CD => Runners settings,如下:

2.注册:

> cd /root/gitrunner;
> ./gitlab-runner register
> # 回车,根据提示填写项目地址、注册Token、标签、执行器
> # 假如,项目地址为:http://gitlab.justmine.cn:8002/, 项目注册token为:6iS4GBCh18NR4GPoMyef。
> ## 以开发环境为例(仅供参考)
> Please enter the gitlab-ci coordinator URL (e.g. https://gitlab.com/):
http://gitlab.justmine.cn:8002/
> Please enter the gitlab-ci token for this runner:
6iS4GBCh18NR4GPoMyef
> Please enter the gitlab-ci description for this runner:
[justmine.com]: development environment
> Please enter the gitlab-ci tags for this runner (comma separated):
build
> Registering runner... succeeded runner=4iS4GwCh
> Please enter the executor: ssh, docker+machine, kubernetes, virtualbox, docker-ssh+machine, docker, docker-ssh, parallels, shell:
shell
> Runner registered successfully. Feel free to start it, but if it's running already the config should be automatically reloaded!
> # 其他环境同理

 

搭建DevOps管道 - PipeLines

上面的方案仅仅描述了愿景,也就是期望达成目标的最后结果,但对于如何落地一条真正的管道而言,还是显得非常的空洞。其实这正是DevOps的难点,大体流程上都晓得有个持续集成、持续部署,讲起来如数家珍,落地时都之乎者也。

同样,秉承微服务的思想,分而治之,我们将管道分为两个部分:创建、更新,即先创建一个主板次,然后再基于此主板次进行小版本迭代,不断地扩展新功能。通过这样有效的拆分,是不是就不那么的空洞了,就像领域驱动设计的CQRS模式一样,区别地对待读写,从而大大地减少了阻抗,也非常地切合产品的创新迭代,比如将需求拆分为3期,每一期都对应一个主版次,然后再小版本迭代每一期的需求,完成一期,封板一期,彼此隔离,互补影响,同时也方便追溯。

理清了整个管道的脉络,现在就需要思考一些实际问题了,比如:

如何将持续集成/部署微服务流程脚本化,即如何实现基础设施代码化?

如何动态解析git当前变化日志,实现准确地按需发布微服务?

如何保留现场,并以最小的成本重试管道?

在不修改管道脚本的情况下,如何手工控制按需发布、自动伸缩和回滚微服务?

如何兼容新增的微服务?

如何快速调试整个管道脚本?

只有把上面的问题都处理了,才算是一条成熟可用的、企业级别的CI/CD管道,才符合高度自动化、稳定、快速、容错等特点;在互联网公司,可能一天要提交好几个版本到不同的环境,不能因为考虑不周而影响连续部署的进度,管道一旦投入使用就需要对修改闭合,只对扩展开放。

只有把上面的问题都处理了,才算是一条成熟可用的、企业级别的CI/CD管道,才符合高度自动化、稳定、快速、容错等特点;在互联网公司,可能一天要提交好几个版本到不同的环境,不能因为考虑不周而影响连续部署的进度,管道一旦投入使用就需要对修改闭合,只对扩展开放。

管道一览图:

为了验证管道的特性,我特意做了以下测试:

1. 创建环境 - 发布主板本

这是一个从0到1、从无到有的过程,这里一小步,却是落地DevOps管道的一大步。

版本迭代的第一步就是创建微服务集群环境,那么如何快捷地创建这个环境呢?我将使用kubernetes的包管理器helm来完成这个任务,可能很多同学都没用过这个工具,平时部署组件都是手工编写好yaml资源部署文件,虽然这种方式方便快捷,但是对于大量组件,以及需要实现基础设施代码化的场景,手工处理这种方式就不能满足需求了。

模板文件请参考示例项目,下面是创建环境的脚本化命令:

helm install /root/AutoDevOpsPipeLinesCharts \
--name=${releaseName} \
--set environment.upper=${Environment} \
--set environment.lower=${environment} \
--set namespace=${namespace} \
--set image.registryhost=${RegistryHost} \
--set image.username=${registryUserName} \
--set image.version=${version} \
--set replicas=${replicas}

从上面可以看出,实现部署服务脚本化的目的已经达到了。

下面我们在来看看如何脚本化整个创建环境管道线:

# 001 Continuous integration image to registry.
bash ./devops/PipeLines/Creation/001_CI.sh .
# 002 Create config information to k8s's configmap.
bash ./devops/PipeLines/Creation/002_CreateConfig.sh

.
# 003 Release major to k8s's cluster.
bash ./devops/PipeLines/Creation/003_ReleaseMajor.sh

.
# 004 Create gateway route.
bash ./devops/PipeLines/Creation/Gateways/Kong/
004_CreateGatewayRoute.sh

备注:管道线脚本请参考示例项目(AspnetCore):MicroService.AutoDevOpsPipeLines/devops/PipeLines/Creation。

1.1、测试

将刚刚创建的helm模板文件上传到gitlab-runner所在服务器的/root目录下,并添加配置,如下:

<Project>
<PropertyGroup>
<Major>1</Major>
<Minor>0</Minor>
<Patch>0</Patch>
</PropertyGroup>
</Project>

然后合并代码到分支release/staging,如下:

从上面可以,第一个主板次(1.0.0)已经成功发布到预生产环境。

肪惩恚谠ど肪撑芡旮髦植馐院螅喜⒋氲椒种elease/production即可。

2. 滚动更新 - 迭代小版本

这个阶段将模拟在第一个主板次(1.0.0)上进行小版本迭代需求,距离上次发布已经一周了,开发部门也完成了第一个小版本的开发工作,现在需要发布版本1.0.1到预生产环境进行测试,首先修改文件version.props,如下:

<Project>
<PropertyGroup>
<Major>1</Major>
<Minor>0</Minor>
<Patch>1</Patch>
</PropertyGroup>
</Project>

除了发布本次需求修改的两个微服务:Identity.API、Marketing.API以外,还需强制发布微服务Basket.API,添加配置,在gitlab仓库依次查找 (Settings => CI/CD => Secret variables),如下:

最后合并代码到分支staging。

先来看看是否正确解析git变更日志和全局变量,准确地实现自动化和手工控制:

再来看看整个管道的执行情况:

最后看一下预生产环境的效果

3. 自动伸缩

3.1、伸缩单个微服务

经过一段时间的观察发现预生产环境的购物车(Basket.API)微服务吞吐量颇高,故决定扩容它的实例数量到2个,首先修改项目属性文件deploy.props,如下:

<Replicas>2</Replicas>

然后添加配置,如下:

最后合并代码到分支scaling/staging,如下:

3.2、伸缩所有微服务

同理,首先修改项目属性文件deploy.props,如下:

<Replicas>2</Replicas>

然后添加配置,如下:

从上面测试看到,只需要修改配置,就可以支持不同粒度地伸缩微服务,也不用修改CI/CD管道脚本。

4. 回滚

4.1、回滚单个微服务

经过一段时间的观察,发现刚刚发布到预生产环境的版本1.0.1有问题,故决定回滚到上一个版次1.0.0,首先修改项目属性文件deploy.props,如下:

<!--回滚步长-->
<RollBackStep>1</RollBackStep>

然后添加配置(只回滚购物车微服务),如下:

最后合并代码到分支rollback/staging,如下:

4.2、回滚所有微服务

同理,首先修改项目属性文件deploy.props,如下:

<!--回滚步长-->
<RollBackStep>1</RollBackStep>

然后添加配置回滚所有微服务,如下:

最后合并代码到分支rollback/staging,或者直接重试管道的roll-back阶段,如下:

5. 可扩展性 - 兼容新增微服务

5.1、添加新的搜索微服务

经过一段时间的迭代,一期已经完工,二期新增了搜索微服务,这时修改helm模板文件支持部署搜索微服务,然后合并代码到release/staging,测试如下:

k8s

网关路由

从上面可以看到,新增的搜索微服务已经成功发布到第二个主版次了。除了修改helm模板文件以外,整个过程并没有修改CI/CD管道脚本,圆满完成了兼容新增微服务的特性。

备注:我们可以将helm模板看成服务编排文件。

运维说明

1、分支

1、build

构建和编译代码。

2、release/staging

创建预生产环境。

3、staging

滚动更新预生产环境。

4、release/production

创建生产环境。

5、master

滚动更新生产环境。

6、scaling/staging

伸缩预生产环境

7、scaling/production

伸缩生产环境

8、rollback/staging

回滚预生产环境

9、rollback/production

回滚生产环境

2、配置文件

应用程序配置 - app.props

<!-- k8s命名空间前缀,比如:microservice
-autodevopspipeline-v1 -->
<NameSpace>microservice-autodevopspipeline</NameSpace>
<!-- 应用程序名称,主要用于Tips -->
<AppName>MicroService.AutoDevOpsPipeLine</AppName>
<!-- 解决方案名称,用于生成项目 -->
<SolutionName>MicroService.AutoDevOpsPipeLines.sln
</SolutionName>

版本配置 - version.props

<!-- 主板次,不兼容升级 -->
<Major>1</Major>
<!-- 次板次,兼容升级 -->
<Minor>0</Minor>
<!-- 补丁版次,静默修复接口 -->
<Patch>1</Patch>

部署配置 - deploy.props

<!-- Auto-scaling 实例数量 -->
<Replicas>1</Replicas>
<!-- Rollback 步长 -->
<RollBackStep>1</RollBackStep>
<!-- 镜像仓库用户名 -->
<ImageUserName>devopspipelines</ImageUserName>

特定环境配置,如:deploy.staging.props

<!-- 镜像仓库主机域名 -->
<RegistryHost>registry.staging.com:8100</RegistryHost>
<!-- k8s restful地址 -->
<K8sApiServer>https://192.168.2.110:6443</K8sApiServer>
<!-- k8s 接口访问令牌 -->
<AccessToken>utyeyerye.ytryeryeryyyyyyr.jhddghdhdhdhd<
/AccessToken>
<!-- kong restful地址 -->
<KongApiServer>http://192.168.2.110:81</KongApiServer>
<!-- kong 域名绑定 -->
<KongRouteDomain>staging.devops.com</KongRouteDomain>

分支环境配置 - branch.env.props

<!-- 解耦,目前用于滚动更新 -->
<!-- key: branch name(last keyword), value: environment -->
<staging>Staging</staging>
<master>Production</master>

总结

上面的测试几乎涵盖了结合k8s管理应用生命周期的所有流程(部署、伸缩、回滚、发布),大家可以放心地运用或者扩展这个管道到自己的微服务项目中,比如:目前仅支持自动创建路由到kong网关,建议大家fork项目后,自行扩展,测试完成后,也可以提取PR。如果你采用示例一样的项目结构,只需要修改配置信息,然后开箱即用。

   
次浏览       
相关文章

DevOps转型融入到企业文化
DevOps 能力模型、演进及案例剖析
基于 DevOps 理念的私有 PaaS 平台实践
微软开发团队的DevOps实践启示
相关文档

DevOps驱动应用运维变革与创新
运维管理规划
如何实现企业应用部署自动化
运维自动化实践之路
相关课程

自动化运维工具(基于DevOps)
互联网运维与DevOps
MySQL性能优化及运维培训
IT系统运维管理
最新活动计划
Node+Vue3.0前端全栈开发 7-5 [特惠]
Spring Cloud微服务架构 7-5[特惠]
SysML和EA系统设计与建模 7-26[特惠]
Python、数据分析与机器学习 8-23[特惠]
嵌入式软件架构设计 8-22[线上]
Linux内核编程及设备驱动 7-25[北京]
 
最新文章
DevOps 道法术器,立体化实施框架
DevOps 中高效测试基础架构的最佳实践
DevOps 在公司项目中的实践落地
如何基于 Kubernetes 构建完整的 DevOps 流水线
阿里云Kubernetes实战
最新课程
DevOps体系实践、工具与平台
基于Kubernetes的DevOps实践
互联网运维与DevOps
基于Kubernetes构建企业容器云
企业级DevOps工作体系与平台
更多...   
成功案例
北京 DevOps体系实践、工具与平台
神龙汽车 DevOps体系实践、工具与平台
中国移动通信 网络规划与管理
某航空公司 IT规划与企业架构
某金融公司 IT服务管理(ITIL V3)
更多...