GitOps 工具 Argo CD 實戰教程
Argo CD 遵循 GitOps 模式,使用 Git 倉庫作爲定義所需應用程序狀態的真實來源,Argo CD 支持多種 Kubernetes 清單:
-
kustomize
-
helm charts
-
ksonnet applications
-
jsonnet files
-
Plain directory of YAML/json manifests
-
Any custom config management tool configured as a config management plugin
Argo CD 可在指定的目標環境中自動部署所需的應用程序狀態,應用程序部署可以在 Git 提交時跟蹤對分支、標籤的更新,或固定到清單的指定版本。
架構
Argo CD 是通過一個 Kubernetes 控制器來實現的,它持續 watch 正在運行的應用程序並將當前的實時狀態與所需的目標狀態( Git 存儲庫中指定的)進行比較。已經部署的應用程序的實際狀態與目標狀態有差異,則被認爲是 OutOfSync
狀態,Argo CD 會報告顯示這些差異,同時提供工具來自動或手動將狀態同步到期望的目標狀態。在 Git 倉庫中對期望目標狀態所做的任何修改都可以自動應用反饋到指定的目標環境中去。
下面簡單介紹下 Argo CD 中的幾個主要組件:
API 服務:API 服務是一個 gRPC/REST 服務,它暴露了 Web UI、CLI 和 CI/CD 系統使用的接口,主要有以下幾個功能:
-
應用程序管理和狀態報告
-
執行應用程序操作(例如同步、回滾、用戶定義的操作)
-
存儲倉庫和集羣憑據管理(存儲爲 K8S Secrets 對象)
-
認證和授權給外部身份提供者
-
RBAC
-
Git webhook 事件的偵聽器 / 轉發器
倉庫服務:存儲倉庫服務是一個內部服務,負責維護保存應用程序清單 Git 倉庫的本地緩存。當提供以下輸入時,它負責生成並返回 Kubernetes 清單:
-
存儲 URL
-
revision 版本(commit、tag、branch)
-
應用路徑
-
模板配置:參數、ksonnet 環境、helm values.yaml 等
應用控制器:應用控制器是一個 Kubernetes 控制器,它持續 watch 正在運行的應用程序並將當前的實時狀態與所期望的目標狀態( repo 中指定的)進行比較。它檢測應用程序的 OutOfSync
狀態,並採取一些措施來同步狀態,它負責調用任何用戶定義的生命週期事件的鉤子(PreSync、Sync、PostSync)。
功能
-
自動部署應用程序到指定的目標環境
-
支持多種配置管理 / 模板工具(Kustomize、Helm、Ksonnet、Jsonnet、plain-YAML)
-
能夠管理和部署到多個集羣
-
SSO 集成(OIDC、OAuth2、LDAP、SAML 2.0、GitHub、GitLab、Microsoft、LinkedIn)
-
用於授權的多租戶和 RBAC 策略
-
回滾 / 隨時回滾到 Git 存儲庫中提交的任何應用配置
-
應用資源的健康狀況分析
-
自動配置檢測和可視化
-
自動或手動將應用程序同步到所需狀態
-
提供應用程序活動實時視圖的 Web UI
-
用於自動化和 CI 集成的 CLI
-
Webhook 集成(GitHub、BitBucket、GitLab)
-
用於自動化的 AccessTokens
-
PreSync、Sync、PostSync Hooks,以支持複雜的應用程序部署(例如藍 / 綠和金絲雀發佈)
-
應用程序事件和 API 調用的審計
-
Prometheus 監控指標
-
用於覆蓋 Git 中的 ksonnet/helm 參數
核心概念
-
Application:應用,一組由資源清單定義的 Kubernetes 資源,這是一個 CRD 資源對象
-
Application source type:用來構建應用的工具
-
Target state:目標狀態,指應用程序所需的期望狀態,由 Git 存儲庫中的文件表示
-
Live state:實時狀態,指應用程序實時的狀態,比如部署了哪些 Pods 等真實狀態
-
Sync status:同步狀態表示實時狀態是否與目標狀態一致,部署的應用是否與 Git 所描述的一樣?
-
Sync:同步指將應用程序遷移到其目標狀態的過程,比如通過對 Kubernetes 集羣應用變更
-
Sync operation status:同步操作狀態指的是同步是否成功
-
Refresh:刷新是指將 Git 中的最新代碼與實時狀態進行比較,弄清楚有什麼不同
-
Health:應用程序的健康狀況,它是否正常運行?能否爲請求提供服務?
-
Tool:工具指從文件目錄創建清單的工具,例如 Kustomize 或 Ksonnet 等
-
Configuration management tool:配置管理工具
-
Configuration management plugin:配置管理插件
安裝
當然前提是需要有一個 kubectl 可訪問的 Kubernetes 的集羣,直接使用下面的命令即可,這裏我們安裝最新的穩定版 v2.4.9:
$ kubectl create namespace argocd
$ kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/v2.4.9/manifests/install.yaml
如果你要用在生產環境,則可以使用下面的命令部署一個 HA 高可用的版本:
$ kubectl create namespace argocd
$ kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/v2.4.9/manifests/ha/install.yaml
這將創建一個新的命名空間 argocd,Argo CD 的服務和應用資源都將部署到該命名空間。
$ kubectl get pods -n argocd
NAME READY STATUS RESTARTS AGE
argocd-application-controller-0 1/1 Running 0 103s
argocd-applicationset-controller-68b9bdbd8b-jzcpf 1/1 Running 0 103s
argocd-dex-server-6b7745757-6mxwk 1/1 Running 0 103s
argocd-notifications-controller-5b56f6f7bb-jqpng 1/1 Running 0 103s
argocd-redis-f4cdbff57-dr8jc 1/1 Running 0 103s
argocd-repo-server-c4f79b4d6-7nh6n 1/1 Running 0 103s
argocd-server-895675597-fr42g 1/1 Running 0 103s
如果你對 UI、SSO、多集羣管理這些特性不感興趣,只想把應用變更同步到集羣中,那麼你可以使用
--disable-auth
標誌來禁用認證,可以通過命令kubectl patch deploy argocd-server -n argocd -p '[{"op": "add", "path": "/spec/template/spec/containers/0/command/-", "value": "--disable-auth"}]' --type json
來實現。
然後我們可以在本地安裝 CLI 工具方便操作 Argo CD,我們可以在 Argo CD Git 倉庫發佈頁面查看最新版本的 Argo CD 或運行以下命令來獲取版本:
VERSION=$(curl --silent "https://api.github.com/repos/argoproj/argo-cd/releases/latest" | grep '"tag_name"' | sed -E 's/.*"([^"]+)".*/\1/')
VERSION
在下面的命令中替換爲你要下載的 Argo CD 版本:
$ curl -sSL -o /usr/local/bin/argocd https://github.com/argoproj/argo-cd/releases/download/$VERSION/argocd-linux-amd64
爲 argocd CLI 賦予可執行權限:
$ chmod +x /usr/local/bin/argocd
現在我們就可以使用 argocd
命令了。如果你是 Mac,則可以直接使用 brew install argocd
進行安裝。
Argo CD 會運行一個 gRPC 服務(由 CLI 使用)和 HTTP/HTTPS 服務(由 UI 使用),這兩種協議都由 argocd-server
服務在以下端口進行暴露:
-
443 - gRPC/HTTPS
-
80 - HTTP(重定向到 HTTPS)
我們可以通過配置 Ingress 的方式來對外暴露服務,其他 Ingress 控制器的配置可以參考官方文檔 https://argo-cd.readthedocs.io/en/stable/operator-manual/ingress/ 進行配置。
Argo CD 在同一端口 (443) 上提供多個協議 (gRPC/HTTPS),所以當我們爲 argocd 服務定義單個 nginx ingress 對象和規則的時候有點麻煩,因爲 nginx.ingress.kubernetes.io/backend -protocol
這個 annotation 只能接受一個後端協議(例如 HTTP、HTTPS、GRPC、GRPCS)。
爲了使用單個 ingress 規則和主機名來暴露 Argo CD APIServer,必須使用 nginx.ingress.kubernetes.io/ssl-passthrough
這個 annotation 來傳遞 TLS 連接並校驗 Argo CD APIServer 上的 TLS。
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: argocd-server-ingress
namespace: argocd
annotations:
nginx.ingress.kubernetes.io/force-ssl-redirect: "true"
nginx.ingress.kubernetes.io/ssl-passthrough: "true"
spec:
ingressClassName: nginx
rules:
- host: argocd.k8s.local
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: argocd-server
port:
name: https
上述規則在 Argo CD APIServer 上校驗 TLS,該服務器檢測到正在使用的協議,並做出適當的響應。請注意,nginx.ingress.kubernetes.io/ssl-passthrough
註解要求將 --enable-ssl-passthrough
標誌添加到 nginx-ingress-controller
的命令行參數中。
由於 ingress-nginx
的每個 Ingress 對象僅支持一個協議,因此另一種方法是定義兩個 Ingress 對象。一個用於 HTTP/HTTPS,另一個用於 gRPC。
如下所示爲 HTTP/HTTPS 的 Ingress 對象:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: argocd-server-http-ingress
namespace: argocd
annotations:
nginx.ingress.kubernetes.io/force-ssl-redirect: "true"
nginx.ingress.kubernetes.io/backend-protocol: "HTTP"
spec:
ingressClassName: nginx
rules:
- http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: argocd-server
port:
name: http
host: argocd.k8s.local
tls:
- hosts:
- argocd.k8s.local
secretName: argocd-secret # do not change, this is provided by Argo CD
gRPC 協議對應的 Ingress 對象如下所示:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: argocd-server-grpc-ingress
namespace: argocd
annotations:
nginx.ingress.kubernetes.io/backend-protocol: "GRPC"
spec:
ingressClassName: nginx
rules:
- http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: argocd-server
port:
name: https
host: grpc.argocd.k8s.local
tls:
- hosts:
- grpc.argocd.k8s.local
secretName: argocd-secret # do not change, this is provided by Argo CD
然後我們需要在禁用 TLS 的情況下運行 APIServer。編輯 argocd-server 這個 Deployment 以將 --insecure
標誌添加到 argocd-server 命令,或者簡單地在 argocd-cmd-params-cm
ConfigMap 中設置 server.insecure: "true"
即可。
創建完成後,我們就可以通過 argocd.k8s.local
來訪問 Argo CD 服務了,不過需要注意我們這裏配置的證書是自簽名的,所以在第一次訪問的時候會提示不安全,強制跳轉即可。
默認情況下 admin
帳號的初始密碼是自動生成的,會以明文的形式存儲在 Argo CD 安裝的命名空間中名爲 argocd-initial-admin-secret
的 Secret 對象下的 password
字段下,我們可以用下面的命令來獲取:
$ kubectl -n argocd get secret argocd-initial-admin-secret -o jsonpath="{.data.password}" | base64 -d && echo
使用用戶名 admin
和上面輸出的密碼即可登錄 Dashboard。
同樣我們也可以通過 ArgoCD CLI 命令行工具進行登錄:
$ argocd login grpc.argocd.k8s.local
WARNING: server certificate had error: x509: “Kubernetes Ingress Controller Fake Certificate” certificate is not trusted. Proceed insecurely (y/n)? y
Username: admin
Password:
'admin:login' logged in successfully
Context 'grpc.argocd.k8s.local' updated
需要注意的是這裏登錄的地址爲 gRPC 暴露的服務地址。
CLI 登錄成功後,可以使用如下所示命令更改密碼:
$ argocd account update-password
*** Enter current password:
*** Enter new password:
*** Confirm new password:
Password updated
Context 'argocd.k8s.local' updated
$ argocd version
argocd: v2.4.9+1ba9008
BuildDate: 2022-08-11T15:41:08Z
GitCommit: 1ba9008536b7e61414784811c431cd8da356065e
GitTreeState: clean
GoVersion: go1.18.5
Compiler: gc
Platform: darwin/arm64
argocd-server: v2.4.9+1ba9008
BuildDate: 2022-08-11T15:22:41Z
GitCommit: 1ba9008536b7e61414784811c431cd8da356065e
GitTreeState: clean
GoVersion: go1.18.5
Compiler: gc
Platform: linux/amd64
Kustomize Version: v4.4.1 2021-11-11T23:36:27Z
Helm Version: v3.8.1+g5cb9af4
Kubectl Version: v0.23.1
Jsonnet Version: v0.18.0
配置集羣
由於 Argo CD 支持部署應用到多集羣,所以如果你要將應用部署到外部集羣的時候,需要先將外部集羣的認證信息註冊到 Argo CD 中,如果是在內部部署(運行 Argo CD 的同一個集羣,默認不需要配置),直接使用 https://kubernetes.default.svc
作爲應用的 K8S APIServer 地址即可。
首先列出當前 kubeconfig
中的所有集羣上下文:
$ kubectl config get-contexts -o name
從列表中選擇一個上下文名稱並將其提供給 argocd cluster add CONTEXTNAME
,比如對於 kind-kind
上下文,運行:
$ argocd cluster add kind-kind
創建應用
Git 倉庫 https://github.com/argoproj/argocd-example-apps.git 是一個包含留言簿應用程序的示例庫,我們可以用該應用來演示 Argo CD 的工作原理。
通過 CLI 創建應用
我們可以通過 argocd app create xxx
命令來創建一個應用:
$ argocd app create --help
Create an application
Usage:
argocd app create APPNAME [flags]
Examples:
# Create a directory app
argocd app create guestbook --repo https://github.com/argoproj/argocd-example-apps.git --path guestbook --dest-namespace default --dest-server https://kubernetes.default.svc --directory-recurse
# Create a Jsonnet app
argocd app create jsonnet-guestbook --repo https://github.com/argoproj/argocd-example-apps.git --path jsonnet-guestbook --dest-namespace default --dest-server https://kubernetes.default.svc --jsonnet-ext-str replicas=2
# Create a Helm app
argocd app create helm-guestbook --repo https://github.com/argoproj/argocd-example-apps.git --path helm-guestbook --dest-namespace default --dest-server https://kubernetes.default.svc --helm-set replicaCount=2
# Create a Helm app from a Helm repo
argocd app create nginx-ingress --repo https://charts.helm.sh/stable --helm-chart nginx-ingress --revision 1.24.3 --dest-namespace default --dest-server https://kubernetes.default.svc
# Create a Kustomize app
argocd app create kustomize-guestbook --repo https://github.com/argoproj/argocd-example-apps.git --path kustomize-guestbook --dest-namespace default --dest-server https://kubernetes.default.svc --kustomize-image gcr.io/heptio-images/ks-guestbook-demo:0.1
# Create a app using a custom tool:
argocd app create kasane --repo https://github.com/argoproj/argocd-example-apps.git --path plugins/kasane --dest-namespace default --dest-server https://kubernetes.default.svc --config-management-plugin kasane
Flags:
......
直接執行如下所示命令即可:
$ argocd app create guestbook --repo https://github.com/argoproj/argocd-example-apps.git --path guestbook --dest-server https://kubernetes.default.svc --dest-namespace default
application 'guestbook' created
通過 UI 創建應用
除了可以通過 CLI 工具來創建應用,我們也可以通過 UI 界面來創建,定位到 argocd.k8s.local
頁面,登錄後,點擊 +New App
新建應用按鈕,如下圖:
將應用命名爲 guestbook,使用 default project,並將同步策略設置爲 Manual
:
然後在下面配置 Repository URL
爲 https://github.com/argoproj/argocd-example-apps.git,由於某些原因我們這裏使用的是一個 GitHub 倉庫加速地址 https://github.91chi.fun/https://github.com/cnych/argocd-example-apps.git
,將 Revision 設置爲 HEAD,並將路徑設置爲 guestbook。然後下面的 Destination 部分,將 cluster 設置爲 inCluster
和 namespace 爲 default:
填寫完以上信息後,點擊頁面上方的 Create 安裝,即可創建 guestbook 應用,創建完成後可以看到當前應用的處於 OutOfSync
狀態:
Argo CD 默認情況下每 3 分鐘會檢測 Git 倉庫一次,用於判斷應用實際狀態是否和 Git 中聲明的期望狀態一致,如果不一致,狀態就轉換爲 OutOfSync
。默認情況下並不會觸發更新,除非通過 syncPolicy
配置了自動同步。
通過 CRD 創建
除了可以通過 CLI 和 Dashboard 可以創建 Application 之外,其實也可以直接通過聲明一個 Application
的資源對象來創建一個應用,如下所示:
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: guestbook
spec:
destination:
name: ""
namespace: default
server: "https://kubernetes.default.svc"
source:
path: guestbook
repoURL: "https://github.com/cnych/argocd-example-apps"
targetRevision: HEAD
project: default
syncPolicy:
automated: null
部署應用
由於上面我們在創建應用的時候使用的同步策略爲 Manual
,所以應用創建完成後沒有自動部署,需要我們手動去部署應用。同樣可以通過 CLI 和 UI 界面兩種同步方式。
使用 CLI 同步
應用創建完成後,我們可以通過如下所示命令查看其狀態:
$ argocd app get guestbook
Name: guestbook
Project: default
Server: https://kubernetes.default.svc
Namespace: default
URL: https://grpc.argocd.k8s.local/applications/guestbook
Repo: https://github.91chi.fun/https://github.com/cnych/argocd-example-apps.git
Target: HEAD
Path: guestbook
SyncWindow: Sync Allowed
Sync Policy: <none>
Sync Status: OutOfSync from HEAD (67bda3d)
Health Status: Missing
GROUP KIND NAMESPACE NAME STATUS HEALTH HOOK MESSAGE
Service default guestbook-ui OutOfSync Missing
apps Deployment default guestbook-ui OutOfSync Missing
應用程序狀態爲初始 OutOfSync
狀態,因爲應用程序尚未部署,並且尚未創建任何 Kubernetes 資源。要同步(部署)應用程序,可以執行如下所示命令:
$ argocd app sync guestbook
此命令從 Git 倉庫中檢索資源清單並執行 kubectl apply
部署應用,執行上面命令後 guestbook 應用便會運行在集羣中了,現在我們就可以查看其資源組件、日誌、事件和評估其健康狀態了。
通過 UI 同步
直接添加 UI 界面上應用的 Sync
按鈕即可開始同步:
同步完成後可以看到我們的資源狀態:
甚至還可以直接查看應用的日誌信息:
也可以通過 kubectl 查看到我們部署的資源:
➜ ~ kubectl get pods
NAME READY STATUS RESTARTS AGE
guestbook-ui-6c96fb4bdc-bdwh9 1/1 Running 0 3m3s
➜ ~ kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
guestbook-ui ClusterIP 10.100.170.117 <none> 80/TCP 3m16s
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 42d
和我們從 Git 倉庫中同步 guestbook
目錄下面的資源狀態也是同步的,證明同步成功了。
Tekton 結合 Argo CD
前面我們使用 Tekton 完成了應用的 CI/CD 流程,但是 CD 是在 Tekton 的任務中去完成的,現在我們使用 GitOps 的方式來改造我們的流水線,將 CD 部分使用 Argo CD 來完成。
這裏我們要先去回顧下前面的 Tekton 實戰部分的內容,整個流水線包括 clone、test、build、docker、deploy、rollback 幾個部分的任務,最後的 deploy 和 rollback 屬於 CD 部分,我們只需要這部分使用 Argo CD 來構建即可。
首先我們將項目 http://git.k8s.local/course/devops-demo.git
倉庫中的 Helm Chart 模板單獨提取出來放到一個獨立的倉庫中 http://git.k8s.local/course/devops-demo-deploy
,這樣方便和 Argo CD 進行對接,整個項目下面只有用於應用部署的 Helm Chart 模板。
如果有多個團隊,每個團隊都要維護大量的應用,就需要用到 Argo CD 的另一個概念:項目(Project)。Argo CD 中的項目(Project)可以用來對 Application 進行分組,不同的團隊使用不同的項目,這樣就實現了多租戶環境。項目還支持更細粒度的訪問權限控制:
-
限制部署內容(受信任的 Git 倉庫);
-
限制目標部署環境(目標集羣和 namespace);
-
限制部署的資源類型(例如 RBAC、CRD、DaemonSets、NetworkPolicy 等);
-
定義項目角色,爲 Application 提供 RBAC(例如 OIDC group 或者 JWT 令牌綁定)。
比如我們這裏創建一個名爲 demo
的項目,將該應用創建到該項目下,只需創建一個如下所示的 AppProject
對象即可:
apiVersion: argoproj.io/v1alpha1
kind: AppProject
metadata:
# 項目名
name: demo
namespace: argocd
spec:
# 目標
destinations:
# 此項目的服務允許部署的 namespace,這裏爲全部
- namespace: "*"
# 此項目允許部署的集羣,這裏爲默認集羣,即爲Argo CD部署的當前集羣
server: https://kubernetes.default.svc
# 允許的數據源
sourceRepos:
- http://git.k8s.local/course/devops-demo-deploy.git
該對象中有幾個核心的屬性:
-
sourceRepos
:項目中的應用程序可以從中獲取清單的倉庫引用 -
destinations
:項目中的應用可以部署到的集羣和命名空間 -
roles
:項目內資源訪問定義的角色
直接創建該對象即可:
$ kubectl get AppProject -n argocd
NAME AGE
default 79m
demo 24s
然後前往 Argo CD 添加倉庫:
需要注意的是這裏的密碼需要使用 AccessToken,我們可以前往 GitLab 的頁面 http://git.k8s.local/-/profile/personal_access_tokens 創建。
項目創建完成後,在該項目下創建一個 Application,代表環境中部署的應用程序實例。
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: devops-demo
namespace: argocd
spec:
destination:
namespace: default
server: "https://kubernetes.default.svc"
project: demo
source:
path: helm # 從 Helm 存儲庫創建應用程序時,chart 必須指定 path
repoURL: "http://git.k8s.local/course/devops-demo-deploy.git"
targetRevision: HEAD
helm:
parameters:
- name: replicaCount
value: "2"
valueFiles:
- my-values.yaml
這裏我們定義了一個名爲 devops-demo
的應用,應用源來自於 helm 路徑,使用的是 my-values.yaml
文件,此外還可以通過 source.helm.parameters
來配置參數,同步策略我們仍然選擇使用手動的方式,我們可以在 Tekton 的任務中去手動觸發同步。上面的資源對象創建完成後應用就會處於 OutOfSync
狀態,因爲集羣中還沒部署該應用。
現在接下來我們去修改之前的 Tekton 流水線,之前的 Pipeline 流水線如下所示:
# pipeline.yaml
apiVersion: tekton.dev/v1beta1
kind: Pipeline
metadata:
name: pipeline
spec:
workspaces: # 聲明 workspaces
- name: go-repo-pvc
params:
# 定義代碼倉庫
- name: git_url
- name: revision
type: string
default: "main"
# 定義鏡像參數
- name: image
- name: registry_url
type: string
default: "harbor.k8s.local"
- name: registry_mirror
type: string
default: "https://dockerproxy.com"
# 定義 helm charts 參數
- name: charts_dir
- name: release_name
- name: release_namespace
default: "default"
- name: overwrite_values
default: ""
- name: values_file
default: "values.yaml"
tasks: # 添加task到流水線中
- name: clone
taskRef:
name: git-clone
workspaces:
- name: output
workspace: go-repo-pvc
params:
- name: url
value: $(params.git_url)
- name: revision
value: $(params.revision)
- name: test
taskRef:
name: test
runAfter:
- clone
- name: build # 編譯二進制程序
taskRef:
name: build
runAfter: # 測試任務執行之後才執行 build task
- test
- clone
workspaces: # 傳遞 workspaces
- name: go-repo
workspace: go-repo-pvc
- name: docker # 構建並推送 Docker 鏡像
taskRef:
name: docker
runAfter:
- build
workspaces: # 傳遞 workspaces
- name: go-repo
workspace: go-repo-pvc
params: # 傳遞參數
- name: image
value: $(params.image)
- name: registry_url
value: $(params.registry_url)
- name: registry_mirror
value: $(params.registry_mirror)
- name: deploy # 部署應用
taskRef:
name: deploy
runAfter:
- docker
workspaces:
- name: source
workspace: go-repo-pvc
params:
- name: charts_dir
value: $(params.charts_dir)
- name: release_name
value: $(params.release_name)
- name: release_namespace
value: $(params.release_namespace)
- name: overwrite_values
value: $(params.overwrite_values)
- name: values_file
value: $(params.values_file)
- name: rollback # 回滾
taskRef:
name: rollback
when:
- input: "$(tasks.deploy.results.helm-status)"
operator: in
values: ["failed"]
params:
- name: release_name
value: $(params.release_name)
- name: release_namespace
value: $(params.release_namespace)
現在我們需要去掉最後的 deploy 和 rollback 兩個任務,當 Docker 鏡像構建推送完成後,我們只需要去修改部署代碼倉庫中的 values 文件,然後再去手動觸發 ArgoCD 同步狀態即可(如果開啓了自動同步這一步都可以省略了),而回滾操作也是通過操作 Git 倉庫來實現的,不需要定義一個單獨的 Task 任務。
定義一個如下所的 Taks 任務:
apiVersion: tekton.dev/v1beta1
kind: Task
metadata:
name: sync
spec:
volumes:
- name: argocd-secret
secret:
secretName: $(inputs.params.argocd_secret)
params:
- name: argocd_url
description: "The URL of the ArgoCD server"
- name: argocd_secret
description: "The secret containing the username and password for the tekton task to connect to argo"
- name: app_name
description: "The name of the argo app to update"
- name: app_revision
default: "HEAD"
description: "The revision of the argo app to update"
steps:
- name: deploy
image: argoproj/argocd:v2.4.9
volumeMounts:
- name: argocd-secret
mountPath: /var/secret
command:
- sh
args:
- -ce
- |
set -e
echo "starting argocd sync app"
argocd login --insecure $(params.argocd_url) --username $(/bin/cat /var/secret/username) --password $(/bin/cat /var/secret/password)
argocd app sync $(params.app_name) --revision $(params.app_revision)
argocd app wait $(params.app_name) --health
由於我們這裏只需要修改 Helm Chart 的 Values 文件中的 image.tag
參數,最好的方式當然還是在一個 Task 中去修改 values.yaml
文件並 commit 到 Repo 倉庫中去,當然也可以爲了簡單直接在 ArgoCD 的應用側配置參數即可,比如可以使用 argocd app set
命令來爲應用配置參數,然後下面再用 argocd app sync
命令手動觸發同步操作,這裏其實就可以有很多操作了,比如我們可以根據某些條件來判斷是否需要部署,滿足條件後再執行 sync 操作,最後使用 wait
命令等待應用部署完成。
當然除了通過手動 argocd app set
的方式來配置參數之外,可能更好的方式還是直接去修改 Repo 倉庫中的 values 值,這樣在源代碼倉庫中有一個版本記錄,我們可以新建如下所示的一個任務用來修改 values 值:
apiVersion: tekton.dev/v1beta1
kind: Task
metadata:
name: change-manifests
spec:
params:
- name: git_url
description: Git repository containing manifest files to update
- name: git_email
default: pipeline@k8s.local
- name: git_name
default: Tekton Pipeline
- name: git_manifest_dir
description: Manifests files dir
- name: tool_image
default: cnych/helm-kubectl-curl-git-jq-yq
- name: image_tag
description: Deploy docker image tag
steps:
- name: git-push
image: $(params.tool_image)
env:
- name: GIT_USERNAME
valueFrom:
secretKeyRef:
name: gitlab-auth
key: username
optional: true
- name: GIT_PASSWORD
valueFrom:
secretKeyRef:
name: gitlab-auth
key: password
optional: true
command: ["/bin/bash"]
args:
- -c
- |
set -eu
git config --global user.email "$(params.git_email)"
git config --global user.name "$(params.git_name)"
git clone --branch main --depth 1 http://${GIT_USERNAME}:${GIT_PASSWORD}@$(params.git_url) repo
cd "repo/$(params.git_manifest_dir)"
ls -l
echo old value:
cat my-values.yaml | yq r - 'image.tag'
echo replacing with new value:
echo $(params.image_tag)
yq w --inplace my-values.yaml 'image.tag' "$(params.image_tag)"
echo verifying new value
yq r my-values.yaml 'image.tag'
if ! git diff-index --quiet HEAD --; then
git status
git add .
git commit -m "helm values updated by tekton pipeline in change-manifests task"
git push
else
echo "no changes, git repository is up to date"
fi
現在我們的流水線就變成了如下所示的清單:
# pipeline.yaml
apiVersion: tekton.dev/v1beta1
kind: Pipeline
metadata:
name: pipeline
spec:
workspaces: # 聲明 workspaces
- name: go-repo-pvc
params:
# 定義代碼倉庫
- name: git_url
- name: git_infra_url
- name: revision
type: string
default: "main"
# 定義鏡像參數
- name: image
- name: image_tag
- name: registry_url
type: string
default: "harbor.k8s.local"
- name: registry_mirror
type: string
default: "https://ot2k4d59.mirror.aliyuncs.com/"
- name: git_manifest_dir
default: "helm"
# 定義 argocd 參數
- name: argocd_url
- name: argocd_secret
- name: app_name
- name: app_revision
type: string
default: "HEAD"
tasks: # 添加task到流水線中
- name: clone
taskRef:
name: git-clone
workspaces:
- name: output
workspace: go-repo-pvc
params:
- name: url
value: $(params.git_url)
- name: revision
value: $(params.revision)
- name: test
taskRef:
name: test
runAfter:
- clone
- name: build # 編譯二進制程序
taskRef:
name: build
runAfter: # 測試任務執行之後才執行 build task
- test
- clone
workspaces: # 傳遞 workspaces
- name: go-repo
workspace: go-repo-pvc
- name: docker # 構建並推送 Docker 鏡像
taskRef:
name: docker
runAfter:
- build
workspaces: # 傳遞 workspaces
- name: go-repo
workspace: go-repo-pvc
params: # 傳遞參數
- name: image
value: $(params.image):$(params.image_tag)
- name: registry_url
value: $(params.registry_url)
- name: registry_mirror
value: $(params.registry_mirror)
- name: manifests
taskRef:
name: change-manifests
runAfter:
- docker
params:
- name: git_url
value: $(params.git_infra_url)
- name: git_manifest_dir
value: $(params.git_manifest_dir)
- name: image_tag
value: $(params.image_tag)
- name: sync
taskRef:
name: sync
runAfter:
- manifests
params:
- name: argocd_url
value: $(params.argocd_url)
- name: argocd_secret
value: $(params.argocd_secret)
- name: app_name
value: $(params.app_name)
- name: app_revision
value: $(params.app_revision)
最後創建用於 ArgoCD 登錄使用的 Secret 對象:
apiVersion: v1
kind: Secret
metadata:
name: argocd-auth
type: Opaque
stringData:
username: admin
password: admin321 # argocd 的密碼
最後修改 Tekton Triggers 中的 Template,如下所示:
# gitlab-template.yaml
apiVersion: triggers.tekton.dev/v1alpha1
kind: TriggerTemplate
metadata:
name: gitlab-template
spec:
params: # 定義參數,和 TriggerBinding 中的保持一致
- name: gitrevision
- name: gitrepositoryurl
resourcetemplates: # 定義資源模板
- apiVersion: tekton.dev/v1beta1
kind: PipelineRun # 定義 pipeline 模板
metadata:
generateName: gitlab-run- # TaskRun 名稱前綴
spec:
serviceAccountName: tekton-build-sa
pipelineRef:
name: pipeline
workspaces:
- name: go-repo-pvc
persistentVolumeClaim:
claimName: go-repo-pvc
params:
- name: git_url
value: $(tt.params.gitrepositoryurl)
- name: git_infra_url
value: git.k8s.local/course/devops-demo-deploy.git
- name: image
value: "harbor.k8s.local/course/devops-demo"
- name: image_tag
value: "$(tt.params.gitrevision)"
- name: argocd_url
value: argocd.k8s.local
- name: argocd_secret
value: argocd-auth
- name: app_name
value: devops-demo
現在我們的整個流水線就更加精簡了。現在我們去應用倉庫中修改下源代碼並提交就可以觸發我們的流水線了。
同樣可以訪問下應用來驗證結果是否正確:
$ curl devops-demo.k8s.local
{"msg":"Hello Tekton On GitLab With ArgoCD (GitOps)"}
現在查看 Argo CD 中的應用可以發現都是已同步狀態了。
如果需要回滾,則可以直接在 Argo CD 頁面上點擊 HISTORY AND ROLLBACK
安裝查看部署的歷史記錄選擇回滾的版本即可:
可以查看整個 Tekton 流水線的狀態:
$ tkn pr describe gitlab-run-4npk7
Name: gitlab-run-4npk7
Namespace: default
Pipeline Ref: pipeline
Service Account: tekton-build-sa
Timeout: 1h0m0s
Labels:
tekton.dev/pipeline=pipeline
triggers.tekton.dev/eventlistener=gitlab-listener
triggers.tekton.dev/trigger=gitlab-push-events-trigger
triggers.tekton.dev/triggers-eventid=6e21e686-79dc-421c-951a-e1591dcfd2f8
🌡️ Status
STARTED DURATION STATUS
10 minutes ago 4m11s Succeeded
⚓ Params
NAME VALUE
∙ git_url http://git.k8s.local/course/devops-demo.git
∙ git_infra_url git.k8s.local/course/devops-demo-deploy.git
∙ image harbor.k8s.local/course/devops-demo
∙ image_tag 1a49370f2708a01e8eef14c25688c5e0acf3a07c
∙ argocd_url grpc.argocd.k8s.local
∙ argocd_secret argocd-auth
∙ app_name devops-demo
📂 Workspaces
NAME SUB PATH WORKSPACE BINDING
∙ go-repo-pvc --- PersistentVolumeClaim (claimName=go-repo-pvc)
🗂 Taskruns
NAME TASK NAME STARTED DURATION STATUS
∙ gitlab-run-4npk7-sync sync 6 minutes ago 26s Succeeded
∙ gitlab-run-4npk7-manifests manifests 7 minutes ago 19s Succeeded
∙ gitlab-run-4npk7-docker docker 10 minutes ago 3m6s Succeeded
∙ gitlab-run-4npk7-build build 10 minutes ago 10s Succeeded
∙ gitlab-run-4npk7-test test 10 minutes ago 3s Succeeded
∙ gitlab-run-4npk7-clone clone 10 minutes ago 7s Succeeded
最後用一張圖來總結下我們使用 Tekton 結合 Argo CD 來實現 GitOps 的工作流:
除此之外,GitOps 中還有一項非常重要的事情要做就是安全,關於如何實施安全 GitOps 請關注後續文章......
本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源:https://mp.weixin.qq.com/s/EU9oVi8pT39FxBnemH72IA