您好,登錄后才能下訂單哦!
基于GitLab的CICD流程是怎樣的,針對(duì)這個(gè)問(wèn)題,這篇文章詳細(xì)介紹了相對(duì)應(yīng)的分析和解答,希望可以幫助更多想解決這個(gè)問(wèn)題的小伙伴找到更簡(jiǎn)單易行的方法。
最近想把公司基于Jenkins的自動(dòng)化構(gòu)建修改到GitLab上,主要原因是在Jenkins上沒(méi)有做權(quán)限控制,大家使用同一個(gè)賬號(hào),造成不同項(xiàng)目組的源碼泄漏問(wèn)題;另外還有一個(gè)使用Jenkins的獨(dú)立服務(wù)器,感覺(jué)還是資源浪費(fèi)了點(diǎn)。
按項(xiàng)目
項(xiàng)目
->設(shè)置
->CI/CD
->Runner
按分組
分組
->設(shè)置
->CI/CD
->Runner
全局
管理中心
->概覽
->Runner
從gitee上下載對(duì)應(yīng)的的helm包,地址
修改values文件的gitlabUrl
、runnerRegistrationToken
、tags
執(zhí)行以下命令
helm package . helm install --namespace gitlab --name gitlab-runner *.tgz
說(shuō)明:
gitlabUrl
就是你gitlab私服地址
runnerRegistrationToken
就是從第1步獲取的runner注冊(cè)的token值
tags
標(biāo)識(shí)這個(gè)runner,stage的job就是根據(jù)該tag選擇對(duì)應(yīng)的runner的
Chart.yaml
定義該helm的基本信息,注意里面的name
字段必須和當(dāng)前目錄的名稱一致
templates/pvc.yaml
定義了一個(gè)Dynamic Provisioning的PVC,使用的storageClassName
是阿里云的alicloud-disk-efficiency
(我們的k8s是阿里云的容器服務(wù)),它會(huì)自動(dòng)創(chuàng)建對(duì)應(yīng)的PV,并創(chuàng)建一個(gè)云盤實(shí)例。這個(gè)可以用來(lái)處理多個(gè)Job之間的緩存文件
templates/configmap.yaml
文件的runners.kubernetes.volumes.pvc
定義了PVC的名稱,即上一步定義的PVC名稱,如果有修改注意同步
至此,一個(gè)gitlab-runner應(yīng)該就可以注冊(cè)到對(duì)應(yīng)的gitlab server上去了。
對(duì)于在構(gòu)建過(guò)程使用到比較私密的信息,應(yīng)該直接配置到gitlab server的環(huán)境變量上,這里我們主要配置一下三個(gè)參數(shù):
REGISTRY_PASSWORD
Harbor私服的密碼
REGISTRY_USERNAME
Harbor私服的用戶名
KUBE_CONFIG
kubectl執(zhí)行所需的賬號(hào)、證書(shū)等信息,該字符串可以使用以下命令獲取
echo $(cat ~/.kube/config | base64) | tr -d " "
這里的環(huán)境變量是配置在group下的
CI/CD
頁(yè)面的環(huán)境變量
對(duì)于以下容器的配置為了純手工配置,更好的方式應(yīng)該是使用Dockerfile進(jìn)行編寫(xiě)。這里只是為了更好的說(shuō)明基礎(chǔ)鏡像的制作過(guò)程。
Node容器主要用于編譯前端項(xiàng)目,一般主要使用yarn
下載依賴,npm
編譯打包。所以Node容器需要包含這兩個(gè)命令。
$ docker pull node //拉取最新的node鏡像 $ docker run -it --rm --name node node /bin/sh //運(yùn)行node鏡像,并且進(jìn)入 $ 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 //另外打開(kāi)一個(gè)窗口,提交修改后的node鏡像 $ docker push harbor_url/tools/node-taobao //推送鏡像到Harbor私服
Java容器主要用于編譯Java項(xiàng)目,主要用到JDK
和MAVEN
$ docker pull alpine // 拉取最新的alpine鏡像 $ docker run -it --rm --name java alpine //進(jìn)入鏡像 $ mkdir -p /opt/java // 創(chuàng)建java目錄 $ mkdir -p /opt/maven //創(chuàng)建maven目錄 $ docker cp jdk-8u211-linux-x64.tar.gz java:/opt/java/ //從主機(jī)上拷貝JDK到容器內(nèi)部 $ docker cp apache-maven-3.6.1-bin.tar.gz java:/opt/maven/ //從主機(jī)上拷貝MAVEN到容器內(nèi)部 /opt/maven $ tar -xzvf apache-maven-3.6.1-bin.tar.gz //在容器內(nèi)解壓MAVEN /opt/maven $ rm -rf apache-maven-3.6.1-bin.tar.gz //刪除MAVEN壓縮包 /opt/java $ tar -xzvf jdk-8u211-linux-x64.tar.gz //在容器內(nèi)解壓JDK /opt/java $ rm -rf jdk-8u211-linux-x64.tar.gz //刪除JDK壓縮包 $ vi /etc/profile //配置環(huán)境變量 -------------------------------- 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庫(kù) // 參考地址: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庫(kù)安裝完畢 $ source /etc/profile //生效環(huán)境變量 $ 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 //在另外一個(gè)窗口,提交鏡像 $ docker push harbor_url/tools/java:1.8 //將鏡像推送到Harbor私服
注意
source /etc/profile
這個(gè)命令只是當(dāng)前有效,在提交鏡像后,使用鏡像重新運(yùn)行容器還需要在執(zhí)行一次該命令。具體如何永久生效,還不知道。如果大佬知道可以告知下。
該容器只是適應(yīng)我們公司的狀況,我們公司的前端打包其實(shí)并不需要Node容器。前端打包過(guò)程是在本地打包編譯后生成dist目錄下的文件,然后壓縮上傳到內(nèi)網(wǎng)的oss上。接著在Jenkins上執(zhí)行腳本,其實(shí)是從內(nèi)網(wǎng)的oss下載并解壓,然后根據(jù)Dockerfile在制作業(yè)務(wù)鏡像。這個(gè)過(guò)程就需要使用到Curl和Git命令。整個(gè)過(guò)程是為了解決線上打包環(huán)境可能跟開(kāi)發(fā)本地不一致,以及前端打包需要下載依賴和編譯耗時(shí)的問(wèn)題,通過(guò)這樣的一個(gè)流程,前端每次構(gòu)建的時(shí)間就非常短,幾秒鐘就能搞定。
$ 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 //在另外一個(gè)窗口,提交鏡像 $ docker push harbor_url/tools/curl-git //將鏡像推送到Harbor私服
kubectl容器是用于部署應(yīng)用到k8s集群,需要用到config
的配置信息。但是這個(gè)信息一般比較私密,不會(huì)直接打到容器里面,容器里面只會(huì)放一個(gè)kubectl客戶端,然后具體的配置文件在運(yùn)行期間在放到~/.kube/config
文件內(nèi)。
$ docker run -it --rm --name kubectl alpine //運(yùn)行并且進(jìn)入容器 $ docker cp kubectl kubectl:/usr/bin/ //拷貝kubectl客戶端到容器內(nèi)部,kubectl客戶端可以直接在k8s的master節(jié)點(diǎn)找到,或者直接在github上下載到對(duì)應(yīng)版本的客戶端 $ chmod +x /usr/bin/kubectl //設(shè)置為可執(zhí)行文件 $ kubectl version //查看版本,因?yàn)闆](méi)有配置服務(wù)的證書(shū),所以服務(wù)端的信息打印不出來(lái) -------------------------------- 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 //在另外一個(gè)窗口,提交鏡像 $ docker push harbor_url/tools/kubectl:1.12.6 //將鏡像推送到Harbor私服
# 如果各個(gè)stage沒(méi)有使用鏡像,則使用默認(rèn)鏡像 image: $HARBOR_URL/tools/alpine stages: - build - deploy # 全局變量定義 variables: # 鏡像名,tag默認(rèn)使用pipeline_id IMAGE_NAME: <harbor_url>/<image_path>/<image_name> # 定義應(yīng)用名稱,即deployment_name、container_name、service_name等 APP_NAME: <application_name> # 應(yīng)用端口,一般應(yīng)用端口和service的端口一致 APP_PORT: 80 # 定義命名空間,需要根據(jù)不同的打包命令替換為真實(shí)命名空間 NAMESPACE: dev # HARBOR_URL HARBOR_URL: <harbor_url> docker_build_job: # 包含curl 和 git 工具的鏡像 image: $HARBOR_URL/tools/curl-git stage: build # 定義只有dev分支push或者merge事件觸發(fā)Job only: refs: - dev tags: - <runner_tag> # 使用dind模式,連接到一個(gè)有啟動(dòng)docker的容器 services: - $HARBOR_URL/tools/docker-dind:18.09.7 variables: # docker daemon 啟動(dòng)的參數(shù) DOCKER_DRIVER: overlay DOCKER_HOST: tcp://localhost:2375 # 該 stage 執(zhí)行的腳本命令 # 1. 執(zhí)行構(gòu)建腳本build.sh # 2. 登錄Harbor私服 # 3. 根據(jù)Dockerfile構(gòu)建image # 4. push image 到Harbor script: # build.sh腳本為公司內(nèi)部腳本,根據(jù)后面的參數(shù)配置不同的環(huán)境 # 主要流程是下載開(kāi)發(fā)打包好的壓縮文件,然后解壓,接著根據(jù)不同環(huán)境替換變量 - 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 執(zhí)行的腳本命令 # 1. 創(chuàng)建/etc/deploy/config文件 # 2. 將k8s的證書(shū)信息寫(xiě)入/etc/deploy/config # 3. 替換deployment.yaml文件中的各個(gè)變量 # 4. 部署到k8s集群環(huán)境中 script: - mkdir -p ~/.kube - touch ~/.kube/config # KUBE_CONFIG這個(gè)環(huán)境變量是在gitlab server中配置的 - echo $KUBE_CONFIG | base64 -d > ~/.kube/config # 對(duì)deployment.yaml進(jìn)行對(duì)應(yīng)的變量替換 - 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
這個(gè).gitlab-ci.yml文件少了基于node和java鏡像的配置。不過(guò)都是大同小異,就不在復(fù)述。對(duì)于node鏡像打包后一般會(huì)生成dist目錄,這個(gè)時(shí)候可以加個(gè)步驟把dist目錄壓縮,然后定義
artifacts
,這樣當(dāng)前的stage
執(zhí)行完后就會(huì)上傳該壓縮包到gitlab-server。接著下一個(gè)stage
就會(huì)自動(dòng)下載這個(gè)壓縮包,這樣我們就可以解壓這個(gè)壓縮包,然后再根據(jù)Dockerfile進(jìn)行打包了,同樣是使用dind的模式。對(duì)于java鏡像同樣可以使用這個(gè)原理,mvn編譯打包出一個(gè)jar包或者war包,然后傳遞到下一個(gè)stage
,再進(jìn)行構(gòu)建鏡像;不過(guò)如果使用maven的docker插件的話,那就不用分兩個(gè)stage
了,直接在java的那個(gè)鏡像加個(gè)services
的定義,這樣就可以使用mvn docker:build docker:push
命令了。不過(guò)要注意,使用maven的docker插件,鏡像是定義在pom.xml
文件的,這個(gè)需要和外部的.gitlab-ci.yml文件定義的鏡像名稱同步
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,會(huì)上傳到gitlab-server artifacts: paths: - dist.tar.gz
java_build_job: image: $HARBOR_URL/tools/java:1.8 stage: package only: refs: - dev # services定義,使用dind模式,其實(shí)就是通過(guò)link指令把docker容器鏈接到j(luò)ava鏡像,使得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環(huán)境變量生效 - source /etc/profile - mvn -P$NAMESPACE clean package - cd <module_dir> - mvn -P$NAMESPACE docker:build docker:push
deployment.yaml文件中包含2部分,k8s的deployment
對(duì)象和service
對(duì)象。
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 # 前端項(xiàng)目,使用的是nginx基礎(chǔ)鏡像,一般使用內(nèi)存都比較低 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
至此,一個(gè)完整的基于gitlab的CICD流程可以跑起來(lái)了。因?yàn)槭桥浜蟢8s運(yùn)行的,在整個(gè)搭建的過(guò)程還是坎坷。例如使用javaj鏡像但是需要運(yùn)行docker命令,services
那塊的定義如果不去看文檔就稀里糊涂的;然后前端的yarn
和mvn install
等命令都會(huì)涉及到從公網(wǎng)下載依賴包,這些依賴包如何緩存才能使得下一次構(gòu)建可以直接使用,這個(gè)就涉及到k8s的PV和PVC的相關(guān)概念和使用。
另外,對(duì)于.gitlab-ci.yml的變量還是有寫(xiě)死的內(nèi)容,例如namespace,還需要另外一個(gè)腳本根據(jù)打包命令來(lái)替換對(duì)應(yīng)的變量。還有待優(yōu)化。
這個(gè)整套流程跑下來(lái),感覺(jué)又學(xué)到了一些東西。
關(guān)于基于GitLab的CICD流程是怎樣的問(wèn)題的解答就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,如果你還有很多疑惑沒(méi)有解開(kāi),可以關(guān)注億速云行業(yè)資訊頻道了解更多相關(guān)知識(shí)。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。