什么是CI/CD
持續(xù)集成(Continous Intergration揩抡,CI)是一種軟件開發(fā)實踐,即團隊開發(fā)成員經(jīng)常集成它們的工作澎灸,通常每個成員每天至少集成一次专甩,也就意味著每天可能會發(fā)生多次集成。每次集成都需要通過自動化的編譯辆憔、發(fā)布涮母、自動化回歸測試來驗證,從而盡快地發(fā)現(xiàn)集成錯誤躁愿。而這些自動化的操作則由CI軟件進行執(zhí)行叛本。
持續(xù)部署(Continous Delivery,CD)在持續(xù)集成的基礎(chǔ)上彤钟,將集成后的代碼部署到真實運行環(huán)境中(本文指部署到kubernetes集群)来候。交付團隊 ->版本控制 ->構(gòu)建和單元測試 ->自動驗收測試 -> 發(fā)布
什么是Drone
Drone 是一個基于Docker容器技術(shù)的可擴展的持續(xù)集成引擎,用于自動化測試逸雹、構(gòu)建营搅、發(fā)布。每個構(gòu)建都在一個臨時的Docker容器中執(zhí)行梆砸,使開發(fā)人員能夠完全控制其構(gòu)建環(huán)境并保證隔離转质。開發(fā)者只需在項目中包含 .drone.yml文件,將代碼推送到 git 倉庫帖世,Drone就能夠自動化的進行編譯休蟹、測試、發(fā)布日矫。
使用drone實現(xiàn)CD/CD
首先來看下丑陋的圖
簡單梳理流程:
1赂弓、開發(fā)人員向git(gitlab/github/gogs)提交代碼,代碼中必須包含Dockerfile和.drone.yml文件哪轿。
2盈魁、將代碼commit到遠程倉庫;發(fā)布應(yīng)用時需要填寫服務(wù)類型窃诉、服務(wù)名稱杨耙、資源數(shù)量、實例個數(shù)等信息
3飘痛、gogs觸發(fā)drone自動構(gòu)建
4珊膜、Drone的CI流水線中包括了自定義腳本,根據(jù)準備好的kubernetes的YAML模板敦冬,將其中的變量替換成用戶輸入的選項
生成應(yīng)用的kubernetes YAML配置文件
5辅搬、Drone的CI流水線自動編譯代碼并打包成docker鏡像推送到Harbor鏡像倉庫
6、更新DNS脖旱,插入一條DNS記錄堪遂,IP地址是ingress節(jié)點的IP地址。
7萌庆、Drone的CI流水線中自定義腳本調(diào)用kubernetes的API溶褪,部署應(yīng)用;更新Ingress的配置践险,根據(jù)新部署的應(yīng)用的名稱猿妈,在ingress的配置文件中增加一條路由信息
接下來,開始實戰(zhàn)
部署代碼倉庫gogs
本文使用gogs巍虫,當(dāng)然你可以選擇gitlab,github等代碼倉庫
1彭则、創(chuàng)建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、執(zhí)行部署并查看結(jié)果
[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,是測試環(huán)境搔啊,使用卷類型為:emptyDir柬祠,生產(chǎn)環(huán)境最好單獨部署或者使用StorageClass保證數(shù)據(jù)持久可用性
接下來部署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负芋、執(zhí)行部署并查看結(jié)果
[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漫蛔、現(xiàn)在就可以用瀏覽器訪問http://192.168.100.181:31681 ,使用gogs的賬號就可以登錄drone了
4、登錄后可以看到旧蛾,現(xiàn)在并沒有任何項目惩猫,后續(xù)再gogs新建項目,就能看到了
部署Drone Runner
Runner的作用是詢問Drone Server蚜点,然后執(zhí)行pipeline轧房,更多信息請查看官網(wǎng)
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绍绘、執(zhí)行部署并查看結(jié)果
[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
至此奶镶,實現(xiàn)CI/CD的環(huán)境都準備好了,現(xiàn)在來跑一個demo
CI/CD示例
1陪拘、gogs新建項目demo
2厂镇、drone上點sync,就可以看到demo項目
3、激活demo項目左刽,保存
4捺信、在gogs的demo項目中,添加.drone.yml文件,添加一個pipeline
5、提交代碼迄靠,但是不觸發(fā)CI秒咨,Commit的時候填寫[CI SKIP]就可以跳過觸發(fā)CI
如果這里直接Commit提交代碼,就直接觸發(fā)CI功能掌挚,Drone就開始執(zhí)行這個pipeline了
[CI SKIP]的作用就是如果需要修改多個文件雨席,這時候會很有用;
當(dāng)然在實際開發(fā)過程中吠式,都是把項目clone到本地陡厘,編輯好所有文件,再push到代碼倉庫特占,這樣就不需要[CI SKIP]了
6糙置、我們這里隨便修改 README,然后知己commit,不是用[CI SKIP]看下效果
7是目、執(zhí)行結(jié)果谤饭,這里失敗了,后面再解決
8胖笛、如果您commit以后并沒有觸發(fā)Drone,需要在gogs查看webhooks時候正常网持,如下圖
9、這里我們來解決pipeline執(zhí)行失敗的問題
我們通過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執(zhí)行兩條輸出語句
kind: pipeline
type: kubernetes
name: default
steps:
- name: greeting
image: alpine
commands:
- echo hello
- echo world
但是默認情況下身弊,Drone執(zhí)行pipeline之前會克隆項目辟汰,url就是gogs的http地址,這里是http://192.168.100.181:3000/scofield/demo.git 因為我這里測試環(huán)境使用NodePort暴露的服務(wù)阱佛,Drone需要使用http://192.168.100.181:30526/scofield/demo.git 這個地址才能克隆到項目帖汞,如果使用ingress暴露gogs服務(wù),這個url就是域名而不是IP凑术,就不會出現(xiàn)這個問題翩蘸。
那現(xiàn)在需要解決這個問題,我們就自定義clone淮逊,修改默認的克隆地址催首,修改如下,修改完直接commit代碼泄鹏,觸發(fā)CI
通過drone頁面查看結(jié)果郎任,可以看到clone成功
而且執(zhí)行的echo命令也成功執(zhí)行
至此本文實戰(zhàn)結(jié)束
總結(jié)
本文是“基于Docker及Kubernetes構(gòu)建的容器云平臺”系列第十篇,也是最后一篇备籽,如果您看完了整個系列文章舶治,在此感謝。
通過這十篇文章,您應(yīng)該可以構(gòu)建出一個測試環(huán)境的容器平臺霉猛。關(guān)于容器云平臺更多內(nèi)容尺锚,后續(xù)會繼續(xù)分享,盡請持續(xù)關(guān)注韩脏。
PS:后續(xù)文章會同步到dev.kubeops.net