Gitlab的CICD
devops已经成为了主流,绝大多数的devops架构都是基于gitlab+jenkins+harbor+k8s去做的,在这套东西中我们需要维护的东西很多,甚至编译环境也需要我们自己维护。实际上,gitlab已经集成了完整的cicd功能,我们可以使用gitlab轻松地进行cicd。
1、基本环境
禁用gitlab自带的nginx并使用nginx对gitlab进行反向代理。
操作系统 | 内网地址 | 基础环境 | 用途 |
---|---|---|---|
ubuntu20.04-server | 192.168.31.200 | 无 | 部署gitlab、nginx |
ubuntu20.04-server | 192.168.31.201 | kubernetes | 部署gitlab-runner |
ubuntu20.04-server | 192.168.31.202 | kubernetes | 部署gitlab-runner |
ubuntu20.04-server | 192.168.31.203 | kubernetes | 部署gitlab-runner |
2、环境部署
2.1、安装gitlab
安装方法参照 Gitlab官方ubuntu部署文档
sudo apt-get update
sudo apt-get install -y curl openssh-server ca-certificates tzdata perl postfix
curl https://packages.gitlab.com/install/repositories/gitlab/gitlab-ee/script.deb.sh | sudo bash
sudo EXTERNAL_URL="https://gitlab.linhf.cn" apt-get install gitlab-ee
# 注意:EXTERNAL_URL为访问gitlab的域名或地址,如:https://gitlab.linhf.cn,如果后期需要修改可以更改/etc/gitlab/gitlab.rb的external_url。
默认的管理员用户名为root,初始密码在gitlab安装完成后可在/etc/gitlab/initial_root_password文件中找到。
2.1、配置gitlab-registry
gitlab-registry是gitlab内置的镜像仓库,默认情况下此功能是关闭的,我们需要修改配置文件将其开启。
sudo vim /etc/gitlab/gitlab.rb
# 禁用自带的nginx
nginx['enable'] = false
# 访问的域名
registry_external_url 'https://registry.gitlab.linhf.cn'
# 启用registry
gitlab_rails['registry_enabled'] = true
# registry实际的api地址(nginx反向代理到这里)
gitlab_rails['registry_api_url'] = "http://127.0.0.1:5000"
# registry监听地址
registry['registry_http_addr'] = "0.0.0.0:5000"
sudo gitlab-ctl reconfigure
完成配置后我们可以在仓库目录下的[软件包与镜像库>容器镜像库]中看到当前的容器镜像,如图。
注意
默认情况下gitlab-registry使用http协议的,我们需要在docker中添加私人仓库配置才可使用; 如果需要使用gitlab自带的nginx可参考
gitlab内置nginx配置
。
2.2、安装配置gitlab-runner
gitlab-runner是一个用来构建项目的组件,类似jenkins但又不同于jenkins,它可以与gitlab深度整合并可以进行分布式构建。gitlab-runner有多种配置模式,例如host、docker和kubernetes等,由于gitlab-runner支持在容器中运行并且是作为一个组件,所以他能更加容易保存构建环境的一致性并且轻量。
在kubernetes环境下我们可以借助helm快速配置安装gitlab-runner。
# 列出所有gitlab-runner版本
helm search repo -l gitlab/gitlab-runner
# 选择一个版本,这里的version是chart的version
helm pull gitlab/gitlab-runner --version 0.49.2
# 解压pull下来的文件
tar -xf gitlab-runner-0.49.2.tgz
编辑values.yaml:
gitlabUrl: http://gitlab.your-domain.com/
# runnerRegistrationToken可以在管理员账户下的 设置->CI/CD->Runner 中找到
runnerRegistrationToken: "xxxx"
# 如果需要自定义编译环境,可以更换runner的运行镜像,比如我需要编译golang,可以换成golang
runners:
config: |
[[runners]]
[runners.kubernetes]
image = "golang:1.19"
# 为这个runner指定tag,编译时可在配置文件中指定用哪个runner执行
tags: "k8s,golang"
执行helm安装,就可以在gitlab的runner管理上看到相应的gitlab-runner。
helm install gitlab-runner gitlab-runner/ -n {{namespace}}
其他的安装配置可以参考 gitlab-runner安装文档 。
3、cicd配置编写
在项目的根目录新建一个 .gitlab-ci.yml 文件,这个文件的名字可以在项目的
设置->CI/CD->流水线通用设置->CI/CD->配置文件
中自定义名称。下面是一个ci/cd配置的例子,具体可以查看
gitlabCICD配置文档
# include: 引入某个文件,类似go的import
#include:
# local: /ctyun-dev/ci.yml
# remote: https://xxx.com/ci.yml
stages:
- build
- deploy
# 变量,可在构建过程中获取的,key:value
variables:
GOPROXY: https://goproxy.io
RULE_TYPE: "other"
## 全局缓存,与阶段缓存一致
#cache:
## 注意:only和except官方不建议使用,推荐使用rules,rules不能与only、except组合使用
build-job-only-main:
stage: build
script:
- echo "这个输出表明执行构建的是main分支"
# only,定义在哪些分支和标签中执行
only:
- ctyun-main
# # need:某一步骤执行了这个步骤才能执行
# needs:
build-job-except-main:
stage: build
script:
- echo "这个输出表明执行构建的不是main分支"
# only,定义在哪些分支和标签中不会被执行
except:
- ctyun-main
build-job-rules:
stage: build
script:
- echo "这个输出表明执行构建是由rules触发的"
# if:规则逻辑,类似编程语言的if-else,注意,此处有坑:if记得加冒号,记得加单引号
# when:代表执行时机(manual-手动、delayed-延迟n秒、on_success-马上、on_failure-失败时),start_in: 代表延迟执行
# change:当文件发生变化时触发
# exists:文件存在时
rules:
- if: '$RULE_TYPE == "manual"'
when: manual
- if: '$RULE_TYPE == "delay"'
when: delayed
start_in: '5'
- when: on_success
build-bin:
# 阶段名称
stage: build
# # 阶段缓存,仅此阶段,如果是nodejs项目有node_modules时可以启用
# cache:
# # 缓存的key,防止被覆盖,每个key会独立分配一个缓存空间
# key: build
# # 缓存路径
# paths:
# - node_modules
# 执行的脚本
script:
- echo "Compiling the code..."
- export GOPROXY="$GOPROXY"
- go mod tidy
- go build -o bin/http_server http_server/main.go
- echo "Compile complete."
# 制品配置,构建出的文件收集
artifacts:
# 制品名称 $CI_JOB_NAME-阶段名称 $CI_COMMIT_REF_NAME-分支名称
name: "$CI_JOB_NAME-$CI_COMMIT_REF_NAME"
# 目标文件路径
paths:
- bin/http_server
# 何时收集:on_success-成功时,always-总是,on_failure-失败时
when: on_success
# 过期时间,到期自动清理
expire_in: 365 days
# gitlab-runner的tag
tags:
- k8s
- golang
build-image:
# 阶段名称
stage: build
script:
- echo "Start to image build......"
- img build -t gitlab.linhf.cn/experiment/get-started:http-server-0.0.1 .
- echo "Compile image build."
tags:
- k8s
- img
deploy-job:
stage: deploy
environment: prod
script:
- echo "Deploying application..."
- "这里可以使用kubectl进行此应用的发布"
- echo "Application successfully deployed."
- k8s
- kubectl
使用img在容器中打包镜像
在虚拟机环境中一般都是用docker打包镜像,我们也可以通过容器调用虚拟机中的docker打包镜像,但是这就可能会造成额外的负担,比如确保环境的一致性。而使用docker-in-docker就相当于在容器中再运行一个docker,比较笨拙。
genuinetools/img 是一个无容器依赖的镜像打包工具,我们只需要在配置runner的运行镜像的时候使用img的docker镜像,由于img打包镜像的时候可能会读写容器中的/tmp目录,所以要配置 runners.kubernetes.pod_annotations 以增加权限。
runners:
config: |
[[runners]]
[runners.kubernetes]
image = "r.j3ss.co/img:v0.5.9"
[runners.kubernetes.pod_annotations]
"container.apparmor.security.beta.kubernetes.io/build" = "unconfined"
"container.seccomp.security.alpha.kubernetes.io/build" = "unconfined"
我们在配置 .gitlab-cicd.yml 的时候,使用img代替docker即可,如: “img build xxx”、“img push xxx” 等。
在cicd中使用环境变量
无论是使用gitlab-registry还是使用harbor的时候,都需要进行登录,如果将登录的账号密码直接写在配置文件中是非常不安全的,我们可以借助gitlab的环境变量对敏感数据进行存储,这个环境变量分为全局和项目的,我们以项目的为例。
在项目中找到
设置->CICD->变量
可以看到环境变量的设置,我们可以添加一个环境变量,在使用的时候我们可以直接使用
$XXX
即可。全局环境变量与项目环境变量一样,只不过全局环境变量在gitlab的全局设置中的CI/CD中。
build-image:
stage: build
script:
- echo "Start to image build......"
- img login $CI_REGISTRY_URL -u $PROJECT_CI_USERNAME -p $PROJECT_CI_PASSWORD
- img build -t registry.gitlab.linhf.cn/experiment/get-started:http-server-"$VERSION" .
- img push registry.gitlab.linhf.cn/experiment/get-started:http-server-"$VERSION"