Incubator4

Incubator4

github
steam
nintendo switch

構建一套完整的 GitOps 生態

這篇文章寫給 DevOps 和想要了解的各位朋友。

前言#

在開始之前,還是先講一下傳統的 GitOps 流程。 使用 git 倉庫配置 cicd 的流水線,
git push 之後根據當前 git sha 構建出一個鏡像,然後 apply 到 kubernetes 中。
Deployment 就會自動更新。

這很簡單,並且也很有用,kubernetes 會自動的滾動更新你的鏡像,但我們會有更多的問題和需求。

  1. 如何只更變資源
    假設我只是做了編排改動,例如增加了副本數量或者增加了資源,它會創建一個新的 git commit。
    從流程上這和提交新的代碼是一樣的,仍然要走一遍 [ci]->build->deploy 的流程。 當然可以配置 pipeline 來做到當 deploy 文件更改的時候不會觸發 build 流程。只有在 src/ 或者 app/ 這樣的目錄下文件更變才需要構建一次鏡像。
    那麼這又會帶來新的問題,剛才說到,我們是根據 git commit sha 作為鏡像 tag 來應用到部署的。假設我提交了一次 a1b2c3 的 commit,但是 skip 了 build,在 deploy 的階段就會出錯,因為找不到 tag 為 a1b2c3 的鏡像。

  2. 如何存放敏感信息
    通常應用會伴隨著一些 DATABASE_URL 或者 ACCESS_TOKEN 之類的敏感信息,這些不應該放到 git 倉庫中,即使是私有或者私域倉庫。
    這些通常會以 kubernetes secret 的形式存在,而 secret 只是簡單的 base64 加密,約等於明文存儲。當然我們可以把 secret 單獨存放,或者直接手動應用到集群中。
    但是這麼做會導致,一方面,整個應用的發布和 secret 割裂,另一方面無法有效的管理。

ArgoCD#

Argocd 是一個 CD 工具,官方的介紹如下

What Is Argo CD?
Argo CD is a declarative, GitOps continuous delivery tool for Kubernetes.

ArgoCD 採用 Application (後續簡稱 app) 級別的單位來管理,一般來說,一個 app 對應單個集群中的單個應用。

ArgoCD 使用監聽 git 倉庫資源的形式管理 app,它支持 Helm/Kustomize/Directory 等多種管理 kubernetes 資源的方式。簡單來說,只要把需要 deploy 的文件放在 git 倉庫裡,並且正確的配置 app,argocd 就會監聽 deploy 的更變。

例如

OK, 到現在為止,我們解決了一個問題 —— 《如何在不重新構建鏡像下更變資源》

Secret management#

https://argo-cd.readthedocs.io/en/stable/operator-manual/secret-management/

ArgoCD 沒有強制管理 secret 的方案,上述的鏈接中提到推薦和支持一部分的 secret 管理方式,本文會使用 Hashicorp Vault 和 argocd-vault-plugin 作為工具來管理。

Vault#

Vault 是一個 Hashicorp 出品的支持 KV 鍵值對的 secret-based engine。 大概可以理解為 server 版本的 1password。由於篇幅有限,這裡不會多贅述 vault 的安裝和配置方式。

假設現在我們把 secret 存在 vault 的 kv/<namepsace>/<app> 路徑下,例如 DATABASE_URL 等。

vault 自帶的 pod inject 由於不滿足使用需求,這裡也不多贅述。
我們希望有一個可以同步 vault secret 到 kubernetes secret 的方案。

argocd-vault-plugin#

argocd-vault-plugin 是一個 argocd 用於訪問 vault 的插件,以下簡稱 avp。

avp 的主要作用就是可以把相應 template 轉化成 vault secret

例如我有一個 yaml

kind: Secret
apiVersion: v1
metadata:
  name: example-secret
  annotations:
    avp.kubernetes.io/path: "path/to/secret"
type: Opaque
data:
  password: <password-vault-key>

使用 avp 處理過之後再應用到集群中,就是實際的數據,而不是 template。
具體可以看:https://argocd-vault-plugin.readthedocs.io/en/stable/howitworks/

然而, 上面雖然講到了 argocd 支持多種資源編排工具,但是它們是不會默認啟用 avp。
想要使用 avp ,需要自定義插件,也就是使用 plugin 的方式來使用。

plugin 本身只是一個預處理腳本,在 AVP Install 中的一段 github yaml 文件示例

      discover:
        find:
          command:
            - find
            - "."
            - -name
            - kustomization.yaml
      generate:
        command:
          - sh
          - "-c"
          - "kustomize build . | argocd-vault-plugin generate -"

這裡可以看到, 有一個 discover 來發現 一個 kustomization.yaml,並且在 build 之後使用 avp 插件生成。

特別說明 由於 helm 和 kustomize 使用的插件不一樣,按照官方的插件示例在使用的時候需要指定 plugin 的名稱
例如 plugin = avp-helm 和 plugin = avp-kustomize 否則會報錯。

由於 kustomize 在 4.x 的版本中在 kustomization 中支持 helm-charts 的語法,不過需要手動使用 --enable-helm flags,所以我們自定義了插件,部分代碼如下所示。

      avp-kustomize:
        allowConcurrency: true
        discover:
          find:
            command:
              - sh
              - "-c"
              - "find . -name kustomization.yaml"
        generate:
          command:
            - sh
            - "-c"
            - "kustomize edit set annotation \"github.com/url:${ARGOCD_ENV_APP_REPO}\"; kustomize edit set image ${ARGOCD_ENV_IMAGE_NAME}:${ARGOCD_ENV_IMAGE_TAG}; kustomize build --enable-helm . | argocd-vault-plugin -s ${ARGOCD_ENV_AVP_SECRET} generate -"
        lockRepo: false

https://argo-cd.readthedocs.io/en/latest/operator-manual/upgrading/2.3-2.4/#update-plugins-to-use-newly-prefixed-environment-variables
根據文章所示,我們需要在傳入 plugin 的 env 中加上 ARGO_ENV 的 prefix

在這裡我們加入了四個環境變量,分別是

  • IMAGE_NAME 鏡像名稱
  • IMAGE_TAG 鏡像 tag
  • AVP_SECRET 配置 vault 的憑據
  • APP_REPO git 倉庫地址

git 倉庫地址會被用於一個 global annotations 用來在集群中查看 某個資源會屬於哪個倉庫。

到這裡,我們已經完成了大部分了。

Git CI#

不管用的是 github action/gitlab ci/drone 等任意流水線,都能做到相應的配置方式。

我們在 CI 中應該配置兩個階段,build 和 deploy

build 階段用於 build docker 鏡像 和 push 到鏡像倉庫。
deploy 階段是一個更新 / 創建 argocd app 的過程。

主要重點介紹 deploy 階段, 它會使用 argocd 的 cli 來更新或者創建鏡像的 tag。
example:

argocd app create  {your_app}  \
  --repo https://github.com/{git_url} \
  --path {your_repo_pass} \
  --project {your_project} \
  --dest-name {deploy_cluster} \
  --dest-namespace {cluster_ns} \
  --config-management-plugin=avp-kustomize \
  --revision {revision} \
  --plugin-env AVP_SECRET={secret_name} \
  --plugin-env APP_REPO={git_url} \
  --plugin-env IMAGE_NAME={image.name} \
  --plugin-env IMAGE_TAG={image.tag} \
  --sync-policy automated \
  --sync-option ApplyOutOfSyncOnly=true,ServerSideApply=true \
  --upsert

這將會創建一個 argocd app。如此一來,argocd 將會自己監聽 git repo,當你更變 deploy 文件後,由於應用到 app 的 image name 和 tag 沒有變化,可以以之前的鏡像生成新的部署。

因此現在可以在 git pipeline 中配置一些 觸發條件,排除 deploy 文件或者只包含代碼文件。

總結#

這篇文章主要講了如何把 argocd,vault,argocd-vault-plugin,ci 串聯起來使用,構建一個相對比較完善的 gitops 生態,可能比不上成熟的商業方案,但是開源的組件自由搭配,能夠找到一個最佳的實踐形式。

例如 CI 和 Git 倉庫沒有任何的限定, 使用 vault 和 avp 也只是我的方案,在 argocd 中提到的任何管理 secret 的方式,以 plugin 的形式使用都是可以的。

載入中......
此文章數據所有權由區塊鏈加密技術和智能合約保障僅歸創作者所有。