工作了5年多,期间接触了一些CI工具。谈一谈我对这些工具的使用感受。
首先,有了这些工具使我聚焦开发本身,不用做重复的动作(如编译、打包、发布、测试等),节省了很大的开销。
Jenkins
最早接触的CI工具算是Jenkins了,Jenkins给我最深的印象就是需要安装很多插件。而工作场景是离线内网的,所以有时候很痛苦,尽管有代理可以使用,但速度也很感人。
初用jenkins配置ci流程的方式是web节点配置,没有使用Jenkinsfile。但随着越来越多的项目需要配置CI流程,这样的工作变得重复且没有价值。
因此我开始使用Jenkinsfile定义CI流程,刚开始用的时候其实很痛苦,有些配置写不出来,只能网上冲浪,找一些样例。
Jenkinsfile
样例
pipeline {
agent any
tools {
go 'go'
}
environment {
K8S_BASE_PATH="/ceph/download/deploy/soft/k8s/v1.18.6"
}
stages {
stage ('checkout scm') {
steps {
checkout(scm)
}
}
stage ('build k8s...') {
steps {
sh '''
alias sudo='sudo env PATH=$PATH'
chmod +x -R hack
sudo make WHAT=cmd/kubeadm
sudo mv _output/bin/kubeadm $K8S_BASE_PATH
'''
}
}
}
}
Jenkinsfile
的方式个人感觉更好,原因就是它将CI的流程完整的声明出来了,并存储于版本库(git)内,使CI本身具备了版本管理的能力。
但是就个人而言,Jenkinsfile的groovy语法实在不是很喜欢,相较而言还是更喜欢yaml语法
gitlab-ci
去年年初接触到了GitOps概念(以前都是鼓吹DevOps),进而了解了Gitlab拥有原生的ci工具gitlab-runnner。
在试用一段时间后,爱不释手,遂将所有与Jenkins集成的项目切换到了Gitlab-CI上。
为什么这么推崇gitlab-ci?
首先,他足够简单,搭建一个gitlba-runner后注册下就可以用了,gitlab-runner可以是shell类型的,也可以是docker类型的。并且可以基于gitlab的组注册gitlab-runner,使整个组共享该CI执行器。
其次,是其yaml语言更符合个人习惯。
还有比较重要的一点就是,在整个构建过程中可以切换gitlab-runner,这点非常的吸引我。如此一来构建流程更为灵活。并且可以将重要的凭据存放于gitlab的变量中。
让我们感受下Gitlab-ci配置的魅力
variables:
CI_REGISTRY_PROJECT: paas
CI_IMAGE_TAG: "ks-cleaner"
BUILD_IMAGE_TAG: $CI_REGISTRY/$CI_REGISTRY_PROJECT/$CI_IMAGE_TAG
stages:
- build
- push
- clean
- package
- trigger-next-builder
build:
stage: build
script:
- mkdir -p ~/.docker
- echo "{\"auths\":{\"$CI_REGISTRY\":{\"auth\":\"$(echo -n ${CI_REGISTRY_USER}:${CI_REGISTRY_PASSWORD} | base64)\"}}}" > ~/.docker/config.json
- docker build -f Dockerfile -t $BUILD_IMAGE_TAG .
tags:
- runner-vm
push:
stage: push
script:
- docker push $BUILD_IMAGE_TAG
tags:
- runner-vm
clean:
stage: clean
script:
- docker rmi -f $BUILD_IMAGE_TAG
tags:
- runner-vm
package:
stage: package
image:
name: harbor.chs.neusoft.com/build/helm:latest
before_script:
- mkdir -p ~/.config/helm
- echo "" > /etc/resolv.conf
- echo "$CI_REGISTRY_ADDRESS $CI_REGISTRY_DOMAIN" >> /etc/hosts
script:
- cd charts
- helm repo add harbor $CI_CHART_REGISTRY --username $CI_REGISTRY_USER --password $CI_REGISTRY_PASSWORD
- helm package ks-cleaner
- helmpush ks-cleaner-0.1.0.tgz harbor
tags:
- runner-docker
trigger-next-builder:
stage: trigger-next-builder
trigger:
project: deploy/harbor-installer
github Action
对我冲击最大的CI工具算是github Action
了,足够简单。
语法与gitlab-ci相似,可选插件较多(个人开发),比如自动release。
这里以我维护的weiliang-ms/easyctl: 基于golang运维工具集 (github.com) 所使用的action为例
- 单元测试流程
当代码提交至master分支,触发单元测试流程,并生成对应的单元测试覆盖率
name: Test
on:
push:
branches: [ master ]
pull_request:
branches: [ master ]
jobs:
go-test:
runs-on: ubuntu-latest
steps:
- name: Set up Go 1.16
uses: actions/setup-go@v1
with:
go-version: 1.16
- uses: actions/checkout@master
- run: go get -t -v ./...
- run: go test $(go list ./...|grep -v mocks) -race -coverprofile=coverage.txt -covermode=atomic -v
- uses: codecov/codecov-action@v2
with:
token: ${{ secrets.CODECOV_TOKEN }} # not required for public repos
files: coverage.txt # optional
flags: unittests # optional
name: codecov-umbrella # optional
fail_ci_if_error: true # optional (default = false)
verbose: true # optional (default = false)
- release流程
tag push事件触发后,将打包编译工程,并发布release制品
name: Tag
on:
push:
tags:
- 'v*'
jobs:
create-release:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Create Release # 创建Release,可以在仓库看到一个个版本
env:
GITHUB_TOKEN: ${{ secrets.EASYCTL_PUBLISH_TOKEN }}
id: create_release
uses: actions/create-release@master
with:
tag_name: ${{ github.ref }} # (tag)标签名称
release_name: Release ${{ github.ref }}
draft: false # 是否是草稿
prerelease: false # 是否是预发布
releases-matrix:
name: Release Go Binary
runs-on: ubuntu-latest
strategy:
matrix:
# build and publish in parallel: linux/386, linux/amd64, windows/386, windows/amd64, darwin/amd64
# goos: [linux, windows, darwin]
goos: [ linux ]
goarch: [ "386", amd64 ]
exclude:
- goarch: "386"
# goos: darwin
steps:
- uses: actions/checkout@v2
- run: sudo ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
- name: get date
id: current_time
run: echo "::set-output name=date::$(date +%Y-%m-%d-%H:%M:%S)"
- name: branch name
id: branch_name
run: echo "::set-output name=name::$(git rev-parse --abbrev-ref HEAD)"
- uses: wangyoucao577/go-release-action@v1.20
with:
github_token: ${{ secrets.EASYCTL_PUBLISH_TOKEN }}
goos: ${{ matrix.goos }}
goarch: ${{ matrix.goarch }}
build_flags: "-gcflags=-trimpath=$GOPATH -asmflags=-trimpath=$GOPATH"
ldflags: "-w -s -X 'main.BuildTime=${{ steps.current_time.outputs.date }}' -X 'main.GitTag=${{ steps.branch_name.outputs.name }}'"
goversion: "1.16"
project_path: "."
binary_name: "easyctl"
# release_tag: "latest"
overwrite: true
extra_files: LICENSE README.md
很多需求都有对应的插件,而且可以与其他的工具联动。可惜我们基于内网开发,使用不到。