iT邦幫忙

第 12 屆 iT 邦幫忙鐵人賽

DAY 15
0
DevOps

Kubernetes X CICD X DevOps 成就時間管理大師暨薪水強盜系列 第 15

Day15 - CD 之 Pull Mode 介紹: Keel

本文將於賽後同步刊登於筆者部落格
有興趣學習更多 Kubernetes/DevOps/Linux 相關的資源的讀者,歡迎前往閱讀
更多相關科技的技術分享,歡迎追蹤 矽谷牛的耕田筆記

上篇文章中,我們探討了不同類型的部署架構,今天我們就針對最後一種 Pull 的方式來進行一個介紹,同時使用開源專案 keel 來展示一

下這種模式下的操作過程與結果

本文中的圖片都節錄自 Keel官網

介紹

Keel 的官網介紹如下

Keel - automated Kubernetes deployments for the rest of us

Keel 是一款 CD 部署的工具,其實作方式除了我們介紹的 Pull Mode 之外,他也支援 Push Mode 的方式,讓 Container Registry 主動通知 Keel 去進行自動部署。

下圖是一個最快理解 Keel 的運作流程,該圖片有五個步驟,分別是

  1. 修改程式碼推到 Github
  2. 透過 CI pipeline 來產生最後的 Container Image,並且把 Container Image 給推到遠方 Registry
  3. Container Registry 知道有新版出現後,透過 relay 的方式把 web hook 的資訊往下傳遞
  4. 當 Webhook 最終到達 Keel 的 Controller 後, Keel 根據設定來準備更新相關資源
  5. 將差異性更新到 Kubernetes 內

上述的運作方式跟我們前篇提到的 Pull-Mode 不太一樣,因為還是透過 webhook 的方式主動通知 Keel 去更新,但是 Keel 本身也有提供別的機制來實現不同的架構,如同其官方內的文章介紹

Polling

Since only the owners of docker registries can control webhooks - it's often convenient to use polling. Be aware that registries can be rate limited so it's a good practice to set up reasonable polling intervals. While configuration for each provider can be slightly different - each provider has to accept several polling parameters:

如圖上篇文章所說,不是每個 container registry 都能去控管 web hooks 的架構,我們等等的示範中會使用 docker registry 配上 Polling 的機制來實現這種稍微被動一點的更新

此外,相對於 Push mode, Pull 則是透過定期詢問的方式去確認有沒有新版本,因此更新的速度上可能會比 webhook 還來得慢一點。

下圖是比較完整的架構,用來敘述 Keel 整個專案的架構

整個架構圖非常簡單,首先右邊代表的是 Keel Controller 以及控管的 Kubernetes Cluster,其中可以 Keel 下方還有 Helm 的標誌,這意

味者 Keel 對於應用程式可以支援原生的 Yaml 也可以支援用 Helm 控管的應用程式

左邊有三個框架,最上面代表的是 KEEL 支援的 Kubernetes 版本,不論是官方原生, Rancher 或者 Openshift 都支援。

下面則是所支援的 Container Registry 版本,譬如是 Quay, Harbor, Docker 或是其他公有雲的 Cloud Registry。

最下面則是一些通知系統,包含 Slack, Mattermost, Hipchat 等,此外 keel 還可以支援審核機制,當要部署的時候會發通知到 slack 等系統,需要有人按下同意後,才會繼續執行後續的動作。

有更多的興趣可以參閱官方網站

安裝

安裝方面提供兩種做法,可以透過 helm 去安裝或是直接透過 kubectl 安裝原生 yaml 檔案

$ helm repo add keel https://charts.keel.sh
"keel" has been added to your repositories
$ helm repo update
Hang tight while we grab the latest from your chart repositories...
...Successfully got an update from the "keel" chart repository
Update Complete. ⎈Happy Helming!⎈
$ helm upgrade --install keel --namespace=kube-system keel/keel
Release "keel" does not exist. Installing it now.
NAME: keel
LAST DEPLOYED: Sun Sep 13 03:28:06 2020
NAMESPACE: kube-system
STATUS: deployed
REVISION: 1
TEST SUITE: None
NOTES:
1. The keel is getting provisioned in your cluster. After a few minutes, you can run the following to verify.

To verify that keel has started, run:

  kubectl --namespace=kube-system get pods -l "app=keel"

到這邊完畢我們就將 Keel Controller 安裝到 Kubernetes 叢集內了,接下來就來試試看如何使用 Keel 來完成自動部署

示範

接下來的示範流程如下

  1. 透過 Deployment 準備一個自己準備的 Container Image
  2. 讓 Keel 幫忙部署該應用程式
  3. 手動於別的畫面更新 Container Image
  4. 觀察 Keel 的 log 以及 Kubernetes 狀況,確認該 container 有更新

首先,因為 Keel 本身沒有額外的 CRD 去告訴 Keel 到底哪些應用程式想要被 Keel 控管,因此控制的方式就是在應用程式的 Yaml 內增加 label,然後 Keel 的 controller 就會去監聽所有有設定這些規則的應用程式,再根據應用程式的內容來決定如何更新

下面是一個簡單的 deployment 的範例,該範例中我們於 metadata.labels 裡面增加兩個關於 keel 的敘述

apiVersion: apps/v1
kind: Deployment
metadata:
  name: ithome
  namespace: default
  labels:
      name: "ithome"
      keel.sh/policy: all
      keel.sh/trigger: poll
spec:
  replicas: 3
  selector:
    matchLabels:
      app: ithome
  template:
    metadata:
      name: ithome
      labels:
        app: ithome
    spec:
      containers:
        - image: hwchiu/netutils:3.4.5
          name: ithome
  1. keel.sh/policy:
    這邊描述怎樣的 image tag 的變化是認可為有新版,keel 會希望image tag的版本都可以根據 SemVer 的方式使用 $major.$minor.$patch 來描述。 而今天我們使用 all 的含義是三者有任何一個版本更新,我們就會更新,預設會使用最新的版本。
  2. keel.sh/trigger
    這邊描述我們不使用 webhook 的方式,而是改用去定期詢問遠方 image 是否有更新

接下來我們就來部署看看

$ kubectl apply -f deployment.yaml
$ kubectl get deployment ithome -o jsonpath='{.spec.template.spec.containers[0].image}'
hwchiu/netutils:3.4.5

接下來開啟其他視窗,嘗試部署一個全新的 image tag, 其版本必須大於 3.4.5,譬如我們使用 4.5.6 試試看

$ docekr push hwchiu/netutils:4.5.6
....
Successfully tagged hwchiu/netutils:4.5.6
The push refers to repository [docker.io/hwchiu/netutils]
de527d59ee7c: Layer already exists
0c98ba7dbe5c: Layer already exists
64d2e4aaa54c: Layer already exists
0d3833376c2f: Layer already exists
4a048ea09024: Layer already exists
b592b5433bbf: Layer already exists
4.5.6: digest: sha256:f2956ee6b5aafb43ec22aeeda10cfd20b92b3d01d9048908a25ef4430671b8a3 size: 1569
$ kubectl get deployment ithome -o jsonpath='{.spec.template.spec.containers[0].image}'
hwchiu/netutils:4.5.6

不久後就可以觀察到系統上的 image 已經被改變了,此時去觀察中間層的 replicaset,就可以看到有 4.5.6 的出現

$ kubectl get rs -o wide
NAME                DESIRED   CURRENT   READY   AGE     CONTAINERS   IMAGES                  SELECTOR
ithome-7d44545847   3         3         3       2m49s   ithome       hwchiu/netutils:4.5.6   app=ithome,pod-template-hash=7d44545847
ithome-7d5fb6757f   0         0         0       12m     ithome       hwchiu/netutils:3.4.5   app=ithome,pod-template-hash=7d5fb6757f

透過這樣的 Demo 過程,我們算是跑了一個基本的 Pull Mode 的更新,我們透過 Container Image 版本的更新來自動更新 Kubernetes 內部資源的狀態,這中間沒有牽扯到任何 CD Pipeline 的運作。

實際上這種運作模式後來也有一種更好的架構,稱為 GitOps,下篇開始我們就來認真學習一下 GitOps 的概念!


上一篇
Day 14 - CD 與 Kubernetes 的整合
下一篇
Day 16 - GitOps 的介紹
系列文
Kubernetes X CICD X DevOps 成就時間管理大師暨薪水強盜30

尚未有邦友留言

立即登入留言