前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Gitlab CI/CD 实践四:Golang 项目 CI/CD 流水线配置

Gitlab CI/CD 实践四:Golang 项目 CI/CD 流水线配置

作者头像
Yuyy
发布2022-09-21 10:27:19
2.8K0
发布2022-09-21 10:27:19
举报
文章被收录于专栏:yuyy.info技术专栏

.gitlab-ci.yml

流水线入口:阶段

代码语言:javascript
复制
stages:
  - lint
  - test
  - build
  - deploy

流水线以job为单位运行,每个job就是自己想通过流水线做的事情,例如单元测试的job,核心是运行脚本:

代码语言:javascript
复制
go test -short go list ./...

每个阶段下可以定义多个job。

同一阶段的job会并行执行。

阶段是串行执行。

全局变量

代码语言:javascript
复制
variables:
  IMAGE_GROUP: xxx
  NAME_SPACE: xxx
  GOPATH: ${CI_PROJECT_DIR}/.go
  GOMODCACHE: ${CI_PROJECT_DIR}/.go/pkg/mod
  GOCACHE: ${CI_PROJECT_DIR}/.go/.cache/go-build
  GOLANGCI_LINT_CACHE: ${CI_PROJECT_DIR}/.go/.cache/golangci-lint
  • 自定义一些变量,在流水线执行过程中以环境变量的形式存在。
  • GOPATH:指定GOPATH为项目目录下的.go,原因是流水线缓存只能缓存项目目录下的文件。
  • GOMODCACHE:Go依赖缓存。
  • GOCACHE:go build 产生的缓存。
  • GOLANGCI_LINT_CACHE:golangci-lint 代码质量检查工具,也会产生缓存。

公共模板

job公共模板
代码语言:javascript
复制
.template:
  image: 172.30.3.150/xxx/go-tools:latest
  tags:
    - 172.30.3.219-runner
  interruptible: true

go-tools:运行流水线的基础镜像,里面封装了go运行环境。

  • Dockerfile
代码语言:javascript
复制
FROM golang:1.17.9
USER root

ENV GOPATH /go
ENV PATH ${GOPATH}/bin:$PATH

# 设置私服
RUN go env -w GOPRIVATE=xxx.com
# 设置忽略私服的https证书校验
RUN go env -w GOINSECURE=xxx.com
RUN git config --global http.sslverify false
RUN git config --global https.sslverify false

RUN go env -w GOPROXY="https://goproxy.cn,direct"
RUN go env -w GO111MODULE=on

# install docker
RUN curl -O https://get.docker.com/builds/Linux/x86_64/docker-latest.tgz \
    && tar zxvf docker-latest.tgz \
    && cp docker/docker /usr/local/bin/ \
    && rm -rf docker docker-latest.tgz

tags:指定运行流水线的gitlab runner。

.template:gitlab流水线会认为.开头的脚本不是一个job,就不会去执行。这里只是作为脚本模板,后面真正的job会去extends此模板,达到代码复用的效果。

interruptible:支持可中断,例如上一次流水线还没跑完,又触发了一次,这种情况下会取消上一次流水线。还需要勾选gitlab的这个选项:

image-20220531140614848
image-20220531140614848
缓存模板
代码语言:javascript
复制
.go_cache:
  cache:
    key: go-cache-${CI_PROJECT_PATH_SLUG}
    paths:
      - .go
  • 创建流水线缓存,以项目名称为key,缓存的目录为项目目录下的.go

lint阶段

代码检测job
代码语言:javascript
复制
golangci_lint:
  stage: lint
  only:
    - merge_requests
    - /^release\/.*$/
  extends:
    - .go_cache
    - .template
  script:
    - make golangci_lint
  • stage:指定此job属于lint阶段
  • 触发方式为合并请求下的提交,和以release开头的分支上的提交。
  • extends:继承脚本模板,代码复用。
  • script:job核心内容,指定此job运行的脚本。

test阶段

单元测试、检查数据竞争job
代码语言:javascript
复制
unit_test:
  stage: test
  only:
    - merge_requests
    - /^release\/.*$/
  extends:
    - .go_cache
    - .template
  cache:
    policy: pull
  script:
    - make unit_test
  • cache.policy:默认缓存策略会pull and push,这个job中只使用了缓存,但没有产生缓存,所以不需要上传缓存。

build阶段

打包镜像的job模板
代码语言:javascript
复制
.build_image:
  stage: build
  only:
    - tags
    - /^release\/.*$/
  extends:
    - .go_cache
    - .template
打包镜像job
代码语言:javascript
复制
build_xxx_admin_image:
  extends:
    - .build_image
  script:
    - make build_admin_app
    - make build_admin_image
    - make push_admin_image

build_xxx_interface_image:
  extends:
    - .build_image
  script:
    - make build_interface_app
    - make build_interface_image
    - make push_interface_image

build_xxx_job_image:
  extends:
    - .build_image
  script:
    - make build_job_app
    - make build_job_image
    - make push_job_image

build_xxx_task_image:
  extends:
    - .build_image
  script:
    - make build_task_app
    - make build_task_image
    - make push_task_image
  • 一个阶段多个job。

deploy阶段

部署到测试环境的job模板
代码语言:javascript
复制
.deploy_to_test_k8s:
  stage: deploy
  only:
    - tags
    - /^release\/.*$/
  extends:
    - .template
  image:
    name: 172.30.3.150/xxx/kubectl:latest
    entrypoint: [ "" ]

image:指定运行此job的基础镜像,覆盖公共模板里的image。

172.30.3.150/xxx/kubectl:封装kubectl镜像,增加git、make命令。

  • Dockerfile
代码语言:javascript
复制
FROM bitnami/kubectl

USER root
RUN apt-get update && apt-get install -y --no-install-recommends \
    make git
部署到测试环境job
代码语言:javascript
复制
deploy_admin_to_test_k8s:
  extends:
    - .deploy_to_test_k8s
  needs: [ build_xxx_admin_image ]
  script:
    - make deploy_admin_to_test_k8s

deploy_interface_to_test_k8s:
  extends:
    - .deploy_to_test_k8s
  needs: [ build_xxx_interface_image ]
  script:
    - make deploy_interface_to_test_k8s

deploy_job_to_test_k8s:
  extends:
    - .deploy_to_test_k8s
  needs: [ build_xxx_job_image ]
  script:
    - make deploy_job_to_test_k8s

.deploy_task_to_test_k8s:
  extends:
    - .deploy_to_test_k8s
  needs: [ build_xxx_task_image ]
  script:
    - make deploy_task_to_test_k8s
  • needs:指定依赖关系,流水线默认是一个阶段一个阶段的运行,这里部署admin,只需要admin镜像制作好就运行,而不是等待整个build阶段运行完才执行。

完整的.gitlab-ci.yml

代码语言:javascript
复制
stages:
  - lint
  - test
  - build
  - deploy

#定义全局变量
variables:
  IMAGE_GROUP: xxx
  NAME_SPACE: xxx
  GOPATH: ${CI_PROJECT_DIR}/.go
  GOMODCACHE: ${CI_PROJECT_DIR}/.go/pkg/mod
  GOCACHE: ${CI_PROJECT_DIR}/.go/.cache/go-build
  GOLANGCI_LINT_CACHE: ${CI_PROJECT_DIR}/.go/.cache/golangci-lint

########################### 公共模板 ###########################

#job公共模板
.template:
  image: 172.30.3.150/xxx/go-tools:latest
  tags:
    - 172.30.3.219-runner
  interruptible: true

#缓存模板
.go_cache:
  cache:
    key: go-cache-${CI_PROJECT_PATH_SLUG}
    paths:
      - .go

########################### lint阶段 ###########################

#代码检测job
golangci_lint:
  stage: lint
  only:
    - merge_requests
    - /^release\/.*$/
  extends:
    - .go_cache
    - .template
  script:
    - make golangci_lint

########################### test阶段 ###########################

#单元测试、检查数据竞争job
unit_test:
  stage: test
  only:
    - merge_requests
    - /^release\/.*$/
  extends:
    - .go_cache
    - .template
  cache:
    policy: pull
  script:
    - make unit_test

########################### build阶段 ###########################

#打包镜像的job模板
.build_image:
  stage: build
  only:
    - tags
    - /^release\/.*$/
  extends:
    - .go_cache
    - .template

#打包镜像job
build_xxx_admin_image:
  extends:
    - .build_image
  script:
    - make build_admin_app
    - make build_admin_image
    - make push_admin_image

build_xxx_interface_image:
  extends:
    - .build_image
  script:
    - make build_interface_app
    - make build_interface_image
    - make push_interface_image

build_xxx_job_image:
  extends:
    - .build_image
  script:
    - make build_job_app
    - make build_job_image
    - make push_job_image

build_xxx_task_image:
  extends:
    - .build_image
  script:
    - make build_task_app
    - make build_task_image
    - make push_task_image

########################### deploy阶段 ###########################

#部署到测试环境的job模板
.deploy_to_test_k8s:
  stage: deploy
  only:
    - tags
    - /^release\/.*$/
  extends:
    - .template
  image:
    name: 172.30.3.150/xxx/kubectl:latest
    entrypoint: [ "" ]

#部署到测试环境job
deploy_admin_to_test_k8s:
  extends:
    - .deploy_to_test_k8s
  needs: [ build_xxx_admin_image ]
  script:
    - make deploy_admin_to_test_k8s

deploy_interface_to_test_k8s:
  extends:
    - .deploy_to_test_k8s
  needs: [ build_xxx_interface_image ]
  script:
    - make deploy_interface_to_test_k8s

deploy_job_to_test_k8s:
  extends:
    - .deploy_to_test_k8s
  needs: [ build_xxx_job_image ]
  script:
    - make deploy_job_to_test_k8s

.deploy_task_to_test_k8s:
  extends:
    - .deploy_to_test_k8s
  needs: [ build_xxx_task_image ]
  script:
    - make deploy_task_to_test_k8s

Makefile

具体的脚本抽取到Makefile里,.gitlab-ci.yml只做流水线控制。而且Makefile支持任意环境执行,不依赖于gitlab流水线(使用到gitlab流水线变量的除外),开发可在本地运行Makefile的脚本。

代码语言:javascript
复制
VERSION=$(shell git describe --tags --always)

#################################### 代码检查 ####################################

.PHONY: golangci_lint
golangci_lint:
    go mod tidy # 必须先下载依赖,否则golangci-lint会报:could not load export data: no export data for
    go install github.com/golangci/golangci-lint/cmd/golangci-lint@v1.45.0
    golangci-lint run -v --timeout=5m --color always --out-format colored-line-number

#################################### 单元测试 ####################################

.PHONY: unit_test
unit_test:
    go test -short `go list ./...`

#################################### 构建应用二进制执行文件 ####################################

.PHONY: build_all_app
build_all_app: build_admin_app build_interface_app build_job_app build_task_app

.PHONY: build_admin_app
build_admin_app:
    make build_app SUB_MODULE=admin

.PHONY: build_interface_app
build_interface_app:
    make build_app SUB_MODULE=interface

.PHONY: build_job_app
build_job_app:
    make build_app SUB_MODULE=job

.PHONY: build_task_app
build_task_app:
    make build_app SUB_MODULE=task

.PHONY: build_app
build_app:
    mkdir -p bin
    cd cmd/$(SUB_MODULE) && CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -ldflags "-X main.version=$(VERSION)" -o ../../bin/ && cd -

#################################### 打镜像 ####################################

.PHONY: build_all_image
build_all_image: build_admin_image build_interface_image build_job_image build_task_image

.PHONY: build_admin_image
build_admin_image:
    make build_image SUB_MODULE=admin

.PHONY: build_interface_image
build_interface_image:
    make build_image SUB_MODULE=interface

.PHONY: build_job_image
build_job_image:
    make build_image SUB_MODULE=job

.PHONY: build_task_image
build_task_image:
    make build_image SUB_MODULE=task

.PHONY: build_image
build_image:
    docker build --build-arg SUB_MODULE=$(SUB_MODULE) -t xxx-$(SUB_MODULE):$(VERSION) .

#################################### 推镜像到私仓 ####################################

.PHONY: push_all_image
build_all_image: push_admin_image push_interface_image push_job_image push_task_image

.PHONY: push_admin_image
push_admin_image:
    make push_image SUB_MODULE=admin

.PHONY: push_interface_image
push_interface_image:
    make push_image SUB_MODULE=interface

.PHONY: push_job_image
push_job_image:
    make push_image SUB_MODULE=job

.PHONY: push_task_image
push_task_image:
    make push_image SUB_MODULE=task

.PHONY: push_image
push_image:
    docker login "${DOCKER_REGISTRY_SERVER}" --username "${DOCKER_REGISTRY_USER}" --password "${DOCKER_REGISTRY_PASSWORD}"

    docker tag "xxx-$(SUB_MODULE):$(VERSION)" "${DOCKER_REGISTRY_ADDR}/${IMAGE_GROUP}/xxx-$(SUB_MODULE):$(VERSION)"
    docker push "${DOCKER_REGISTRY_ADDR}/${IMAGE_GROUP}/xxx-$(SUB_MODULE):$(VERSION)"
    docker rmi -f "${DOCKER_REGISTRY_ADDR}/${IMAGE_GROUP}/xxx-$(SUB_MODULE):$(VERSION)"

    docker tag "xxx-$(SUB_MODULE):$(VERSION)" "${DOCKER_REGISTRY_ADDR}/${IMAGE_GROUP}/xxx-$(SUB_MODULE):latest"
    docker push "${DOCKER_REGISTRY_ADDR}/${IMAGE_GROUP}/xxx-$(SUB_MODULE):latest"
    docker rmi -f "${DOCKER_REGISTRY_ADDR}/${IMAGE_GROUP}/xxx-$(SUB_MODULE):latest"

    docker rmi -f "xxx-$(SUB_MODULE):$(VERSION)"

#################################### 部署到k8s ####################################

.PHONY: deploy_all_to_test_k8s
deploy_all_to_test_k8s: deploy_admin_to_test_k8s deploy_interface_to_test_k8s deploy_job_to_test_k8s deploy_task_to_test_k8s

.PHONY: deploy_admin_to_test_k8s
deploy_admin_to_test_k8s:
    make deploy_to_test_k8s SUB_MODULE=admin

.PHONY: deploy_interface_to_test_k8s
deploy_interface_to_test_k8s:
    make deploy_to_test_k8s SUB_MODULE=interface

.PHONY: deploy_job_to_test_k8s
deploy_job_to_test_k8s:
    make deploy_to_test_k8s SUB_MODULE=job

.PHONY: deploy_task_to_test_k8s
deploy_task_to_test_k8s:
    make deploy_to_test_k8s SUB_MODULE=task

.PHONY: deploy_to_test_k8s
deploy_to_test_k8s:
    echo ${K8S_CONFIG_192} | base64 -id > /.kube/config
    sed -i "s/IMAGE_VERSION/$(VERSION)/g" deploy/$(SUB_MODULE)/test/*.yaml
    sed -i "s/NAME_SPACE/${NAME_SPACE}/g" deploy/$(SUB_MODULE)/test/*.yaml
    sed -i "s/DOCKER_REGISTRY_ADDR/${DOCKER_REGISTRY_ADDR}/g" deploy/$(SUB_MODULE)/test/*.yaml
    sed -i "s/IMAGE_GROUP/${IMAGE_GROUP}/g" deploy/$(SUB_MODULE)/test/*.yaml
    kubectl apply -f deploy/$(SUB_MODULE)/test
  • VERSION:此变量用于打镜像的版本号,如果当前分支打了tag,此变量的值就为tag,没有打tag,值为commit hash标识。
  • .PHONY:伪目标,可以防止在Makefile中定义的命令目标和工作目录下的实际文件出现名字冲突。
  • DOCKER_REGISTRY_SERVER:在gitlab配置的变量,可根据实际情况,放到不同级别下。例如gitlab全局,项目群组,项目。
image-20220531153438532
image-20220531153438532
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2022-5-31 1,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • .gitlab-ci.yml
    • 流水线入口:阶段
      • 全局变量
        • 公共模板
          • job公共模板
          • 缓存模板
        • lint阶段
          • 代码检测job
        • test阶段
          • 单元测试、检查数据竞争job
        • build阶段
          • 打包镜像的job模板
          • 打包镜像job
        • deploy阶段
          • 部署到测试环境的job模板
          • 部署到测试环境job
        • 完整的.gitlab-ci.yml
        • Makefile
        相关产品与服务
        容器服务
        腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档