共計 13847 個字符,預計需要花費 35 分鐘才能閱讀完成。
這篇文章給大家介紹 k8s+docker 如何部署 jenkins+gitlab 實現 CICD,內容非常詳細,感興趣的小伙伴們可以參考借鑒,希望對大家能有所幫助。
CICD 核心概念
CICD 是持續集成(continuous integration,CI),持續交付(continuous delivery,CD),持續部署(continuous Deployment,CD)的簡稱。
指在開發過程中自動執行一系列腳本來減低開發引入 bug 的概率,在新代碼從開發到部署的過程中,盡量減少人工的介入。
1,持續集成
持續集成指的是,頻繁地(一天多次)將代碼集成到主干。
它的好處有兩個:
1)快速發現錯誤:每完成一點更新,就集成到主干,可以快速發現錯誤,定位錯誤也比較容易。
2)防止分支大幅偏離主干:如果不是經常集成,主干又在不斷更新,會導致以后集成的難度變大,甚至難以集成。
持續集成的目的:
讓產品可以快速迭代同時還能保持高質量,它的核心措施是:代碼集成到主干之前,必須通過自動化測試,只要有一個測試用例失敗,就不能集成。
Martin Fowler 說過,持續集成并不能消除 Bug,而是讓它們非常容易發現和改正。
2,持續交付
持續交付指的是頻繁的將軟件的新版本交付給質量團隊或用戶,以供評審,如果評審通過,代碼就進入生產階段。
持續交付可以看作是持續集成的下一步,強調的是,不管怎樣更新,軟件是隨時隨地可以交付的。
3,持續部署
持續部署是持續交付的下一步,指的是代碼通過評審之后,自動部署到生產環境。
持續部署的目標是:代碼在任何時候都是可以部署的,可以進入生產階段。
持續部署的前提是能自動化完成測試,構建,部署等步驟。
持續部署與持續交付的區別,可以參考下圖:
Docker,kubernetes 的 CICD 實現思路
jenkins 是一個比較流行的持續集成工具。
GitLab 是存儲鏡像的鏡像倉庫。
流程詳解:
由客戶端將代碼 push 推送到 git 倉庫,gitlab 上配置了一個 webHook 的東西可以觸發 Jenkins 的構建。進入到 Jenkins 虛線范圍內,它所做的事情非常多,從 mvn 構建代碼,對代碼進行靜態分析,做單元測試,測試通過之后就可以 build 鏡像,鏡像構建成功后就把鏡像 push 推送到 Harbor 鏡像倉庫中,鏡像 push 推送到鏡像倉庫后,我們就可以調用 kubernetes 集群的 restAPI 更新服務,而后 kubernetes 接收到了更新的指令,從 Harbor 鏡像倉庫 pull 拉取鏡像,從而完成服務的更新與重啟,最后我們從客戶端來訪問 kubernetes 集群的服務。
項目實踐
項目環境:
主機操作系統 ip 地址 k8s01(master)Centos 7.3172.16.1.30k8s02(node01)Centos 7.3172.16.1.31k8s03 (node02)Centos 7.3172.16.1.32jenkins+gitlab+dockerCentos 7.3172.16.1.33 項目實施:
本文所用到的安裝包和插件我已上傳至百度網盤:鏈接:https://pan.baidu.com/s/17mDLgSZ218a-zYhjYddhiA
提取碼:nyxh
1,部署 kubernetes 集群(前三臺主機):
部署 kubernetes 集群可參考博文 kubeadm 部署 kubernetes 集群
# 確保 k8s 集群正常運行:[root@master ~]# kubectl get nodes
NAME STATUS ROLES AGE VERSION
master Ready master 112d v1.15.0
node01 Ready none 112d v1.15.0
node02 Ready none 112d v1.15.0
2,集群中部署 harbor 私有倉庫 **
可以選擇任意一臺服務器,這里選擇 master 作為 harboar 私有倉庫。詳細配置可參考博文 kubernetes 部署 Harbor 私有倉庫
[root@master ~]# yum -y install yum-utils device-mapper-persistent-data lvm2
[root@master ~]# curl -L https://github.com/docker/compose/releases/download/1.25.0-rc4/docker-compose-`uname -s`-`uname -m` -o /usr/local/bin/docker-compose
[root@master ~]# chmod +x /usr/local/bin/docker-compose
[root@master harbor]# wget https://storage.googleapis.com/harbor-releases/release-1.7.0/harbor-offline-installer-v1.7.4.tgz
[root@master harbor]# tar xf harbor-offline-installer-v1.7.4.tgz
[root@master harbor]# cd harbor/
[root@master harbor]# vim harbor.cfg
[root@master harbor]# ./install.sh # 執行安裝腳本
[Step 4]: starting Harbor ...
Creating network harbor_harbor with the default driver
Creating harbor-log ... done
Creating redis ... done
Creating registryctl ... done
Creating harbor-adminserver ... done
Creating harbor-db ... done
Creating registry ... done
Creating harbor-core ... done
Creating harbor-portal ... done
Creating harbor-jobservice ... done
Creating nginx ... done
? ----Harbor has been installed and started successfully.----
Now you should be able to visit the admin portal at http://172.16.1.30.
For more details, please visit https://github.com/goharbor/harbor .
# 登錄 web 界面新建倉庫,URL:http://172.16.1.30
默認用戶名:admin 密碼:Harbor12345
# 修改 docker 配置文件(且重啟 docker)并登錄 harbor:(集群中的三個節點做相同操作)
[root@master harbor]# vim /usr/lib/systemd/system/docker.service
[root@master harbor]# systemctl daemon-reload
[root@master harbor]# systemctl restart docker
[root@master harbor]# docker login -uadmin -pHarbor12345 172.16.1.30:80
WARNING! Using --password via the CLI is insecure. Use --password-stdin.
WARNING! Your password will be stored unencrypted in /root/.docker/config.json.
Configure a credential helper to remove this warning. See
https://docs.docker.com/engine/reference/commandline/login/#credentials-store
Login Succeeded
#node01 和 node02 操作同上(都需登錄 harbor)
# 在 harbor 服務器(master)上,將鏡像上傳到私有倉庫:
[root@master harbor]# docker pull nginx:latest
[root@master harbor]# docker tag nginx:latest 172.16.1.30:80/cicd/nginx:v1.0
[root@master harbor]# docker push 172.16.1.30:80/cicd/nginx:v1.0
The push refers to repository [172.16.1.30:80/cicd/nginx]
12fdf55172df: Pushed
002a63507c1c: Pushed
1c95c77433e8: Pushed
v1.0: digest: sha256:099019968725f0fc12c4b69b289a347ae74cc56da0f0ef56e8eb8e0134fc7911 size: 948
# 創建認證登錄密鑰,以保證 kubernetes 能夠拉取 harbor 倉庫中的私有鏡像:
[root@master harbor]# kubectl create secret docker-registry login --docker-server=172.16.1.30:80 --docker-username=admin --docker-password=Harbor12345
secret/login created
[root@master harbor]# kubectl get secrets
NAME TYPE DATA AGE
default-token-wswg2 kubernetes.io/service-account-token 3 113d
login kubernetes.io/dockerconfigjson 1 33s
# 選擇集群中的某個節點測試是否能夠從 Harbor 私有倉庫中拉取鏡像:
[root@node01 ~]# docker pull 172.16.1.30:80/cicd/nginx:v1.0
v1.0: Pulling from cicd/nginx
1ab2bdfe9778: Pull complete
a17e64cfe253: Pull complete
e1288088c7a8: Pull complete
7ee7d3fe92e1: Pull complete
Digest: sha256:763562fbc544806c1305304da23d36d0532f082325a1c427996474e304313801
Status: Downloaded newer image for 172.16.1.30:80/cicd/nginx:v1.0
[root@node01 ~]# docker images | grep 172.16.1.30
172.16.1.30:80/cicd/nginx v1.0 c6ad7233ab97 10 minutes ago 126MB
ok,證明 kubernetes 和 Harbor 私有倉庫部署完畢。接下來部署 jenkins+gitlab,并配置聯動。
3,部署 jenkins+gitlab
# 在最后一臺主機 172.16.1.33 上進行操作。
1),基本環境準備
# 關閉防火墻:
[root@docker-cicd ~]# systemctl stop firewalld
[root@docker-cicd ~]# systemctl status firewalld
● firewalld.service - firewalld - dynamic firewall daemon
Loaded: loaded (/usr/lib/systemd/system/firewalld.service; disabled; vendor preset: enabled)
Active: inactive (dead)
Docs: man:firewalld(1)
# 禁用 selinux:
[root@docker-cicd ~]# vim /etc/sysconfig/selinux
2)部署 jenkins 服務
[root@docker-cicd ~]# mkdir CICD
[root@docker-cicd ~]# cd CICD/
[root@docker-cicd CICD]# tar zxf jdk-8u131-linux-x64.tar.gz
[root@docker-cicd CICD]# mv jdk1.8.0_131/ /usr/java
#設置全局變量:[root@docker-cicd CICD]# vim /etc/profile
在最后添加以下配置項:export JAVA_HOME=/usr/java
export JRE_HOME=/usr/java/jre
export PATH=$JAVA_HOME/bin:$JRE_HOME/bin:$PATH
export CLASSPATH=$JAVA_HOME/lib/tools.jar:$JAVA_HOME/lib/dt.jar
[root@docker-cicd CICD]# source /etc/profile # 使其環境變量生效
[root@docker-cicd CICD]# java -version # 驗證 java 環境
java version 1.8.0_131
Java(TM) SE Runtime Environment (build 1.8.0_131-b11)
Java HotSpot(TM) 64-Bit Server VM (build 25.131-b11, mixed mode)
# 安裝 tomcat
[root@docker-cicd CICD]# tar zxf apache-tomcat-7.0.54.ta
[root@docker-cicd CICD]# mv apache-tomcat-7.0.54 /usr/tomcat7
[root@docker-cicd CICD]# cd /usr/tomcat7/webapps/
[root@docker-cicd webapps]# ls
docs examples host-manager manager ROOT
[root@docker-cicd webapps]# rm -rf * # 刪除 tomcat 網頁目錄原有文件
#將 jenkins war 包上傳至 tomcat 的網頁根目錄下
[root@docker-cicd webapps]# ls
jenkins.war
# 修改 tomcat 的字符集:[root@docker-cicd webapps]# vim /usr/tomcat7/conf/server.xml
# 在 tomcat 中定義 jenkins 的家目錄(/data/jenkins)[root@docker-cicd webapps]# vim /usr/tomcat7/bin/catalina.sh
export CATALINA_OPTS= -DJENKINS_HOME=/data/jenkins
export JENKINS_JAVA_OPTIONS= -Djava.awt.headless=true -Dhudson.ClassicPluginStrategy.noBytecodeTransformer=true
# 啟動 tomcat(即啟動 jenkins)
[root@docker-cicd webapps]# /usr/tomcat7/bin/catalina.sh start
Using CATALINA_BASE: /usr/tomcat7
Using CATALINA_HOME: /usr/tomcat7
Using CATALINA_TMPDIR: /usr/tomcat7/temp
Using JRE_HOME: /usr/java/jre
Using CLASSPATH: /usr/tomcat7/bin/bootstrap.jar:/usr/tomcat7/bin/tomcat-juli.jar
Tomcat started.
[root@docker-cicd webapps]# ss -anput | grep 8080
tcp LISTEN 0 100 :::8080 :::* users:((java ,pid=41682,fd=46))
# 瀏覽器登錄 jenkins web 界面,在 web 界面中配置安裝 jenkins
URL:http://172.16.1.33:8080/jenkins
[root@docker-cicd webapps]# cat /data/jenkins/secrets/initialAdminPassword
36ceb6eeb1bc46af8ce20935b81d8fe8
將管理員密碼粘貼上后,點擊“繼續”。
# 左邊是自動安裝,右邊是自定義安裝,我們選擇安裝推薦的插件。
選擇離線安裝,斷掉網絡失敗后,點擊繼續。
登錄界面如下:
# 安裝必要插件
1)首先安裝中文插件:系統管理 —– 插件管理 —– avalilable(可選) 然后搜索 localization-zh-cn
安裝成功后,重新啟動 jenkins,可以發現界面已經支持中文了:
# 還需安裝 3 個插件,搜索 gitlab 安裝:Gitlab Authentication、GitLab、Gitlab Hook
安裝過程可能較慢,耐心等待,
插件下載成功后,勾選重啟 jenkins 選項即可:
如果網絡問題導致無法下載成功,還可以在服務器目錄下進行上傳插件:/var/lib/jenkins/plugins 這個目錄是存放所有安裝的插件。(插件已上傳至網盤)
3)部署 gitlab 服務
[root@docker-cicd CICD]# rpm -ivh gitlab-ce-11.9.8-ce.0.el6.x86_64.rpm
warning: gitlab-ce-11.9.8-ce.0.el6.x86_64.rpm: Header V4 RSA/SHA1 Signature, key ID f27eab47: NOKEY
Preparing... ################################# [100%]
Updating / installing...
1:gitlab-ce-11.9.8-ce.0.el6 ################################# [100%]
# 為了解決端口沖突,修改 gitlab 配置文件:
[root@docker-cicd CICD]# vim /etc/gitlab/gitlab.rb
因沒有部署 dns,所以 url 修改為本機 ip,80 默認是 http 服務的端口,unicorn[‘port’]默認是 8080,同樣與上邊的 jenkins8080 端口沖突,所以分別修改為 81 和 8081。
# 初始化并啟動 gitlab:[root@docker-cicd CICD]# gitlab-ctl reconfigure
# 確定 81 端口正常監聽:[root@docker-cicd CICD]# netstat -anput | grep -w 81
tcp 0 0 0.0.0.0:81 0.0.0.0:* LISTEN 47382/nginx: master
# 瀏覽器登錄 gitlab,并在 web 界面中進行配置
URL:http://172.16.1.33:81/
登錄 gitlab 后需要先設置一個密碼再登錄,這里設置 1234.com(需要符合密碼復雜性要求,最少 8 位),用戶默認為 root。
# 配置 ssh 密鑰認證:
部署 jenkins 和 gitlab 這兩個服務的聯動,需要經過 ssh 驗證。
首先在 gitlab 上綁定 jenkins 服務器的 ssh 公鑰(因為是部署在同一臺服務器上,所以綁定自己的公鑰)
[root@docker-cicd ~]# ssh-keygen -t rsa
[root@docker-cicd ~]# cat /root/.ssh/id_rsa.pub
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDW7s9qm08DaiShtnjBbUUwOpFYmvYaqUuqrIrXHrvcGGQDlte6Ug0R7/K5Igz4HKsjZIFCCblzgH2VLIk6FM0L+eccKnW8/uSywQcKclgK3gqiTRBDiqSt4NqYQz1R8hEW3KbXkXXUIU8kJ3svehxzG0Y8lUrMy7zEhkJ6vod7z5wcJeayzVfkro6Xd4TMiRrasXilApRiIr1Sr9Z9dWgWQkCCM85pQeZZirsZ/w4fT6gwRpP1kTtRBggDnXGi7lfWkMbKYljKMuG4jp92K8mRBLyjsg6Lkq0hkKAOToftwmpCx8CA/05LhMexvDnJXyFg/o+8yG+o0qmrlSvojl+N root@docker-cicd
復制這個公鑰,然后登陸 gitlab,點擊右上角的設置:
# 在 gitlab 上創建一個代碼倉庫:
輸入一個倉庫的名字 權限選擇公共的(public)然后直接點擊創建:
點擊新建一個 new.file:
創建完成后,在本地測試是否能夠拉取倉庫中的文件:
[root@docker-cicd ~]# git clone git@172.16.1.33:root/my-test-project.git
[root@docker-cicd ~]# cd my-test-project/
[root@docker-cicd my-test-project]# ls
index.html
[root@docker-cicd my-test-project]# cat index.html
print: hello world!!
4)配置 jenkins 和 gitlab 聯動
該 URL 鏈接:
# 執行構建操作:
#!/bin/bash
#定義變量(存放數據的目錄)backupcode= /data/backcode/$JOB_NAME/$BUILD_NUMBER
#創建該目錄
mkdir -p $backupcode
#對 jenkins 家目錄(/data/jenkins)下的 workspace/ 設置所需擁有的權限
chmod 644 $JENKINS_HOME /workspace/ $JOB_NAME /*
#使用 rsync 工具拷貝并同步數據
rsync -acP $JENKINS_HOME /workspace/ $JOB_NAME /* $backupcode
#以下操作是編寫一個 Dockerfile 文件(將修改的內容拷貝到新鏡像中)
echo FROM 172.16.1.30:80/cicd/nginx:v1.0 $JENKINS_HOME /workspace/Dockerfile # 源鏡像就使用私有倉庫中鏡像
echo COPY ./ $JOB_NAME /* /usr/share/nginx/html/ $JENKINS_HOME /workspace/Dockerfile
#刪除舊版本的鏡像(因為存在會持續不斷的進行構建)docker rmi 172.16.1.30:80/cicd/nginx:v2.0
#使用 docker build 通過該 dockerfile 構建新版本鏡像
docker build -t 172.16.1.30:80/cicd/nginx:v2.0 / $JENKINS_HOME /workspace/.
#將新生成的新鏡像 push 到私有倉庫上
docker push 172.16.1.30:80/cicd/nginx:v2.0
#刪除之前版本的 deployment 資源(nginx 應用)ssh root@172.16.1.30 kubectl delete deployment nginx
#重新創建 nginx 應用(這次從倉庫中拉取的鏡像是新生成的鏡像)ssh root@172.16.1.30 kubectl apply -f /root/yaml/nginx.yaml
注意:/root/yaml/nginx.yaml 此路徑是自定義的,后邊需要在該目錄下創建 nginx 的 YAML 文件(路徑保持一致,否則會導致構建失敗)
這里面寫的是 jenkins 構建時會執行的 shell 腳本,這個腳本才是實現持續集成核心,它實現了下端 kubernetes 自動更新容器的操作。
注意:腳本中所定義的內容,得根據你們自己當前的環境進行定義(比如主機地址,私有倉庫鏡像和存放文件路徑都是不同的),腳本編寫較易,可根據自己的需求進行修改。
# 編寫完腳本后不要保存,下面的這個插件很重要,就是他實現自動化更新的 webhook 插件,首先復制下圖的 jenkins URL 地址,然后去 gitlab 上綁定 webhook:
復制 url 后點擊保存:
## 登錄 github 進行操作
點擊添加后,可以看到有報錯提示:gitlab 默認設置不允許向自己發送 webhook(因為我們是部署在一臺服務器上),如下圖所示:
## 修改全局配置,勾選允許發送本地請求:
# 修改成功后,重新添加 web hook:
# 添加完成后,會出現一個版塊,測試連接:
證明 jenkins 與 gitlab 聯動成功。
# 如果添加 webhook 出現以下報錯信息,則需要在 jenkins 上的“全局安全配置”中開啟匿名訪問權限,然后重新添加。報錯信息如下圖:
5)配置 jenkins 免密登錄 kubernetes 集群
配置免密登錄的目的是為了在構建時,能夠去執行 master 中的 YAML 文件。
# 將 jenkins 主機上的密鑰對拷貝給 master 節點,以實現能夠免密登錄集群中的 master:[root@docker-cicd ~]# ssh-copy-id root@172.16.1.30
到此,集成環境部署完畢,接下來進行測試。
5,測試部署環境
在 gitlab 上新建代碼,刪除代碼,修改代碼,都會觸發 webhook 進行自動部署。最終會作用在所有的 nginx 容器中,也就是我們的 web 服務器。
# 首先將 jenkins 和 gitlab 這臺主機登錄 harbor 私有倉庫:
1)安裝 docker:
[root@docker-cicd ~]# cd /etc/yum.repos.d/
[root@docker-cicd yum.repos.d]# wget https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
[root@docker-cicd yum.repos.d]# yum repolist # 查看可用的 repo 源
[root@docker-cicd yum.repos.d]# yum -y install docker-ce
[root@docker-cicd yum.repos.d]# systemctl start docker
[root@docker-cicd yum.repos.d]# systemctl enable docker
[root@docker-cicd yum.repos.d]# docker -v
Docker version 19.03.6, build 369ce74a3c
2)修改 docker 配置文件:
[root@docker-cicd yum.repos.d]# vim /usr/lib/systemd/system/docker.service
# 重新加載 docker 服務:[root@docker-cicd yum.repos.d]# systemctl daemon-reload
[root@docker-cicd yum.repos.d]# systemctl restart docker
3)登錄 harbor 倉庫:
[root@docker-cicd ~]# docker login -uadmin -pHarbor12345 172.16.1.30:80
WARNING! Using --password via the CLI is insecure. Use --password-stdin.
WARNING! Your password will be stored unencrypted in /root/.docker/config.json.
Configure a credential helper to remove this warning. See
https://docs.docker.com/engine/reference/commandline/login/#credentials-store
Login Succeeded
4)在 master 上創建在 shell 腳本中定義的 nginx 應用的 YAML 文件(部署 web 服務):
[root@master ~]# mkdir yaml
[root@master ~]# cd yaml/
[root@master yaml]# vim nginx.yaml
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: nginx
spec:
replicas: 2 # 定義兩個副本
template:
metadata:
labels:
web: nginx
spec:
containers:
- name: nginx
image: 172.16.1.30:80/cicd/nginx:v2.0 # 鏡像指定私有倉庫中的鏡像(注意:版本為在 jenkins 上新構建的版本) imagePullPolicy: Always # 定義鏡像策略(每次創建 pod 時,總是從倉庫中重新拉取鏡像) ports:
- containerPort: 80
imagePullSecrets: # 添加 imagePullSecrets 字段,指定剛才創建的登錄密鑰(login) - name: login
apiVersion: v1 # 創建 service 資源(映射 web 端口為 31234)kind: Service
metadata:
name: nginx-svc
spec:
type: NodePort
ports:
- port: 80
targetPort: 80
nodePort: 31234
selector:
web: nginx
# 在 gitlab 上修改或新建代碼(例如修改之前創建的 index.html 文件)
# 點擊提交后,會觸發 webhook,進行構建:
控制臺輸出信息中會顯示構建過程中的詳細信息,如果在構建的過程中那個環節出現了問題,也能在信息中準確的查看到,如下圖所示:
# 瀏覽器訪問 web 服務(nginx),URL:http://172.16.1.30:31234
# 在 gitlab 上重新修改代碼:
// 修改內容: h2 hello world, This is two build /h2
再次觸發 webhook,重新構建:
# 重新通過瀏覽器訪問 nginx 服務:
# 第三次在 gitlab 上修改代碼:
// 修改代碼為:h2 hello world, This is three build /h2
# 重新通過瀏覽器訪問 nginx:
# 在服務器本地查看上面構建的項目和文件:
[root@docker-cicd ~]# cd /data/
[root@docker-cicd data]# ls
backcode jenkins #backcode 為我們創建的存放構建項目的目錄,一個為 jenkins 的家目錄
[root@docker-cicd data]# cd backcode/test/
[root@docker-cicd test]# ls # 在當前目錄下存放了所構建的項目
10 11 12 3 4 5 6 7 8 9
[root@docker-cicd test]# cat 12/index.html # 而目錄中的內容正是我們所構建的代碼
h2 hello world, This is three build /h2
[root@docker-cicd test]# cd ../../jenkins/workspace/
[root@docker-cicd workspace]# ls
Dockerfile test
[root@docker-cicd workspace]# cat test/index.html
h2 hello world, This is three build /h2
#在 jenkins 家目錄下存放了 Dcokerfile 文件和最新構建的代碼
至此,CICD 項目部署完畢,Kubernetes 中的 web 應用,會通過 jenkins+gitlab 的自動構建,無需人工的介入,自動部署并更新 web 界面,減少了在生產中出現的 bug 的概率,等待時間及更高的產品質量。
關于 k8s+docker 如何部署 jenkins+gitlab 實現 CICD 就分享到這里了,希望以上內容可以對大家有一定的幫助,可以學到更多知識。如果覺得文章不錯,可以把它分享出去讓更多的人看到。