容器云平臺No.10~通過gogs+drone+kubernetes實現(xiàn)CI/CD

什么是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

首先來看下丑陋的圖


image.png

簡單梳理流程:

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了


image.png

4、登錄gogs


image.png

至此瓦胎,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了


image.png

4、登錄后可以看到旧蛾,現(xiàn)在并沒有任何項目惩猫,后續(xù)再gogs新建項目,就能看到了


image.png

部署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


image.png

2厂镇、drone上點sync,就可以看到demo項目


image.png

3、激活demo項目左刽,保存


image.png

4捺信、在gogs的demo項目中,添加.drone.yml文件,添加一個pipeline

image.png

5、提交代碼迄靠,但是不觸發(fā)CI秒咨,Commit的時候填寫[CI SKIP]就可以跳過觸發(fā)CI


image.png

如果這里直接Commit提交代碼,就直接觸發(fā)CI功能掌挚,Drone就開始執(zhí)行這個pipeline了
[CI SKIP]的作用就是如果需要修改多個文件雨席,這時候會很有用;
當(dāng)然在實際開發(fā)過程中吠式,都是把項目clone到本地陡厘,編輯好所有文件,再push到代碼倉庫特占,這樣就不需要[CI SKIP]了
6糙置、我們這里隨便修改 README,然后知己commit,不是用[CI SKIP]看下效果


image.png

7是目、執(zhí)行結(jié)果谤饭,這里失敗了,后面再解決


image.png

8胖笛、如果您commit以后并沒有觸發(fā)Drone,需要在gogs查看webhooks時候正常网持,如下圖


image.png

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

image.png

通過drone頁面查看結(jié)果郎任,可以看到clone成功


image.png

而且執(zhí)行的echo命令也成功執(zhí)行


image.png

至此本文實戰(zhàn)結(jié)束

總結(jié)

本文是“基于Docker及Kubernetes構(gòu)建的容器云平臺”系列第十篇,也是最后一篇备籽,如果您看完了整個系列文章舶治,在此感謝。
通過這十篇文章,您應(yīng)該可以構(gòu)建出一個測試環(huán)境的容器平臺霉猛。關(guān)于容器云平臺更多內(nèi)容尺锚,后續(xù)會繼續(xù)分享,盡請持續(xù)關(guān)注韩脏。


image.png

PS:后續(xù)文章會同步到dev.kubeops.net

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末缩麸,一起剝皮案震驚了整個濱河市铸磅,隨后出現(xiàn)的幾起案子赡矢,更是在濱河造成了極大的恐慌,老刑警劉巖阅仔,帶你破解...
    沈念sama閱讀 212,718評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件吹散,死亡現(xiàn)場離奇詭異,居然都是意外死亡八酒,警方通過查閱死者的電腦和手機空民,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,683評論 3 385
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來羞迷,“玉大人界轩,你說我怎么就攤上這事∠挝停” “怎么了浊猾?”我有些...
    開封第一講書人閱讀 158,207評論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長热鞍。 經(jīng)常有香客問我葫慎,道長,這世上最難降的妖魔是什么薇宠? 我笑而不...
    開封第一講書人閱讀 56,755評論 1 284
  • 正文 為了忘掉前任偷办,我火速辦了婚禮,結(jié)果婚禮上澄港,老公的妹妹穿的比我還像新娘椒涯。我一直安慰自己,他們只是感情好回梧,可當(dāng)我...
    茶點故事閱讀 65,862評論 6 386
  • 文/花漫 我一把揭開白布废岂。 她就那樣靜靜地躺著,像睡著了一般漂辐。 火紅的嫁衣襯著肌膚如雪泪喊。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 50,050評論 1 291
  • 那天髓涯,我揣著相機與錄音袒啼,去河邊找鬼。 笑死,一個胖子當(dāng)著我的面吹牛蚓再,可吹牛的內(nèi)容都是我干的滑肉。 我是一名探鬼主播,決...
    沈念sama閱讀 39,136評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼摘仅,長吁一口氣:“原來是場噩夢啊……” “哼靶庙!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起娃属,我...
    開封第一講書人閱讀 37,882評論 0 268
  • 序言:老撾萬榮一對情侶失蹤六荒,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后矾端,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體掏击,經(jīng)...
    沈念sama閱讀 44,330評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,651評論 2 327
  • 正文 我和宋清朗相戀三年秩铆,在試婚紗的時候發(fā)現(xiàn)自己被綠了砚亭。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,789評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡殴玛,死狀恐怖捅膘,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情滚粟,我是刑警寧澤寻仗,帶...
    沈念sama閱讀 34,477評論 4 333
  • 正文 年R本政府宣布,位于F島的核電站坦刀,受9級特大地震影響愧沟,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜鲤遥,卻給世界環(huán)境...
    茶點故事閱讀 40,135評論 3 317
  • 文/蒙蒙 一沐寺、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧盖奈,春花似錦混坞、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,864評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至爹凹,卻和暖如春厨诸,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背禾酱。 一陣腳步聲響...
    開封第一講書人閱讀 32,099評論 1 267
  • 我被黑心中介騙來泰國打工微酬, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留绘趋,地道東北人。 一個月前我還...
    沈念sama閱讀 46,598評論 2 362
  • 正文 我出身青樓颗管,卻偏偏與公主長得像陷遮,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子垦江,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,697評論 2 351