在 DevOps 領域,自動化是主要目標之一。這包括自動化軟件部署方式。與其依賴某人在部署軟件的機器上進行 rsync/FTP/編寫軟件,不如使用 CI/CD 的概念。
CI,即持續集成,是通過代碼提交創建工件的步驟。這可以是 Docker 鏡像,使用 Git 倉庫主分支中的提交進行部署。
CD,即持續部署/交付,是部署工件的步驟。這可以是任何操作,例如在機器上運行 docker pull 和 docker run 的部署系統,指示 AWS Lambda 將代碼更新到 S3 存儲桶中的最新代碼,或者指示 Kubernetes 集群更新現有部署以使用新鏡像。
在本文中,我將快速介紹如何設置觸發 ArgoCD 的 Jenkins 流水線。ArgoCD 是一個基于 Git 倉庫中的清單更新 Kubernetes 集群的 CD 工具。它可以部署標準 Kubernetes 清單,并使用 Kustomize 更新清單或 Helm 圖表。
先決條件
要將 Jenkins 與 ArgoCD 結合使用,您需要執行以下操作:-
- 在 Jenkins 工作器/運行器上安裝 argocd-cli
- 在 ArgoCD 中創建一個 Jenkins 部署角色,該角色有權更新應用程序
- 在基于 Git 的版本控制系統中,ArgoCD 可以訪問一個或多個代碼庫(例如 GitHub、Gitlab、Gitea 或無前端的 Git)
- Jenkins 工作器/運行器需要能夠通過 API 訪問 ArgoCD,因此請確保設置了正確的防火墻規則
?安裝ArgoCD CLI
我們使用 Packer 為 Jenkins 工作器配置/準備鏡像。因此,添加其他工具非常簡單。但是,如果您運行的是靜態工作器,則只需確保 argocd 二進制文件安裝在 Jenkins 用戶可運行的位置即可。例如:
$ pwd
/home/jenkins## Download the tool
$ curl -LO https://github.com/argoproj/argo-cd/releases/download/v1.2.0/argocd-linux-amd64 ## Move it to the /usr/local/bin
$ sudo mv argocd-linux-amd64 /usr/local/bin/argocd## Ensure it is exectutable
$ sudo chmod 755 /usr/local/bin/argocd## Check it works
$ argocd version
argocd: v1.2.0+674978cBuildDate: 2019-09-04T21:26:04ZGitCommit: 674978cd587701b39e81fce6d5c960b6d76d5882GitTreeState: cleanGoVersion: go1.12.6Compiler: gcPlatform: linux/amd64
argocd-server: v1.2.0+674978cBuildDate: 2019-09-04T21:27:17ZGitCommit: 674978cd587701b39e81fce6d5c960b6d76d5882GitTreeState: cleanGoVersion: go1.12.6Compiler: gcPlatform: linux/amd64Ksonnet Version: 0.13.1
ArgoCD Jenkins 部署角色
要在 ArgoCD 中創建部署角色,請轉到 ArgoCD 儀表板,點擊側邊欄上的齒輪圖標(進入設置),然后轉到“項目”。
在“項目中”,選擇您的應用程序正在運行的項目。如果您尚未創建任何項目,則默認為“默認”。
在項目中,轉到“角色”,然后點擊“添加角色”。
?在角色中,您可以為角色指定您想要的名稱和描述,以便將來更容易理解其用途。您可以在此處應用細粒度的策略來定義 Jenkins 可以執行的操作(例如,僅創建、僅更新、僅同步現有應用程序)。或者,您可以授予其完全訪問權限,但顯然在生產環境中不建議這樣做。)
完成上述所有操作后,您需要創建一個 JWT(JSON Web Token)。它用于對用戶進行身份驗證,確保只有客戶端(在本例中為 Jenkins)才能承擔此角色并使用其權限。這可以在 Web UI 中完成,也可以通過 CLI 完成。
要從 CLI 創建 JWT,您需要執行 argocd proj role create-token {PROJECT-NAME} {PROJECT-ROLE} 命令,示例如下:
$ argocd proj role create-token default jenkins-deploy-role
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpYXQiOjE1Njg3MjEyMjEsImlzcyI6ImFyZ29jZCIsIm5iZiI6MTU2ODcyMTIyMSwic3ViIjoicHJvajpkZWZhdWx0OmplbmtpbnMtZGVwbG95LXJvbGUifQ.UyXNZtdbDyllzGl7PbLPhMgqNMFE1oJqONaLHV8RK-k
將令牌添加到 Jenkins
要將令牌添加到 Jenkins 本身(以便在流水線中使用),首先轉到您的 Jenkins 實例,然后在側邊欄上找到“憑據”,然后選擇“系統”,再選擇“全局憑據”。點擊添加憑據,如下圖所示。
允許ArgoCD 訪問代碼庫
ArgoCD 需要訪問的代碼庫是托管 Kubernetes 清單的代碼庫。您可以將清單與代碼放在同一個代碼庫中,也可以將它們放在一個完全獨立的代碼庫中。
您可以通過多種方式進行設置。您可以使用 SSH 或 HTTPS 連接到您的版本控制系統。我選擇了 SSH。
再次轉到 ArgoCD 的“設置”頁面,但不要點擊“項目”,而是點擊“代碼庫”。在這里,點擊“使用 SSH 連接代碼庫”。
??
ninjamac@192 ~ % ssh-keygen -o -f argocd-deploy -C "argocd@example.com"
Generating public/private ed25519 key pair.
Enter passphrase for "argocd-deploy" (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in argocd-deploy
Your public key has been saved in argocd-deploy.pub
The key fingerprint is:
SHA256:nAuYAjALq9QIGII14J1vtjZfEboOQE4+Q985bu5BjuU argocd@example.com
The key's randomart image is:
+--[ED25519 256]--+
|@+o |
|O++.. |
|++ B . |
|o.* oo..o.. |
|. .*o=.BS. |
| .* O.o.. |
| * E.. |
| . B o |
| .= |
+----[SHA256]-----+
獲取私鑰(在本例中為 argocd-deploy)的內容,并將其粘貼到 ArgoCD 的 SSH 私鑰數據字段中。提供 Kubernetes 清單所在倉庫的 URL(如果您使用 HTTPS 連接,則為 HTTPS URL;如果使用 SSH 連接,則為 SSH URL)。
您需要公鑰(在本例中為 argocd-deploy.pub)來在您選擇的 Git 服務器中設置部署密鑰。
防火墻規則
您的 Jenkins 工作器/運行器需要能夠訪問 ArgoCD API。我們將其暴露在 TCP:443 端口(即標準 HTTPS)上,因此您需要確保您的防火墻允許其通過。
Kubernetes 清單
如上所述,您可以使用標準 Kubernetes 清單、Kustomize 和/或 Helm 圖表來部署您的應用程序。我使用 Kustomize 來更新 Kubernetes 部署中使用的 Docker 鏡像哈希值。如果沒有 Kustomize,即使您的 Docker 鏡像倉庫(私有或公共)中有新的鏡像可用,部署也不會更新。
這是因為 Kubernetes API 認為部署沒有發生變化。標簽與以前相同,因此它不知道需要執行任何操作。
從 Kubernetes v1.15 版本開始,它們現在支持滾動重啟。與 ImagePullPolicy: Always 結合使用,這將強制部署獲取新鏡像。
在 Kubernetes v1.15 之前的版本中,Deployment 永遠不會更新。使用 :latest 并非最佳實踐,因此引用實際哈希值可能是一個好主意。
清單示例
我最基本的 Kubernetes 清單如下:-
## ------------------- Debian Deployment ------------------- #kind: Deployment
apiVersion: apps/v1
metadata:labels:k8s-app: debian-testname: debian-test
spec:replicas: 1revisionHistoryLimit: 10selector:matchLabels:k8s-app: debian-testtemplate:metadata:labels:k8s-app: debian-testspec:containers:- name: debian-testimage: docker.io/rockwang415/k8s-debian-test:latest imagePullPolicy: Alwaysresources:requests:memory: "64Mi"cpu: "250m"limits:memory: "128Mi"cpu: "500m"ports:- containerPort: 80protocol: TCPlivenessProbe:httpGet:scheme: HTTPpath: /port: 80initialDelaySeconds: 30timeoutSeconds: 30---
## ------------------- Debian Service ------------------- #kind: Service
apiVersion: v1
metadata:labels:k8s-app: debian-testname: debian-test
spec:ports:- port: 80targetPort: 80type: NodePortselector:k8s-app: debian-test
我們使用?Docker 鏡像倉庫來存放鏡像。如您所見,上面的鏡像標簽為 :latest。不過,我們也使用 Kustomize 來根據部署情況進行更改。我們的 kustomization.yaml 文件非常簡單:-
resources:
- debian-test.yaml
從 v1.2.0 開始,ArgoCD 可以原生地利用 Kustomize(如果您指定了正確的參數),因此無需在此 YAML 文件中添加任何其他內容。
Jenkins Pipeline
現在所有先決條件都已滿足,您已將 ArgoCD 連接到您的倉庫并創建了清單,接下來您可以創建一個 Jenkinsfile 來部署應用程序。
pipeline {agent {node {label 'testing'}}stages { stage('Prepare') {steps {checkout([$class: 'GitSCM',branches: [[name: "origin/master"]],doGenerateSubmoduleConfigurations: false,submoduleCfg: [],userRemoteConfigs: [[url: 'ssh://git@git.example.com/argocd-test/argocd-test.git']]])}}stage('Docker_Build') {steps {// Build the Docker imagesh '''# Login to Docker registrydocker login -u <docker-username> -p <docker-password> <docker-registry-url># Build the imagedocker build . -t k8s-debian-test'''}}stage('Deploy_K8S') {steps {withCredentials([string(credentialsId: "jenkins-argocd-deploy", variable: 'ARGOCD_AUTH_TOKEN')]) {sh '''ARGOCD_SERVER="argocd-prod.example.com"APP_NAME="debian-test-k8s"CONTAINER="k8s-debian-test"REGION="eu-west-1"# Tag the docker imagedocker tag $CONTAINER:latest <docker-registry-url>/$CONTAINER:latest# Push the image to Docker registrydocker push <docker-registry-url>/$CONTAINER:latestIMAGE_DIGEST=$(docker image inspect <docker-registry-url>/$CONTAINER:latest -f '{{join .RepoDigests ","}}')# Customize image ARGOCD_SERVER=$ARGOCD_SERVER argocd --grpc-web app set $APP_NAME --kustomize-image $IMAGE_DIGEST# Deploy to ArgoCDARGOCD_SERVER=$ARGOCD_SERVER argocd --grpc-web app sync $APP_NAME --forceARGOCD_SERVER=$ARGOCD_SERVER argocd --grpc-web app wait $APP_NAME --timeout 600'''}}}}
}
docker hub 登錄
這用于登錄 docker hub,檢索 Docker 鏡像(例如,基礎 Debian 鏡像),然后根據我們的 Dockerfile 進行標記和推送。如果您使用的是標準鏡像或您自己的私有鏡像倉庫,則可以忽略這些部分。
鏡像摘要
由于某種原因,Docker 鏡像摘要并不總是顯示在 docker images --digests 中。相反,我們會檢查最新推送到 docker hub的鏡像,并檢索 .RepoDigests 標簽。這將提供以下內容:
ninjamac@192 ~ % docker image inspect rockwang415/k8s-debian-test -f '{{join .RepoDigests ","}}'
rockwang415/k8s-debian-test@sha256:b662d828445b39ac0a659ec77b629a75d1b298a6c76afdf5296cff64806fc638
ArgoCD
由于我們的 ArgoCD API 和儀表板位于 AWS 應用負載均衡器前端,我們目前在所有 ArgoCD 命令前都添加了 --grpc-web 前綴,例如 argocd --grpc-web app sync TEST --force。這是因為 AWS 應用負載均衡器默認不支持 GRPC。如果您在 ArgoCD 前端的負載均衡器/入口支持 GRPC,請從所有命令中移除該前綴。
自定義鏡像
ARGOCD_SERVER=$ARGOCD_SERVER argocd --grpc-web app set $APP_NAME --kustomize-image $IMAGE_DIGEST
上述命令將 Kubernetes 清單中的鏡像設置為生成的鏡像摘要變量。由于 ArgoCD 默認支持 Kustomize,它可以自行操作清單。這意味著我們不會因為鏡像標簽始終不變而導致 Deployment 始終不更新。
這是一個非常棒的功能,意味著我們不需要像 ArgoCD 一樣在 Jenkins 工作進程中同時運行 Kustomize 二進制文件。
同步應用程序
ARGOCD_SERVER=$ARGOCD_SERVER argocd --grpc-web app sync $APP_NAME --force
ARGOCD_SERVER=$ARGOCD_SERVER argocd --grpc-web app wait $APP_NAME --timeout 600
?上述代碼只是要求 ArgoCD 觸??發 Kubernetes 部署應用程序。在 ArgoCD 中,這將使用 Git 倉庫中的 Manifest 文件,該文件已通過 Kustomize 更新以使用新的鏡像標簽。然后,它將根據 Jenkins 生成的鏡像部署應用程序的新版本。
運行Jenkins Pipeline?
下面是運行后的結果
Kubernetes Output
Pre-ArgoCD Run
kubectl get pods
NAME READY STATUS RESTARTS AGE
debian-test-8648f969ff-hrsvp 1/1 Running 0 4d22h
Post-ArgoCD Run
kubectl get pods
NAME READY STATUS RESTARTS AGE
debian-test-7664c648bb-sq6h7 1/1 Running 0 22s
Jenkins Console Output - ArgoCD
+ ARGOCD_SERVER=argocd-prod.example.com argocd \ --grpc-web app set debian-test-k8s \ --kustomize-image rockwang415/k8s-debian-test@sha256:###SHA256-IMAGE-HASH###+ ARGOCD_SERVER=argocd-prod.example.com argocd --grpc-web app sync debian-test-k8s --force
TIMESTAMP GROUP KIND NAMESPACE NAME STATUS HEALTH HOOK MESSAGE
2025-05-017T13:05:27+00:00 apps Deployment default debian-test Synced Healthy
2025-05-017T13:05:27+00:00 Service default debian-test Synced Healthy
2025-05-017T13:05:27+00:00 apps Deployment default debian-test OutOfSync Healthy Name: debian-test-k8s
Project: default
Server: https://kubernetes.default.svc
Namespace: default
URL: https://argocd-prod.example.com/applications/debian-test-k8s
Repo: git@git.example.com:yeti/argocd-test.git
Target: HEAD
Path: yaml
Sync Policy: <none>
Sync Status: Synced to HEAD (f5f91ad)
Health Status: ProgressingOperation: Sync
Sync Revision: f5f91ad16296ecab90f337e5dbf3f4f927b61799
Phase: Succeeded
Start: 2025-05-01 13:05:27 +0000 UTC
Finished: 2025-05-01 13:05:29 +0000 UTC
Duration: 2s
Message: successfully synced (all tasks run)GROUP KIND NAMESPACE NAME STATUS HEALTH HOOK MESSAGEService default debian-test Synced Healthy service/debian-test unchanged
apps Deployment default debian-test Synced Progressing deployment.apps/debian-test configured
+ ARGOCD_SERVER=argocd-prod.example.com argocd --grpc-web app wait debian-test-k8s --timeout 600
TIMESTAMP GROUP KIND NAMESPACE NAME STATUS HEALTH HOOK MESSAGE
2025-05-01T13:05:29+00:00 Service default debian-test Synced Healthy service/debian-test unchanged
2025-05-01T13:05:29+00:00 apps Deployment default debian-test Synced Progressing deployment.apps/debian-test configuredName: debian-test-k8s
Project: default
Server: https://kubernetes.default.svc
Namespace: default
URL: https://argocd-prod.example.com/applications/debian-test-k8s
Repo: git@git.example.com:yetiops/argocd-test.git
Target: HEAD
Path: yaml
Sync Policy: <none>
Sync Status: Synced to HEAD (f5f91ad)
Health Status: HealthyOperation: Sync
Sync Revision: f5f91ad16296ecab90f337e5dbf3f4f927b61799
Phase: Succeeded
Start: 2025-05-01 13:05:27 +0000 UTC
Finished: 2025-05-01 13:05:29 +0000 UTC
Duration: 2s
Message: successfully synced (all tasks run)GROUP KIND NAMESPACE NAME STATUS HEALTH HOOK MESSAGEService default debian-test Synced Healthy service/debian-test unchanged
apps Deployment default debian-test Synced Healthy deployment.apps/debian-test configured
ArgoCD Dashboard
?總結
我們為什么要使用 Jenkins 和 ArgoCD?Jenkins 非常擅長構建工件、整合代碼提交,并接受來自 GitHub 或 GitLab 等平臺的 Webhook 來啟動作業。然而,ArgoCD 能夠更好地控制鏡像的部署方式,因為所有內容都可以在原生 Kubernetes 清單中描述。
這消除了將 Kubernetes 直接暴露給 Jenkins 的需要,也無需操作 kubectl 命令來部署(或使用額外的插件)。
ArgoCD 還為我們提供了部署進度的實時視圖,以及在需要時可以回滾到的位置。它還以 Kubernetes 為中心(即部署和服務如何關聯)的方式展示它們,因此開發人員和運維團隊可以更輕松地了解所有內容是如何關聯的。