在 Kubernetes 上部署 Spinnaker

  • 2020 年 2 月 26 日
  • 筆記

Spinnaker 是一種持續交付平台,最初由 Netflix 開發,用於快速、可靠地發布軟體變更。Spinnaker 使開發人員可以更輕鬆地專註於編寫程式碼,而無需擔心底層的雲基礎設施,它可以和 Jenkins 以及其他流行的構建工具無縫集成。很早就想要體驗下 Spinnaker 了,但是由於 GFW 的原因嘗試了很多次都無功而返,這次解決了代理的問題終於順利的在 Kubernetes 集群上成功部署上了 Spinnaker。

本文將使用 helm3 來為大家演示在 Kubernetes 集群上安裝 Spinnaker,對應的環境版本如下所示:

$ helm version  version.BuildInfo{Version:"v3.0.1", GitCommit:"7c22ef9ce89e0ebeb7125ba2ebf7d421f3e82ffa", GitTreeState:"clean", GoVersion:"go1.13.4"}  $ kubectl version  Client Version: version.Info{Major:"1", Minor:"14", GitVersion:"v1.14.2", GitCommit:"66049e3b21efe110454d67df4fa62b08ea79a19b", GitTreeState:"clean", BuildDate:"2019-05-16T18:55:03Z", GoVersion:"go1.12.5", Compiler:"gc", Platform:"darwin/amd64"}  Server Version: version.Info{Major:"1", Minor:"16", GitVersion:"v1.16.2", GitCommit:"c97fe5036ef3df2967d086711e6c0c405941e14b", GitTreeState:"clean", BuildDate:"2019-10-15T19:09:08Z", GoVersion:"go1.12.10", Compiler:"gc", Platform:"linux/amd64"}

對於 Helm3 的安裝配置其實很簡單,只需要在 kubectl 所在節點上面安裝上 Helm3 客戶端即可,默認就會讀取 kubeconfig 文件來訪問集群。我們這裡使用微軟提供的 helm chart 倉庫源:

$  helm repo ls  NAME            URL  stable          http://mirror.azure.cn/kubernetes/charts/  $ helm repo update  Hang tight while we grab the latest from your chart repositories...  ...Successfully got an update from the "stable" chart repository  Update Complete. ⎈ Happy Helming!⎈

由於我們這裡使用的是 Kubernetes 1.16.x 版本,該版本之後將之前很多資源對象的一些舊的 API 廢棄掉了,比如 Deployment 只能使用 apps/v1 這個版本了,而我們這裡要使用的 Spinnaker 對應的 chart 包目前還是使用的以前的 API 版本,所以我們需要手動下載下來做一次更改:

$ helm fetch stable/spinnaker  $ tar -xvf spinnaker-1.23.2.tgz

然後將 spinnaker chart 模板中的 Deployment、StatefulSet 這些資源對象的 apiVersion 更改成 apps/v1,也需要記住如果是 Deployment 還需要添加上 selector.matchLabels 欄位,大家可以直接使用我更改後的 chart 模板 https://github.com/cnych/spinnaker-helm。

在 chart 模板的 values.yaml 文件中指定了 halyard.spinnakerVersion=1.17.6,這還是因為 apiVersion 版本的問題,該版本以上就可以兼容 Kubernetes v1.16.x 的集群,另外將默認的 gcr.io 的鏡像替換成了微軟的鏡像源 gcr.azk8s.cn,此外還有一個非常重要的就是存儲的指定,這裡我們創建了一個 StorageClass 的資源對象來提供存儲,我這裡是創建的一個 CephRBD 類型的存儲 rook-ceph-block,當然任何可用的 StorageClass 資源對象都是可以的:

apiVersion: storage.k8s.io/v1  kind: StorageClass  metadata:     name: rook-ceph-block  provisioner: rook-ceph.rbd.csi.ceph.com  reclaimPolicy: Retain  parameters:      # clusterID 是 rook 集群運行的命名空間      clusterID: rook-ceph        # 指定存儲池      pool: k8s-test-pool        # RBD image (實際的存儲介質) 格式. 默認為 "2".      imageFormat: "2"        # RBD image 特性. CSI RBD 現在只支援 `layering` .      imageFeatures: layering        # Ceph 管理員認證資訊,這些都是在 clusterID 命名空間下面自動生成的      csi.storage.k8s.io/provisioner-secret-name: rook-csi-rbd-provisioner      csi.storage.k8s.io/provisioner-secret-namespace: rook-ceph      csi.storage.k8s.io/node-stage-secret-name: rook-csi-rbd-node      csi.storage.k8s.io/node-stage-secret-namespace: rook-ceph      # 指定 volume 的文件系統格式,如果不指定, csi-provisioner 會默認設置為 `ext4`      csi.storage.k8s.io/fstype: ext4

需要為 halyard、redis、mino 都指定對應的存儲,當然直接指定一個合適的 PVC 也是可以的,這裡可以根據實際情況決定:

halyard:    ...    persistence:      storageClass: rook-ceph-block  ...  redis:    ...    master:      persistence:        storageClass: rook-ceph-block  ...  minio:    ...    persistence:      storageClass: rook-ceph-block  ...

接下來最重要的一步就是必須要為 halyard 配置代理,所以繼續下去的前提是你需要配置一個在 Kubernetes 的 Pod 中可以訪問的代理,比如我這裡的代理地址為 10.151.30.11:8118,則需要配置如下所示的 JAVA_OPTS 這個環境變數:

halyard:    env:      - name: JAVA_OPTS        value: '"-Djava.security.egd=file:/dev/./urandom" "-Dhttp.proxyHost=10.151.30.11" "-Dhttps.proxyHost=10.151.30.11" "-Dhttp.proxyPort=8118" "-Dhttps.proxyPort=8118" "-Dhttp.nonProxyHosts="localhost|*.spinnaker.com""'

獲取上面我修改過後的 Spinnaker 的 Chart 模板,將 values.yaml 文件中上面對應的配置替換成自己對應的配置即可。

$ git clone https://github.com/cnych/spinnaker-helm spinnaker  $ kubectl create ns spinnaker  # 安裝 spinnaker  $ helm install spinnaker --namespace spinnaker ./spinnaker

由於安裝過程非常耗時,可能上面的 helm install 的過程可能會有超時提示,這個可以忽略:

$ helm ls -n spinnaker  NAME            NAMESPACE       REVISION        UPDATED                                 STATUS  CHART            APP VERSION  spinnaker       spinnaker       1               2020-02-17 19:28:02.644552 +0800 CST    failed  spinnaker-1.23.2 1.16.2

安裝完成後最開始會生成如下所示的幾個 Pod,其中 spinnaker-install-using-hal-th8qf 就是用來去真正安裝 Spinnaker 的一個 Job 任務:

$ kubectl get pods -n spinnaker  spinnaker-install-using-hal-th8qf   0/1     Completed   0          17h  spinnaker-minio-86f5b8785-bkjfq     1/1     Running     0          17h  spinnaker-redis-master-0            1/1     Running     0          17h  spinnaker-spinnaker-halyard-0       1/1     Running     0          17h

不過由於在安裝 Spinnaker 的過程中會使用 gcr.io 的鏡像,所以會看到很多 Pod 鏡像拉取失敗的錯誤,這個時候我們可以手動編輯 Deployment 對象更改鏡像地址:

$ kubectl get deploy -n spinnaker  NAME               READY   UP-TO-DATE   AVAILABLE   AGE  spin-clouddriver   0/1     1            0           17h  spin-deck          0/1     1            0           17h  spin-echo          0/1     1            0           17h  spin-front50       0/1     1            0           17h  spin-gate          0/1     1            0           17h  spin-igor          0/1     1            0           17h  spin-orca          0/1     1            0           17h  spin-rosco         0/1     1            0           17h  spinnaker-minio    1/1     1            1           17h

比如修改 spin-deck 這個 Deployment 資源對象的鏡像地址:

$ kubectl edit deploy spin-deck -n spinnaker  # 然後在打開的編輯中將 gcr.io 替換成 gcr.azk8s.cn

用同樣的方法替換其他資源對象,正常替換過後隔一段時間就可以正常啟動 Pod 了,最終的 Pod 列表如下所示:

$ kubectl get pods -n spinnaker  NAME                                READY   STATUS      RESTARTS   AGE  spin-clouddriver-76b8989b4f-cjw8r   1/1     Running     0          17h  spin-deck-5fd7b64b77-fnl5r          1/1     Running     0          17h  spin-echo-644c4cb6b6-gh98w          1/1     Running     0          17h  spin-front50-9d99cd697-cqbxb        1/1     Running     0          17h  spin-gate-6c49bccb6f-nhbzx          1/1     Running     0          17h  spin-igor-7c84d9bcb-rltw7           1/1     Running     0          17h  spin-orca-b5944685-wbm5p            1/1     Running     0          17h  spin-rosco-6d5f9c8f55-g89hq         1/1     Running     0          17h  spinnaker-install-using-hal-th8qf   0/1     Completed   0          17h  spinnaker-minio-86f5b8785-bkjfq     1/1     Running     0          17h  spinnaker-redis-master-0            1/1     Running     0          17h  spinnaker-spinnaker-halyard-0       1/1     Running     0          17h

到這裡就證明我們的 Spinnaker 已經安裝成功了,這個時候如果我們想要把 Spinnaker 暴露給外部用戶訪問,當然可以創建一個 NodePort 類型的 Service,或者創建一個 Ingress 資源對象即可,其實上面的 chart 模板中我們就可以通過配置指定 Ingress 資源對象的參數。由於我這裡使用的是 Traefik2.1 版本,所以單獨創建一個 IngressRoute 資源對象來暴露服務:

apiVersion: traefik.containo.us/v1alpha1  kind: IngressRoute  metadata:    name: spin-deck-https    namespace: spinnaker  spec:    entryPoints:    - websecure    routes:    - match: Host(`spinnaker.qikqiak.com`)      kind: Rule      services:      - name: spin-deck        port: 9000    tls:      certResolver: ali      domains:      - main: "*.qikqiak.com"  ---  apiVersion: traefik.containo.us/v1alpha1  kind: Middleware  metadata:    name: redirect-https    namespace: spinnaker  spec:    redirectScheme:      scheme: https  ---  apiVersion: traefik.containo.us/v1alpha1  kind: IngressRoute  metadata:    name: spin-deck-http    namespace: spinnaker  spec:    entryPoints:    - web    routes:    - match: Host(`spinnaker.qikqiak.com`)      kind: Rule      services:      - name: spin-deck        port: 9000      middlewares:      - name: redirect-https

直接創建上面的資源對象即可,對 Traefik2 使用不是很熟悉的,可以查看前面的文章 一文搞懂 Traefik2.1 的使用 了解更多,然後直接對域名 spinnaker.qikqiak.com 做好 DNS 解析即可在瀏覽器中訪問 Spinnaker 了:

到這裡就安裝成功了,當然這只是萬里長征的第一步呢,後面我們再慢慢的去了解 Spinnaker 到底有哪些值得我們關注的功能。

Tags: