容器雲平臺No.10~經過gogs+drone+kubernetes實現CI/CD

什麼是CI/CD

持續集成(Continous Intergration,CI)是一種軟件開發實踐,即團隊開發成員常常集成它們的工做,一般每一個成員天天至少集成一次,也就意味着天天可能會發生屢次集成。每次集成都須要經過自動化的編譯、發佈、自動化迴歸測試來驗證,從而儘快地發現集成錯誤。而這些自動化的操做則由CI軟件進行執行。node

持續部署(Continous Delivery,CD)在持續集成的基礎上,將集成後的代碼部署到真實運行環境中(本文指部署到kubernetes集羣)。交付團隊 ->版本控制 ->構建和單元測試 ->自動驗收測試 -> 發佈git

什麼是Drone

Drone 是一個基於Docker容器技術的可擴展的持續集成引擎,用於自動化測試、構建、發佈。每一個構建都在一個臨時的Docker容器中執行,使開發人員可以徹底控制其構建環境並保證隔離。開發者只需在項目中包含 .drone.yml文件,將代碼推送到 git 倉庫,Drone就可以自動化的進行編譯、測試、發佈。github

使用drone實現CD/CD

首先來看下醜陋的圖
容器雲平臺No.10~經過gogs+drone+kubernetes實現CI/CDweb

簡單梳理流程:

一、開發人員向git(gitlab/github/gogs)提交代碼,代碼中必須包含Dockerfile和.drone.yml文件。
二、將代碼commit到遠程倉庫;發佈應用時須要填寫服務類型、服務名稱、資源數量、實例個數等信息
三、gogs觸發drone自動構建
四、Drone的CI流水線中包括了自定義腳本,根據準備好的kubernetes的YAML模板,將其中的變量替換成用戶輸入的選項
生成應用的kubernetes YAML配置文件
五、Drone的CI流水線自動編譯代碼並打包成docker鏡像推送到Harbor鏡像倉庫
六、更新DNS,插入一條DNS記錄,IP地址是ingress節點的IP地址。
七、Drone的CI流水線中自定義腳本調用kubernetes的API,部署應用;更新Ingress的配置,根據新部署的應用的名稱,在ingress的配置文件中增長一條路由信息
接下來,開始實戰docker

部署代碼倉庫gogs

本文使用gogs,固然你能夠選擇gitlab,github等代碼倉庫
一、建立gogs.yamlapi

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

二、執行部署並查看結果瀏覽器

[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

三、瀏覽器打開,並配置gogs,而後就能夠登陸gogs了
容器雲平臺No.10~經過gogs+drone+kubernetes實現CI/CDbash

四、登陸gogs
容器雲平臺No.10~經過gogs+drone+kubernetes實現CI/CD
至此,gogs配置完畢。
Tips:本文的gogs,是測試環境,使用卷類型爲:emptyDir,生產環境最好單獨部署或者使用StorageClass保證數據持久可用性
接下來部署droneapp

部署CI工具Drone

一、編寫drone.yaml文件ssh

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

二、執行部署並查看結果

[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

三、如今就能夠用瀏覽器訪問http://192.168.100.181:31681 ,使用gogs的帳號就能夠登陸drone了
容器雲平臺No.10~經過gogs+drone+kubernetes實現CI/CD
四、登陸後能夠看到,如今並無任何項目,後續再gogs新建項目,就能看到了
容器雲平臺No.10~經過gogs+drone+kubernetes實現CI/CD

部署Drone Runner

Runner的做用是詢問Drone Server,而後執行pipeline,更多信息請查看官網
一、編寫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

二、執行部署並查看結果

[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示例

一、gogs新建項目demo
容器雲平臺No.10~經過gogs+drone+kubernetes實現CI/CD
二、drone上點sync,就能夠看到demo項目
容器雲平臺No.10~經過gogs+drone+kubernetes實現CI/CD
三、激活demo項目,保存
容器雲平臺No.10~經過gogs+drone+kubernetes實現CI/CD
四、在gogs的demo項目中,添加.drone.yml文件,添加一個pipeline
容器雲平臺No.10~經過gogs+drone+kubernetes實現CI/CD
五、提交代碼,可是不觸發CI,Commit的時候填寫[CI SKIP]就能夠跳過觸發CI
容器雲平臺No.10~經過gogs+drone+kubernetes實現CI/CD
若是這裏直接Commit提交代碼,就直接觸發CI功能,Drone就開始執行這個pipeline了
[CI SKIP]的做用就是若是須要修改多個文件,這時候會頗有用;
固然在實際開發過程當中,都是把項目clone到本地,編輯好全部文件,再push到代碼倉庫,這樣就不須要[CI SKIP]了
六、咱們這裏隨便修改 README,而後知己commit,不是用[CI SKIP]看下效果
容器雲平臺No.10~經過gogs+drone+kubernetes實現CI/CD
七、執行結果,這裏失敗了,後面再解決
容器雲平臺No.10~經過gogs+drone+kubernetes實現CI/CD
八、若是您commit之後並無觸發Drone,須要在gogs查看webhooks時候正常,以下圖
容器雲平臺No.10~經過gogs+drone+kubernetes實現CI/CD
九、這裏咱們來解決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
容器雲平臺No.10~經過gogs+drone+kubernetes實現CI/CD
經過drone頁面查看結果,能夠看到clone成功
容器雲平臺No.10~經過gogs+drone+kubernetes實現CI/CD
並且執行的echo命令也成功執行
容器雲平臺No.10~經過gogs+drone+kubernetes實現CI/CD
至此本文實戰結束

總結

本文是「基於Docker及Kubernetes構建的容器雲平臺」系列第十篇,也是最後一篇,若是您看完了整個系列文章,在此感謝。
經過這十篇文章,您應該能夠構建出一個測試環境的容器平臺。關於容器雲平臺更多內容,後續會繼續分享,盡請持續關注。
容器雲平臺No.10~經過gogs+drone+kubernetes實現CI/CD

PS:後續文章會同步到dev.kubeops.net

相關文章
相關標籤/搜索