2021-05-12 14:32:11
容器雲平臺No.10~通過gogs+drone+kubernetes實現CI/CD
什麼是CI/CD
持續整合(Continous Intergration,CI)是一種軟體開發實踐,即團隊開發成員經常整合它們的工作,通常每個成員每天至少整合一次,也就意味著每天可能會發生多次整合。每次整合都需要通過自動化的編譯、釋出、自動化迴歸測試來驗證,從而儘快地發現整合錯誤。而這些自動化的操作則由CI軟體進行執行。
持續部署(Continous Delivery,CD)在持續整合的基礎上,將整合後的程式碼部署到真實運行環境中(本文指部署到kubernetes叢集)。交付團隊 ->版本控制 ->構建和單元測試 ->自動驗收測試 -> 釋出
什麼是Drone
Drone 是一個基於Docker容器技術的可擴展的持續整合引擎,用於自動化測試、構建、釋出。每個構建都在一個臨時的Docker容器中執行,使開發人員能夠完全控制其構建環境並保證隔離。開發者只需在項目中包含 .drone.yml檔案,將程式碼推送到 git 倉庫,Drone就能夠自動化的進行編譯、測試、釋出。
使用drone實現CD/CD
首先來看下醜陋的圖
簡單梳理流程:
1、開發人員向git(gitlab/github/gogs)提交程式碼,程式碼中必須包含Dockerfile和.drone.yml檔案。
2、將程式碼commit到遠端倉庫;釋出應用時需要填寫服務類型、服務名稱、資源數量、例項個數等資訊
3、gogs觸發drone自動構建
4、Drone的CI流水線中包括了自定義指令碼,根據準備好的kubernetes的YAML模板,將其中的變數替換成使用者輸入的選項
生成應用的kubernetes YAML配置檔案
5、Drone的CI流水線自動編譯程式碼並打包成docker映象推送到Harbor映象倉庫
6、更新DNS,插入一條DNS記錄,IP地址是ingress節點的IP地址。
7、Drone的CI流水線中自定義指令碼呼叫kubernetes的API,部署應用;更新Ingress的配置,根據新部署的應用的名稱,在ingress的配置檔案中增加一條路由資訊
接下來,開始實戰
部署程式碼倉庫gogs
本文使用gogs,當然你可以選擇gitlab,github等程式碼倉庫
1、創建gogs.yaml
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: gogs
labels:
app: gogs
spec:
serviceName: gogs
replicas: 1
selector:
matchLabels:
app: gogs
template:
metadata:
labels:
app: gogs
spec:
terminationGracePeriodSeconds: 180
containers:
- name: gogs
image: gogs/gogs
imagePullPolicy: Always
ports:
- containerPort: 3000
name: port
- containerPort: 22
name: ssh-port
volumeMounts:
- name: volume
mountPath: /data
volumes:
- name: volume
emptyDir: {}
---
apiVersion: v1
kind: Service
metadata:
name: gogs
labels:
app: gogs
spec:
type: NodePort
ports:
- port: 3000
targetPort: 3000
selector:
app: gogs
2、執行部署並檢視結果
[root@k8s-node001 gogs]# kubectl apply -f gogs.yaml
statefulset.apps/gogs created
service/gogs created
[root@k8s-node001 gogs]# kubectl get po,svc -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
pod/gogs-0 1/1 Running 0 2m2s 100.68.150.197 k8s-node001 <none> <none>
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR
service/gogs NodePort 10.106.102.74 <none> 3000:30526/TCP 2m3s app=gogs
3、瀏覽器開啟,並配置gogs,然後就可以登入gogs了
4、登入gogs
至此,gogs配置完畢。
Tips:本文的gogs,是測試環境,使用卷類型為:emptyDir,生產環境最好單獨部署或者使用StorageClass保證資料持久可用性
接下來部署drone
部署CI工具Drone
1、編寫drone.yaml檔案
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: drone
labels:
app: drone
spec:
serviceName: drone
replicas: 1
selector:
matchLabels:
app: drone
template:
metadata:
labels:
app: drone
spec:
terminationGracePeriodSeconds: 180
containers:
- name: drone
image: drone/drone:1
imagePullPolicy: Always
env:
- name: DRONE_AGENTS_ENABLED
value: "true"
- name: DRONE_GOGS_SERVER
value: http://192.168.100.181:30526/ # 注意這裡填的是gogs的地址
- name: DRONE_RPC_SECRET
value: qawsedrftg
- name: DRONE_SERVER_HOST
value: drone.company.com
- name: DRONE_SERVER_PROTO
value: http
ports:
- containerPort: 80
name: port
- containerPort: 443
name: ssl-port
volumeMounts:
- name: volume
mountPath: /data
volumes:
- name: volume
emptyDir: {}
---
apiVersion: v1
kind: Service
metadata:
name: drone
labels:
app: drone
spec:
type: NodePort
ports:
- port: 80
targetPort: 80
selector:
app: drone
2、執行部署並檢視結果
[root@k8s-node001 drone]# kubectl apply -f drone.yaml
[root@k8s-node001 drone]# kubectl get po,svc -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
pod/drone-0 1/1 Running 0 4m40s 100.68.150.198 k8s-node001 <none> <none>
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR
service/drone NodePort 10.100.77.138 <none> 80:31681/TCP 4m40s app=drone
3、現在就可以用瀏覽器訪問http://192.168.100.181:31681 ,使用gogs的賬號就可以登入drone了
4、登入後可以看到,現在並沒有任何項目,後續再gogs新建項目,就能看到了
部署Drone Runner
Runner的作用是詢問Drone Server,然後執行pipeline,更多資訊請檢視官網
1、編寫drone-runner.yaml
---
kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
namespace: default
name: drone
rules:
- apiGroups:
- ""
resources:
- secrets
verbs:
- create
- delete
- apiGroups:
- ""
resources:
- pods
- pods/log
verbs:
- get
- create
- delete
- list
- watch
- update
---
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: drone
namespace: default
subjects:
- kind: ServiceAccount
name: default
namespace: default
roleRef:
kind: Role
name: drone
apiGroup: rbac.authorization.k8s.io
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: drone-runner
labels:
app.kubernetes.io/name: drone-runner
spec:
replicas: 1
selector:
matchLabels:
app.kubernetes.io/name: drone-runner
template:
metadata:
labels:
app.kubernetes.io/name: drone-runner
spec:
containers:
- name: drone-runner
image: drone/drone-runner-kube:latest
ports:
- containerPort: 3000
env:
- name: DRONE_RPC_HOST
value: 192.168.100.181:31681 # Drone Server地址
- name: DRONE_RPC_PROTO
value: http
- name: DRONE_RPC_SECRET
value: qawsedrftg # Drone Server部署時候填寫的secret
2、執行部署並檢視結果
[root@k8s-node001 drone]# kubectl apply -f drone-runner.yaml
[root@k8s-node001 drone]# kubectl get po
NAME READY STATUS RESTARTS AGE
drone-runner-7c64bffb45-dh2dn 1/1 Running 0 11m
至此,實現CI/CD的環境都準備好了,現在來跑一個demo
CI/CD示例
1、gogs新建項目demo
2、drone上點sync,就可以看到demo項目
3、啟用demo項目,儲存
4、在gogs的demo項目中,新增.drone.yml檔案,新增一個pipeline
5、提交程式碼,但是不觸發CI,Commit的時候填寫[CI SKIP]就可以跳過觸發CI
如果這裡直接Commit提交程式碼,就直接觸發CI功能,Drone就開始執行這個pipeline了
[CI SKIP]的作用就是如果需要修改多個檔案,這時候會很有用;
當然在實際開發過程中,都是把項目clone到本地,編輯好所有檔案,再push到程式碼倉庫,這樣就不需要[CI SKIP]了
6、我們這裡隨便修改 README,然後知己commit,不是用[CI SKIP]看下效果
7、執行結果,這裡失敗了,後面再解決
8、如果您commit以後並沒有觸發Drone,需要在gogs檢視webhooks時候正常,如下圖
9、這裡我們來解決pipeline執行失敗的問題
我們通過drone介面可以看到項目pipeline報錯如下,顯示runner clone程式碼失敗了
Initialized empty Git repository in /drone/src/.git/
+ git fetch origin +refs/heads/master:
fatal: unable to access 'http://192.168.100.181:3000/scofield/demo.git/': Failed to connect to 192.168.100.181 port 3000: Connection refused
首先看下這個pipeline,很簡單,使用映象alpine執行兩條輸出語句
kind: pipeline
type: kubernetes
name: default
steps:
- name: greeting
image: alpine
commands:
- echo hello
- echo world
但是預設情況下,Drone執行pipeline之前會克隆項目,url就是gogs的http地址,這裡是http://192.168.100.181:3000/scofield/demo.git 因為我這裡測試環境使用NodePort暴露的服務,Drone需要使用http://192.168.100.181:30526/scofield/demo.git 這個地址才能克隆到項目,如果使用ingress暴露gogs服務,這個url就是域名而不是IP,就不會出現這個問題。
那現在需要解決這個問題,我們就自定義clone,修改預設的克隆地址,修改如下,修改完直接commit程式碼,觸發CI
通過drone頁面檢視結果,可以看到clone成功
而且執行的echo命令也成功執行
至此本文實戰結束
總結
本文是“基於Docker及Kubernetes構建的容器雲平臺”系列第十篇,也是最後一篇,如果您看完了整個系列文章,在此感謝。
通過這十篇文章,您應該可以構建出一個測試環境的容器平臺。關於容器雲平臺更多內容,後續會繼續分享,盡請持續關注。
PS:後續文章會同步到dev.kubeops.net
相關文章