一 背景
在目前微服务大行其道的背景下,Gitlab CI集成kubernetes已经是不可或缺的基本操作,我们前几节系统的实战了前后端项目以及物理/K8s混合环境部署,这节课我们来学习Gitlab CI如何将应用发布进K8s,我们都知道在之前的将gitlab-runner部署在服务器上面是存在一定的风险,如果运行pipeline的服务器宕机,发布任务就没办法继续了,更可怕的时候如果common-runner发送故障,多个发布任务就都有问题,在微服务架构中,不可变的基础设施,容器的自包含环境使得我们发布变得更加简单快捷,不用在考虑担心runner的环境如何根据不同的项目区分,且动态的Job触发,我们会随时拉起一个Pod来运行我们的Job,运行完成后又进行销毁,这样不仅能实现动态运行节省资源,而且可以不用考虑多项目多任务并发构建的问题,这节课就让我们来尽情享受K8s+Gitlab CI为我们带来畅快淋漓的发布体验。
二 架构解析
本文以构建一个Java软件项目并将其部署到阿里云容器服务Kubernetes集群中为例,说明如何使用GitLab CI在阿里云Kubernetes服务上运行GitLab Runner、配置Kubernetes类型的executor,并执行Pipeline。
2.1 Gitlab CI流程图
2.2 流程详解
如上图为一个简单的Gitlab CI部署进K8s流程图,同之前我们讲到的CI集成一致,只需要项目中存在.gitlab-ci.yml文件即可,与之前的差异为在集成kubernetes的时候,我们讲我们的gitlab-runner运行在我们K8s内,其为一个POD形式运行,其控制着后续的pipeline中各stage的执行,我们可以看到,当一个pipeline有多个stage,每个stage都是有一个单独的Pod去执行,这个Pod使用的镜像在我们CI的.gitlab-ci.yml 的每个stage的image中定义,如所示为一个部署Java项目的流程
开发者或项目维护者merge request到特定分支,改分支存在CI文件,开始进行CI
CI任务由已经注册在gitlab-server运行在K8s集群内的giitlab-runner进行下发
第一个为package,对java项目利用maven镜像进行打包,生成war包制品到缓存目录中;
利用docker镜像对根据项目中的Dockerfile对缓存中的制品进行镜像构建,构建完成后登录镜像仓库进行镜像推送;
在此我们利用将部署文件托管在项目内,也体现了gitops的思想,将之前构建推送成功的镜像地址信息在deployment.yaml文件进行修改,之后apply进k8s中,java项目构建的镜像就运行在K8s集群内了,完成整个的发布。
在流程中有一些注意事项:
我们可以在stage中添加自己业务需求的内容,例如单元测试,代码扫描等。
在部署文件中,我们可以将整个项目制作成helm的chart,替换其中的镜像,利用helm来进行整个应用的部署。
应用在部署中单个stage利用的是不同的image,在各个stage中传递已经生成的制品例如war/jar包,需要使用到外部存储来缓存制品。
三 优点
通过上面的Gitlab CI流程我们能够看到将gitlab runner运行在K8s集群中,每个Job启动单独的POD运行操作,此种方式完全利用起了K8s的一些优点
高可用:当某个节点出现故障时,Kubernetes 会自动创建一个新的 GitLab-Runner 容器,并挂载同样的 Runner 配置,使服务达到高可用。
弹性伸缩:触发式任务,合理使用资源,每次运行脚本任务时,Gitlab-Runner 会自动创建一个或多个新的临时 Runner来运行Job。
资源最大化利用:动态创建Pod运行Job,资源自动释放,而且 Kubernetes 会根据每个节点资源的使用情况,动态分配临时 Runner 到空闲的节点上创建,降低出现因某节点资源利用率高,还排队等待在该节点的情况。
扩展性好:当 Kubernetes 集群的资源严重不足而导致临时 Runner 排队等待时,可以很容易的添加一个 Kubernetes Node 到集群中,从而实现横向扩展。
如果您的业务目前运行环境为K8s,那么Gitlab CI完全契合您的业务场景,您只需要自定义gitlab-ci.yml中的各个自己需求的stage即可,配合gitops将配置也托管在项目内,跟随项目一块维护管理,实现端到端的CI工作流,使得运维工作也可通过git追溯,提高工作效能,敏捷开发上线部署。
四 实战
我们在上面了解来Gitlab CI与Kubernetes的集成及其优点,下面就让我们通过实战来更具体的了解其流程。
4.1 环境准备
需要有Gitlab 服务器,可以是部署在物理服务器上,当然也可以部署在K8s集群内部。
我需要准备好K8s集群,可以为公有云的容器编排引擎,例如阿里的ACK,腾讯的TKE,华为的CCE等都适用这些方式。
由于gitlab-runner安装较为复杂,我们在示例中使用helm来进行安装,helm版本为v2.14.3,如果有能力可以自己编写资源清单部署。
4.1.1 记录注册信息
登录Gitlab 服务器记录gitlab 的 url 和注册令牌,在我们部署进K8s的gitlab-runnner的配置中需要填写该信息,运行在K8s中的Pod就利用此此信息在gitlab服务器进行注册。
4.1.2 获取gitlab-runner
由于单独部署gitlab-runner进K8s中,自己去写资源清单文件难度较大,而且容易出错,我们在此利用官方的chart镜像通过helm来进行部署,仅修改其中我们关系的字段即可,首先在登录K8s集群进行gitlab-runner的helm repo的添加,之后将chart下载到本地,解压文件并修改其中的values.yml文件。
添加repo获取charts
[root@master common-service]# helm repo add gitlab https://charts.gitlab.io
"gitlab" has been added to your repositories
[root@master common-service]# helm repo update
Hang tight while we grab the latest from your chart repositories...
...Skip local chart repository
...Successfully got an update from the "aliyun" chart repository
...Successfully got an update from the "apphub" chart repository
...Successfully got an update from the "gitlab" chart repository
...Successfully got an update from the "stable" chart repository
Update Complete.
[root@master common-service]# helm search gitlab-runner
NAME CHART VERSION APP VERSION DESCRIPTION
gitlab/gitlab-runner 0.14.0 12.8.0 GitLab Runner
我看已经看到了 gitlab-runner的chart,其是 helm 中描述相关的一组 Kubernetes 资源的文件集合,里面包含了一个 value.yaml 配置文件和一系列模板(deployment.yaml、svc.yaml 等)。当然如果我们能力够,可以自己去编写这些资源清单文件。
在此有想去的伙伴可以查看之前K8s学习笔记,希望能对读者学习K8s有帮助:awesome-kubernetes-notes
创建角色并绑定权限
gitlab-runner在运行的时候需要访问我们K8s的api,我们在此为期创建ServiceAccount并为其进行RBAC授权,首先创建一个gitlab-runners的名称空间,并创建对用的Role,将ServiceAccount于Role进行绑定。
[root@master gitlab-runner]# cat > rbac-runner-config.yaml <<EOF
apiVersion: v1
kind: ServiceAccount # 在gitlab-runners名称空间下创建名为gitlab的serviceaccount
metadata:
name: gitlab
namespace: gitlab-runners
kind: Role # 创建gitlab角色,
apiVersion: rbac.authorization.k8s.io/v1
metadata:
namespace: gitlab-runners
name: gitlab
rules:
- apiGroups: [""] #"" indicates the core API group
resources: ["*"]
verbs: ["*"] - apiGroups: ["apps"]
resources: ["deployments"]
verbs: ["*"] - apiGroups: ["extensions"]
resources: ["deployments"]
verbs: ["*"]
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: gitlab # 将sa与角色进行绑定
namespace: gitlab-runners
subjects:
- kind: ServiceAccount
name: gitlab # Name is case sensitive
apiGroup: ""
roleRef:
kind: Role #this must be Role or ClusterRole
name: gitlab # this must match the name of the Role or ClusterRole you wish to bind to
apiGroup: rbac.authorization.k8s.io
EOF
创建资源清单
[root@master gitlab-runner]# kubectl create -f rbac-runner-config.yaml
serviceaccount/gitlab created
role.rbac.authorization.k8s.io/gitlab created
rolebinding.rbac.authorization.k8s.io/gitlab created
获取charts文件,并进行配置
[root@master gitlab-runner]# helm fetch gitlab/gitlab-runner
[root@master gitlab-runner]# tar xf gitlab-runner-0.14.0.tgz
[root@master gitlab-runner]# vim gitlab-runner/values.yaml
helm为我们提供了一个配置文件可以在安装 runner 的时候为其注册一个默认的 runner。我们可以去 gitlab-runner 的项目源码 中获取到 values.yaml 这个配置文件。