温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

基于GitLab的CICD流程是怎样的

发布时间:2021-10-19 18:36:19 来源:亿速云 阅读:205 作者:柒染 栏目:大数据

基于GitLab的CICD流程是怎样的,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。

最近想把公司基于Jenkins的自动化构建修改到GitLab上,主要原因是在Jenkins上没有做权限控制,大家使用同一个账号,造成不同项目组的源码泄漏问题;另外还有一个使用Jenkins的独立服务器,感觉还是资源浪费了点。

配置GitLab的runner

从gitlab上获取Runner注册的token。有三种方式
  • 按项目
    项目->设置->CI/CD->Runner

  • 按分组
    分组->设置->CI/CD->Runner

  • 全局
    管理中心->概览->Runner

运行Runner
  • 从gitee上下载对应的的helm包,地址

  • 修改values文件的gitlabUrlrunnerRegistrationTokentags

  • 执行以下命令

helm package . helm install --namespace gitlab --name gitlab-runner *.tgz

说明:

  • gitlabUrl 就是你gitlab私服地址

  • runnerRegistrationToken 就是从第1步获取的runner注册的token值

  • tags 标识这个runner,stage的job就是根据该tag选择对应的runner的

  • Chart.yaml定义该helm的基本信息,注意里面的name字段必须和当前目录的名称一致

  • templates/pvc.yaml 定义了一个Dynamic Provisioning的PVC,使用的storageClassName是阿里云的alicloud-disk-efficiency(我们的k8s是阿里云的容器服务),它会自动创建对应的PV,并创建一个云盘实例。这个可以用来处理多个Job之间的缓存文件

  • templates/configmap.yaml文件的runners.kubernetes.volumes.pvc定义了PVC的名称,即上一步定义的PVC名称,如果有修改注意同步

至此,一个gitlab-runner应该就可以注册到对应的gitlab server上去了。

配置环境变量

对于在构建过程使用到比较私密的信息,应该直接配置到gitlab server的环境变量上,这里我们主要配置一下三个参数:

  • REGISTRY_PASSWORD Harbor私服的密码

  • REGISTRY_USERNAME Harbor私服的用户名

  • KUBE_CONFIG kubectl执行所需的账号、证书等信息,该字符串可以使用以下命令获取

echo $(cat ~/.kube/config | base64) | tr -d " "

这里的环境变量是配置在group下的CI/CD页面的环境变量

对于以下容器的配置为了纯手工配置,更好的方式应该是使用Dockerfile进行编写。这里只是为了更好的说明基础镜像的制作过程。

配置Node容器

Node容器主要用于编译前端项目,一般主要使用yarn下载依赖,npm编译打包。所以Node容器需要包含这两个命令。

$ docker pull node //拉取最新的node镜像 $ docker run -it --rm --name node node /bin/sh //运行node镜像,并且进入 $ yarn config set registry https://registry.npm.taobao.org //配置yarn的源为淘宝源 $ yarn config list //查看配置 -------------------------------- info yarn config {   'version-tag-prefix': 'v',   'version-git-tag': true,   'version-commit-hooks': true,   'version-git-sign': false,   'version-git-message': 'v%s',   'init-version': '1.0.0',   'init-license': 'MIT',   'save-prefix': '^',   'bin-links': true,   'ignore-scripts': false,   'ignore-optional': false,   registry: 'https://registry.yarnpkg.com',   'strict-ssl': true,   'user-agent': 'yarn/1.16.0 npm/? node/v12.5.0 linux x64',   version: '1.16.0' } info npm config {   version: '1.16.0' } Done in 0.07s. -------------------------------- $ docker commit node harbor_url/tools/node-taobao //另外打开一个窗口,提交修改后的node镜像 $ docker push harbor_url/tools/node-taobao //推送镜像到Harbor私服

配置Java容器

Java容器主要用于编译Java项目,主要用到JDKMAVEN

$ docker pull alpine // 拉取最新的alpine镜像 $ docker run -it --rm --name java alpine //进入镜像 $ mkdir -p /opt/java // 创建java目录 $ mkdir -p /opt/maven //创建maven目录 $ docker cp jdk-8u211-linux-x64.tar.gz java:/opt/java/    //从主机上拷贝JDK到容器内部  $ docker cp apache-maven-3.6.1-bin.tar.gz java:/opt/maven/   //从主机上拷贝MAVEN到容器内部 /opt/maven $ tar -xzvf apache-maven-3.6.1-bin.tar.gz  //在容器内解压MAVEN /opt/maven $ rm -rf apache-maven-3.6.1-bin.tar.gz     //删除MAVEN压缩包 /opt/java $ tar -xzvf jdk-8u211-linux-x64.tar.gz      //在容器内解压JDK /opt/java $ rm -rf jdk-8u211-linux-x64.tar.gz         //删除JDK压缩包 $ vi /etc/profile	//配置环境变量 -------------------------------- export JAVA_HOME=/opt/java/jdk1.8.0_211 export M2_HOME=/opt/maven/apache-maven-3.6.1 export PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:$JAVA_HOME/bin:$M2_HOME/bin -------------------------------- //Java是基于GUN Standard C library(glibc),Alpine是基于MUSL libc(mini libc),所以需要安装glibc库 // 参考地址:https://blog.csdn.net/Dannyvon/article/details/80092834 $ echo http://mirrors.ustc.edu.cn/alpine/v3.10/main > /etc/apk/repositories $ echo http://mirrors.ustc.edu.cn/alpine/v3.10/community >> /etc/apk/repositories $ apk update $ apk --no-cache add ca-certificates $ wget https://github.com/sgerrand/alpine-pkg-glibc/releases/download/2.27-r0/glibc-2.27-r0.apk $ wget -q -O /etc/apk/keys/sgerrand.rsa.pub https://alpine-pkgs.sgerrand.com/sgerrand.rsa.pub $ apk add glibc-2.27-r0.apk  // 至此glibc库安装完毕 $ source /etc/profile  //生效环境变量 $ java -version  //查看JAVA版本 -------------------------------- java version "1.8.0_211" Java(TM) SE Runtime Environment (build 1.8.0_211-b12) Java HotSpot(TM) 64-Bit Server VM (build 25.211-b12, mixed mode) -------------------------------- $ mvn -v  //查看MAVEN版本 -------------------------------- Apache Maven 3.6.1 (d66c9c0b3152b2e69ee9bac180bb8fcc8e6af555; 2019-04-04T19:00:29Z) Maven home: /opt/maven/apache-maven-3.6.1 Java version: 1.8.0_211, vendor: Oracle Corporation, runtime: /opt/java/jdk1.8.0_211/jre Default locale: en_US, platform encoding: ANSI_X3.4-1968 OS name: "linux", version: "4.9.125-linuxkit", arch: "amd64", family: "unix" -------------------------------- $ docker commit java harbor_url/tools/java:1.8  //在另外一个窗口,提交镜像 $ docker push harbor_url/tools/java:1.8   //将镜像推送到Harbor私服

注意source /etc/profile这个命令只是当前有效,在提交镜像后,使用镜像重新运行容器还需要在执行一次该命令。具体如何永久生效,还不知道。如果大佬知道可以告知下。

配置Curl&Git容器

该容器只是适应我们公司的状况,我们公司的前端打包其实并不需要Node容器。前端打包过程是在本地打包编译后生成dist目录下的文件,然后压缩上传到内网的oss上。接着在Jenkins上执行脚本,其实是从内网的oss下载并解压,然后根据Dockerfile在制作业务镜像。这个过程就需要使用到Curl和Git命令。整个过程是为了解决线上打包环境可能跟开发本地不一致,以及前端打包需要下载依赖和编译耗时的问题,通过这样的一个流程,前端每次构建的时间就非常短,几秒钟就能搞定。

$ docker run -it --rm --name curl-git alpine $ echo http://mirrors.ustc.edu.cn/alpine/v3.10/main > /etc/apk/repositories $ echo http://mirrors.ustc.edu.cn/alpine/v3.10/community >> /etc/apk/repositories $ apk update $ apk add curl $ apk add git $ curl -V -------------------------------- curl 7.61.1 (x86_64-alpine-linux-musl) libcurl/7.61.1 LibreSSL/2.6.5 zlib/1.2.11 libssh3/1.8.2 Release-Date: 2018-09-05 Protocols: dict file ftp ftps gopher http https imap imaps pop3 pop3s rtsp scp sftp smb smbs smtp smtps telnet tftp Features: AsynchDNS IPv6 Largefile NTLM NTLM_WB SSL libz UnixSockets HTTPS-proxy -------------------------------- $ git version -------------------------------- git version 2.15.3 -------------------------------- $ docker commit curl-git harbor_url/tools/curl-git  //在另外一个窗口,提交镜像 $ docker push harbor_url/tools/curl-git   //将镜像推送到Harbor私服

配置kubectl容器

kubectl容器是用于部署应用到k8s集群,需要用到config的配置信息。但是这个信息一般比较私密,不会直接打到容器里面,容器里面只会放一个kubectl客户端,然后具体的配置文件在运行期间在放到~/.kube/config文件内。

$ docker run -it --rm --name kubectl alpine  //运行并且进入容器 $ docker cp kubectl kubectl:/usr/bin/  //拷贝kubectl客户端到容器内部,kubectl客户端可以直接在k8s的master节点找到,或者直接在github上下载到对应版本的客户端 $ chmod +x /usr/bin/kubectl //设置为可执行文件 $ kubectl version //查看版本,因为没有配置服务的证书,所以服务端的信息打印不出来 -------------------------------- Client Version: version.Info{Major:"1", Minor:"12+", GitVersion:"v1.12.6-aliyun.1", GitCommit:"4304b26", GitTreeState:"", BuildDate:"2019-04-08T08:50:29Z", GoVersion:"go1.10.8", Compiler:"gc", Platform:"linux/amd64"} The connection to the server localhost:8080 was refused - did you specify the right host or port? -------------------------------- $ docker commit kubectl harbor_url/tools/kubectl:1.12.6  //在另外一个窗口,提交镜像 $ docker push  harbor_url/tools/kubectl:1.12.6   //将镜像推送到Harbor私服

配置.gitlab-ci.yml

# 如果各个stage没有使用镜像,则使用默认镜像 image: $HARBOR_URL/tools/alpine stages:   - build   - deploy # 全局变量定义 variables:   # 镜像名,tag默认使用pipeline_id   IMAGE_NAME: <harbor_url>/<image_path>/<image_name>   # 定义应用名称,即deployment_name、container_name、service_name等   APP_NAME: <application_name>   # 应用端口,一般应用端口和service的端口一致   APP_PORT: 80   # 定义命名空间,需要根据不同的打包命令替换为真实命名空间   NAMESPACE: dev   # HARBOR_URL   HARBOR_URL: <harbor_url> docker_build_job:   # 包含curl 和 git 工具的镜像   image: $HARBOR_URL/tools/curl-git   stage: build   # 定义只有dev分支push或者merge事件触发Job   only:     refs:       - dev   tags:     - <runner_tag>   # 使用dind模式,连接到一个有启动docker的容器   services:     - $HARBOR_URL/tools/docker-dind:18.09.7   variables:     # docker daemon 启动的参数     DOCKER_DRIVER: overlay     DOCKER_HOST: tcp://localhost:2375   # 该 stage 执行的脚本命令   # 1. 执行构建脚本build.sh   # 2. 登录Harbor私服   # 3. 根据Dockerfile构建image   # 4. push image 到Harbor   script:   	# build.sh脚本为公司内部脚本,根据后面的参数配置不同的环境     # 主要流程是下载开发打包好的压缩文件,然后解压,接着根据不同环境替换变量     - sh ./build.sh -b development     - docker login -u $REGISTRY_USERNAME -p $REGISTRY_PASSWORD $HARBOR_URL     - docker build -t $IMAGE_NAME:$CI_PIPELINE_ID .     - docker push $IMAGE_NAME:$CI_PIPELINE_ID k8s_deploy_job:   # 包含kubectl 工具的镜像   image: $HARBOR_URL/tools/kubectl:1.12.6   stage: deploy   only:     refs:       - dev   tags:     - <runner_tag>   # 该 stage 执行的脚本命令   # 1. 创建/etc/deploy/config文件   # 2. 将k8s的证书信息写入/etc/deploy/config   # 3. 替换deployment.yaml文件中的各个变量   # 4. 部署到k8s集群环境中   script:     - mkdir -p ~/.kube     - touch ~/.kube/config     # KUBE_CONFIG这个环境变量是在gitlab server中配置的     - echo $KUBE_CONFIG | base64 -d > ~/.kube/config     # 对deployment.yaml进行对应的变量替换     - sed -i "s?IMAGE_TAG?$CI_PIPELINE_ID?g" deployment.yaml     - sed -i "s?IMAGE_NAME?$IMAGE_NAME?g" deployment.yaml     - sed -i "s?APP_NAME?$APP_NAME?g" deployment.yaml     - sed -i "s?NAMESPACE?$NAMESPACE?g" deployment.yaml     - sed -i "s?APP_PORT?$APP_PORT?g" deployment.yaml     - kubectl apply -f deployment.yaml

这个.gitlab-ci.yml文件少了基于node和java镜像的配置。不过都是大同小异,就不在复述。对于node镜像打包后一般会生成dist目录,这个时候可以加个步骤把dist目录压缩,然后定义artifacts,这样当前的stage执行完后就会上传该压缩包到gitlab-server。接着下一个stage就会自动下载这个压缩包,这样我们就可以解压这个压缩包,然后再根据Dockerfile进行打包了,同样是使用dind的模式。对于java镜像同样可以使用这个原理,mvn编译打包出一个jar包或者war包,然后传递到下一个stage,再进行构建镜像;不过如果使用maven的docker插件的话,那就不用分两个stage了,直接在java的那个镜像加个services的定义,这样就可以使用mvn docker:build docker:push命令了。不过要注意,使用maven的docker插件,镜像是定义在pom.xml文件的,这个需要和外部的.gitlab-ci.yml文件定义的镜像名称同步

node镜像部分定义
node_build_job:   image: $HARBOR_URL/tools/node-taobao   stage: package   only:     refs:       - dev   tags:     - <runner_tag>   script:   	# 下载依赖     - yarn     # 编译打包     - npm run build --qa     # 压缩dist目录     - tar -czvf dist.tar.gz dist/   # 定义artifacts,会上传到gitlab-server   artifacts:     paths:     - dist.tar.gz
java镜像部分定义
java_build_job:   image: $HARBOR_URL/tools/java:1.8   stage: package   only:     refs:       - dev   # services定义,使用dind模式,其实就是通过link指令把docker容器链接到java镜像,使得java镜像可以使用docker命令   services:     - $HARBOR_URL/tools/docker-dind:18.09.7   variables:     DOCKER_DRIVER: overlay     DOCKER_HOST: tcp://localhost:2375   tags:     - <runner_tag>   script:     # 重新使得JAVA_HOME、M2_HOME环境变量生效     - source /etc/profile     - mvn -P$NAMESPACE clean package     - cd <module_dir>     - mvn -P$NAMESPACE docker:build docker:push

配置deployment.yaml

deployment.yaml文件中包含2部分,k8s的deployment对象和service对象。

apiVersion: apps/v1beta2 kind: Deployment metadata:   labels:     app: APP_NAME   name: APP_NAME   namespace: NAMESPACE spec:   progressDeadlineSeconds: 600   replicas: 1   revisionHistoryLimit: 10   selector:     matchLabels:       app: APP_NAME   strategy:     rollingUpdate:       maxSurge: 25%       maxUnavailable: 25%     type: RollingUpdate   template:     metadata:       labels:         app: APP_NAME     spec:       affinity: {}       containers:         - image: 'IMAGE_NAME:IMAGE_TAG'           imagePullPolicy: Always           name: APP_NAME           # 前端项目,使用的是nginx基础镜像,一般使用内存都比较低           resources:             limits:               cpu: '1'               memory: 64Mi             requests:               cpu: '0'               memory: 32Mi           terminationMessagePath: /dev/termination-log           terminationMessagePolicy: File       dnsPolicy: ClusterFirst       restartPolicy: Always       schedulerName: default-scheduler       securityContext: {}       terminationGracePeriodSeconds: 30 --- apiVersion: v1 kind: Service metadata:   name: APP_NAME   namespace: NAMESPACE spec:   ports:     - port: APP_PORT       protocol: TCP       targetPort: APP_PORT   selector:     app: APP_NAME   sessionAffinity: None   type: ClusterIP

结束

至此,一个完整的基于gitlab的CICD流程可以跑起来了。因为是配合k8s运行的,在整个搭建的过程还是坎坷。例如使用javaj镜像但是需要运行docker命令,services那块的定义如果不去看文档就稀里糊涂的;然后前端的yarnmvn install等命令都会涉及到从公网下载依赖包,这些依赖包如何缓存才能使得下一次构建可以直接使用,这个就涉及到k8s的PV和PVC的相关概念和使用。

另外,对于.gitlab-ci.yml的变量还是有写死的内容,例如namespace,还需要另外一个脚本根据打包命令来替换对应的变量。还有待优化。

这个整套流程跑下来,感觉又学到了一些东西。


关于基于GitLab的CICD流程是怎样的问题的解答就分享到这里了,希望以上内容可以对大家有一定的帮助,如果你还有很多疑惑没有解开,可以关注亿速云行业资讯频道了解更多相关知识。

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI