您好,登錄后才能下訂單哦!
基于GitLab的CICD流程是怎樣的,針對這個問題,這篇文章詳細介紹了相對應的分析和解答,希望可以幫助更多想解決這個問題的小伙伴找到更簡單易行的方法。
最近想把公司基于Jenkins的自動化構建修改到GitLab上,主要原因是在Jenkins上沒有做權限控制,大家使用同一個賬號,造成不同項目組的源碼泄漏問題;另外還有一個使用Jenkins的獨立服務器,感覺還是資源浪費了點。
按項目
項目
->設置
->CI/CD
->Runner
按分組
分組
->設置
->CI/CD
->Runner
全局
管理中心
->概覽
->Runner
從gitee上下載對應的的helm包,地址
修改values文件的gitlabUrl
、runnerRegistrationToken
、tags
執行以下命令
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容器主要用于編譯前端項目,一般主要使用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項目,主要用到JDK
和MAVEN
$ 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
這個命令只是當前有效,在提交鏡像后,使用鏡像重新運行容器還需要在執行一次該命令。具體如何永久生效,還不知道。如果大佬知道可以告知下。
該容器只是適應我們公司的狀況,我們公司的前端打包其實并不需要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容器是用于部署應用到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私服
# 如果各個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_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_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文件中包含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
那塊的定義如果不去看文檔就稀里糊涂的;然后前端的yarn
和mvn install
等命令都會涉及到從公網下載依賴包,這些依賴包如何緩存才能使得下一次構建可以直接使用,這個就涉及到k8s的PV和PVC的相關概念和使用。
另外,對于.gitlab-ci.yml的變量還是有寫死的內容,例如namespace,還需要另外一個腳本根據打包命令來替換對應的變量。還有待優化。
這個整套流程跑下來,感覺又學到了一些東西。
關于基于GitLab的CICD流程是怎樣的問題的解答就分享到這里了,希望以上內容可以對大家有一定的幫助,如果你還有很多疑惑沒有解開,可以關注億速云行業資訊頻道了解更多相關知識。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。