這篇文章寫給 DevOps 和想要了解的各位朋友。
前言#
在開始之前,還是先講一下傳統的 GitOps 流程。 使用 git 倉庫配置 cicd 的流水線,
git push 之後根據當前 git sha 構建出一個鏡像,然後 apply 到 kubernetes 中。
Deployment 就會自動更新。
這很簡單,並且也很有用,kubernetes 會自動的滾動更新你的鏡像,但我們會有更多的問題和需求。
-
如何只更變資源
假設我只是做了編排改動,例如增加了副本數量或者增加了資源,它會創建一個新的 git commit。
從流程上這和提交新的代碼是一樣的,仍然要走一遍[ci]->build->deploy
的流程。 當然可以配置 pipeline 來做到當 deploy 文件更改的時候不會觸發 build 流程。只有在 src/ 或者 app/ 這樣的目錄下文件更變才需要構建一次鏡像。
那麼這又會帶來新的問題,剛才說到,我們是根據 git commit sha 作為鏡像 tag 來應用到部署的。假設我提交了一次a1b2c3
的 commit,但是 skip 了 build,在 deploy 的階段就會出錯,因為找不到 tag 為a1b2c3
的鏡像。 -
如何存放敏感信息
通常應用會伴隨著一些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 的形式使用都是可以的。