go代码 gitlab-ci/cd部署

使用gitlab CI/CD技术部署golang服务

鉴于每次修改代码后都需要拉取-编译-部署等一些列步骤,探索使用gitlab ci/cd技术实现服务的自动化集成部署,节省服务部署和维护成本,经过几天的摸索踩坑后完成了部署,记录下部署步骤防止遗忘。

原理

部署gitlab ci/cd前必须要知道其运行机制,知其然知其所以然才能在使用中得心应手,
基础的gitlab ci/cd概念如Pipelines,job,stage等可以看官方文档或者百度。
gitlab ci/cd原理图

  1. 推送代码至gitlab,触发git-runner
  2. git-runner容器拉取代码,并启动runner配置文件中预先配置好的镜像执行job
  3. build job对代码进行编译并打包成镜像,将镜像推送至仓库
  4. deploy job通过ssh登录远程部署服务器拉取仓库中的镜像,并执行docker run实现远程服务器部署

部署

配置gitlab-runner

要使用gitlab-ci/cd,需要在gitlab中打开Settings->Genneral->Pipeliness设置,打开后在项目和设置中才会显示CI/CD
gitlab设置
打开Settings->CI/CD在Runners中选择手动设置Runner,gitlab会生成配置Runner需要的URL和Token
手动Runner配置
登录服务器使用Docker安装gitlab-runner,安装教程可以参考官方文档
拉取镜像:

docker pull gitlab/gitlab-runner

拉取镜像后需要注意,由于需要在执行job的容器中生成镜像,那么gitlab-runner容器默认启动的执行job的容器(这里我使用的是golang:1.16)就需要具备docker功能,这里有两个路线:

  1. 在golang:1.16中安装docker服务生成新的镜像golang-tools:1.16作为基础镜像
  2. 将服务器中的docker目录和套接字挂载到gitlab-runner中,gitlab-runner启动golang:1.16容器时再将docker目录和套接字进行二次挂载

两种方法第一种相对麻烦,打包新的基础镜像中频繁出现包安装失败,链接被墙等问题,方案二相对简单,但是将服务器的docker挂在到容器中,容器中操作便是服务器的docker存在安全风险,这里我还是选择使用了方案二,因为我没有搭建docker仓库,使用方案一就需要有个仓库去存储镜像,方案二则直接将镜像生成在服务器上,执行时也是直接在服务器上搜索,在不考虑部署在其他服务器上的情况下比较简单实用。
这里需要注意的是使用方案二进行目录挂载,容器中所有的docker images、docker ps、docker rm等都和服务器一致,尽量不要在gitlab-ci.yaml脚本中出现批量的清理操作。

启动gitlab-runner容器:

docker run -d --name gitlab-runner --restart always   -v /var/run/docker.sock:/var/run/docker.sock   -v /srv/gitlab-runner/config:/etc/gitlab-runner -v /usr/bin/docker:/usr/bin/docker  gitlab/gitlab-runner:latest

启动参数中分别挂载了三个目录

  • /var/run/docker.sock:/var/run/docker.sock //docker套接字
  • /srv/gitlab-runner/config:/etc/gitlab-runner //gitlab-runner配置文件,gitlab-runner启动后可以在/srv/gitlab-runner/config文件夹中找到配置文件进行修改,gitlab-runner每3秒扫描一次该文件。
  • /usr/bin/docker:/usr/bin/docker //docker目录

** 注册runner**
注册的作用是填入gitlab中的URL和token让gitlab可以找到runner

  • 进入容器
dcoker exec -it gitlab-runner /bin/bash
  • 注册
gitlab-runner register

接下来会看到一系列的输入项,一步一步输入即可。
输入 Token 来注册 Runner
在 GitLab 的仓库 Setting -> CI/CD 设置页面中,展开 Runners 部分,即可看到生成的 Token,复制粘贴即可

 输入 GitLab 的地址。
如果是使用的官方的 GitLab,就输入 https://gitlab.com,自建的 GitLab 就输入自己的IP或域名即可。
Please enter the gitlab-ci coordinator URL (e.g. https://gitlab.com )
https://gitlab.com
Please enter the gitlab-ci token for this runner
xxxToken
Please enter the gitlab-ci description for this runner
[hostame] my-runner //名称,后期可以修改
Please enter the gitlab-ci tags for this runner (comma separated):
config-tag //每个runner默认只会运行和自己tag一致的job,也可以设置为运行所有job
Please enter the executor: ssh, docker+machine, docker-ssh+machine, kubernetes, docker, parallels, virtualbox, docker-ssh, shell:
 docker //如果选择了 executor 为 docker,那么就需要选择一个默认的镜像。这里我设置为golang:1.16,可以在配置中修改

注册完成后可在gitlab->Settings->CI/CD->Runners中看到Runners activated for this project
注册完成图

  • 配置修改
    gitlab-runner的配置文件默认存放在/srv/gitlab-runner/config/config.toml,通过修改配置可以对runner进行设置![gitlab-runner描述](https://img-blog.csdnimg.cn/d43cf9fab7d0417f88a041fc9a87ec6b.p
    上文中提到过如果想在job中执行docker的两种方案,为了实现将服务器的docker挂载到执行job的镜像中(golang:1.16)需要在volumes中添加目录映射配置即如上图所示,添加:"/var/run/docker.sock:/var/run/docker.sock","/usr/bin/docker:/usr/bin/docker"
    runner会在启动golang:1.16时将volumes的参数以-v的形式追加到指令后,如此便可实现在golang:1.16使用docker进行镜像打包操作。
    另外也可以在gitlab页面中对runner的部分属性进行修改
    在这里插入图片描述

gitlab-ci.yaml编写

runner配置完成后就需要编写gitlab-ci.yaml告诉gitlab需要做哪些操作,在服务根目录下添加gitlab-ci.yaml文件,按照当前项目需求编写job,并指定执行条件,每次提交代码若执行条件如branch,tag满足则会触发CI/CD操作。

# This file is a template, and might need editing before it works on your project.
image: golang:1.16

variables:
  # Please edit to your GitLab project
  REPO_NAME: test-svr

# The problem is that to be able to use go get, one needs to put
# the repository in the $GOPATH. So for example if your gitlab domain
# is gitlab.com, and that your repository is namespace/project, and
# the default GOPATH being /go, then you'd need to have your
# repository in /go/src/gitlab.com/namespace/project
# Thus, making a symbolic link corrects this.
before_script:
  - mkdir -p $GOPATH/src/$(dirname $REPO_NAME)
  - ln -svf $CI_PROJECT_DIR $GOPATH/src/$REPO_NAME
  - cd $GOPATH/src/$REPO_NAME

stages:
  #  - test
  - build
  - deploy

  #api_test:
  #  stage: test
  #  script:
  #- go fmt $(go list ./... | grep -v /vendor/)
  #- go vet $(go list ./... | grep -v /vendor/)
  #- go test -race $(go list ./... | grep -v /vendor/)

#build:
#  stage: build
#  script:
#    - pwd
#    - go build -race -ldflags "-extldflags '-static'" -o $CI_PROJECT_DIR/$REPO_NAME
#  artifacts:
#    paths:
#      - $REPO_NAME
build_image:
  stage: build
  script:
    - chmod a+x ./build_docker_image.sh
    - ./build_docker_image.sh
  only:
    - master
deploy:
  stage: deploy
  script:
    - docker  run -d --name=test-svr -v /opt/logs:/app/logs --net=host --restart=always test-svr:1.0.0
  only:
    - master

比较详细的gitlab-ci语法可以去官方文档查看这里就不一一介绍了,大概介绍一下当前gitlab-ci.yaml做了哪些算是梳理一下整个流程。

  • before_script:
    声明是告诉runner在每个job中都要执行该操作
    即将代码拷贝到 G O P A T H / s r c / GOPATH/src/ GOPATH/src/(dirname $REPO_NAME)目录下
  • stages:
    声明了两个阶段build和deploy,两个阶段会先后执行,同一阶段中的多个job会并行执行,即当前服务仅有编译和部署两个阶段
  • build_image
    声明了一个job,该job指定为build阶段,在该阶段中执行了build_docker_image.sh脚本,only字段标识该job只在master分支中触发,其他分支runner不会执行该工作
  • deploy
    声明了一个job,该job指定为deploy阶段,该阶段执行docker run启动了上一阶段中生成的镜像,实现服务的部署
    下面附上build_docker_image.sh供参考
#!/bin/bash
#检测GOPATH
echo "检测GOPATH"
if [ -z "$GOPATH" ];then
echo "GOPATH 未设定"
exit 1
else
echo "GOPATH=$GOPATH"
fi
#初始化数据
echo "初始化数据"
new_version="1.0.0"
old_version="1.0.0"
golang_version="1.9.2"
app_name="test-svr"
project_root="test-svr"
DOCKER_IMAGE_NAME="test-svr"
path="/go/src/$project_root"
#设置环境变量
go env -w GO111MODULE=on
go env -w  CGO_ENABLED=0
go env -w GOPROXY=https://goproxy.cn,direct
go env
#当前容器更换为旧标签
echo "移除旧镜像"
#停止旧容器并删除和镜像
docker stop $(docker ps -a | grep $DOCKER_IMAGE_NAME | awk '{print $1 }')   #停止容器
docker rm $(docker ps -a | grep $DOCKER_IMAGE_NAME | awk '{print $1 }')    #删除容器
docker rmi $(docker images | grep $DOCKER_IMAGE_NAME | awk '{print $3}')    #删除镜像
#docker rmi $DOCKER_IMAGE_NAME:$old_version
# 基于golang:1.16镜像启动的容器实例,编译本项目的二进制可执行程序
echo "基于golang:1.16镜像启动的容器实例,编译本项目的二进制可执行程序"
cd $path
go mod download
go build -o $app_name
echo "检测 $app_name 应用"
FILE="$path/$app_name"
if [ -f "$FILE" ];then
echo "$FILE 已就绪"
else
echo "$FILE 应用不存在"
exit 1
fi
#docker构建镜像 禁止在构建上下文之外的路径 添加复制文件
#所以在此可以用命令把需要的文件cp到 dockerfile 同目录内 ,构建完成后再用命令删除
cd $path/script
echo "提取构建时需要的文件"
cp ../$app_name $app_name
cp ../config.yaml config.yaml
echo "当前目录"
pwd
# 基于当前目录下的Dockerfile构建镜像
echo "基于当前目录下的Dockerfile构建镜像"
echo "docker build -t $DOCKER_IMAGE_NAME:$new_version ."
docker build -t $DOCKER_IMAGE_NAME:$new_version .
# 删除本次生成的可执行文件 以及构建所需要的文件
echo "删除本次生成的可执行文件 以及构建所需要的文件"
rm -rf $app_name
rm -rf ../$app_name
#查看镜像
echo "查看镜像"
docker images | grep $DOCKER_IMAGE_NAME
#推送镜像,如果需要部署到其他服务器上可以打开该操作,我当前没有docker仓库进行了注释
#echo "推送镜像"
#echo "docker push $REGISTRY_HOST/$DOCKER_IMAGE_NAME:$new_version"
#docker push $REGISTRY_HOST/$DOCKER_IMAGE_NAME:$new_version

至此我的gitlab CI/CD部署完成了,上传代码可以在CI/CD中看到:
在这里插入图片描述
在这里插入图片描述

  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值