容器技術的爆發讓 Kubernetes(K8s)成為了「云原生時代的操作系統」—— 它能高效編排成千上萬的容器,解決彈性伸縮、資源調度等核心問題。但隨著企業應用規模擴大,K8s 的「部署與管理」逐漸暴露新的挑戰:
- 多環境(開發、測試、生產)配置不一致,手動執行?
kubectl apply
?容易出錯; - 應用配置散落在各種 YAML 文件、腳本或工程師的本地環境中,「配置漂移」成為常態(實際運行狀態與預期狀態偏離);
- 回滾、版本管理依賴人工記錄,出問題時難以快速定位根源;
- 跨團隊協作時,開發、運維對「應用狀態」的認知不同步,溝通成本高。
這些問題的核心,本質是「如何讓 K8s 中的應用狀態與「預期配置」保持一致」。此時,「GitOps」理念應運而生:它將 Git 倉庫作為應用配置的「單一可信數據源」,用聲明式語法定義應用的「最終狀態」,再通過工具自動將「預期狀態」同步到 K8s 集群中。
而 ArgoCD 正是 GitOps 理念在 K8s 中的「最佳實踐工具」—— 它以 Git 倉庫為核心,持續監控 K8s 集群狀態與 Git 配置的差異,自動觸發同步,甚至能在配置被意外修改時「自動糾偏」。
本文將深入探討:ArgoCD 如何與 K8s 深度結合?它能解決哪些實際問題?以及如何通過 ArgoCD 在 K8s 中落地 GitOps,讓應用部署從「手動運維」升級為「自動化、可追溯、一致性」的閉環?
一、 部署ArgoCD
參考鏈接
Argo CD - Declarative GitOps CD for Kubernetes
argoproj/argo-cd: Declarative Continuous Deployment for Kubernetes
1. 快速入門
kubectl 創建命名空間 argocd
kubectl create namespace argocd
使用 kubectl 命令,在 argocd 命名空間下,應用以下配置文件:
kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml
2. 查看資源
root@k8s-master:~# kubectl get deploy,po,svc -n argocd
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/argocd-applicationset-controller 1/1 1 1 18m
deployment.apps/argocd-dex-server 1/1 1 1 18m
deployment.apps/argocd-notifications-controller 1/1 1 1 18m
deployment.apps/argocd-redis 1/1 1 1 18m
deployment.apps/argocd-repo-server 1/1 1 1 18m
deployment.apps/argocd-server 1/1 1 1 18mNAME READY STATUS RESTARTS AGE
pod/argocd-application-controller-0 1/1 Running 0 18m
pod/argocd-applicationset-controller-655cc58ff8-4b7bj 1/1 Running 0 18m
pod/argocd-dex-server-7d9dfb4fb8-447zb 1/1 Running 0 18m
pod/argocd-notifications-controller-6c6848bc4c-gmms8 1/1 Running 0 18m
pod/argocd-redis-656c79549c-2zbc9 1/1 Running 0 18m
pod/argocd-repo-server-856b768fd9-br979 1/1 Running 0 18m
pod/argocd-server-99c485944-rqznp 1/1 Running 0 18mNAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/argocd-applicationset-controller ClusterIP 10.200.150.131 <none> 7000/TCP,8080/TCP 18m
service/argocd-dex-server ClusterIP 10.200.116.20 <none> 5556/TCP,5557/TCP,5558/TCP 18m
service/argocd-metrics ClusterIP 10.200.183.3 <none> 8082/TCP 18m
service/argocd-notifications-controller-metrics ClusterIP 10.200.183.138 <none> 9001/TCP 18m
service/argocd-redis ClusterIP 10.200.101.160 <none> 6379/TCP 18m
service/argocd-repo-server ClusterIP 10.200.167.8 <none> 8081/TCP,8084/TCP 18m
service/argocd-server NodePort 10.200.105.205 <none> 80:30080/TCP,443:32076/TCP 18m
service/argocd-server-metrics ClusterIP 10.200.182.238 <none> 8083/TCP 18m
root@k8s-master:~#
注意,這里的SVC類型默認是ClusterIP類型,需要手動去修改我們想要的類型。
root@k8s-master:~# kubectl edit svc argocd-server -n argocd
apiVersion: v1
kind: Service
metadata:annotations:kubectl.kubernetes.io/last-applied-configuration: |{"apiVersion":"v1","kind":"Service","metadata":{"annotations":{},"labels":{"app.kubernetes.io/component":"server","app.kubernetes.io/name":"argocd-server","app.kubernetes.io/part-of":"argocd"},"name":"argocd-server","namespace":"argocd"},"spec":{"ports":[{"name":"http","port":80,"protocol":"TCP","targetPort":8080},{"name":"https","port":443,"protocol":"TCP","targetPort":8080}],"selector":{"app.kubernetes.io/name":"argocd-server"}}}creationTimestamp: "2025-08-08T01:32:09Z"labels:app.kubernetes.io/component: serverapp.kubernetes.io/name: argocd-serverapp.kubernetes.io/part-of: argocdname: argocd-servernamespace: argocdresourceVersion: "7618"uid: 800b750f-1597-4eb4-82f3-2be8cf2d8768
spec:clusterIP: 10.200.105.205clusterIPs:- 10.200.105.205externalTrafficPolicy: ClusterinternalTrafficPolicy: ClusteripFamilies:- IPv4ipFamilyPolicy: SingleStackports:- name: httpnodePort: 30080 ## 第一處修改port: 80protocol: TCPtargetPort: 8080- name: httpsnodePort: 32076port: 443protocol: TCPtargetPort: 8080selector:app.kubernetes.io/name: argocd-serversessionAffinity: Nonetype: NodePort ## 第二處修改
status:loadBalancer: {}
更新一下資源清單即可。
root@k8s-master:~# kubectl apply -f install.yaml
3. 訪問測試
https://[your_ip]:port(以各自環境為準!)
用戶名: admin
密 碼:
# 使用以下命令可以得到
kubectl -n argocd get secret argocd-initial-admin-secret -o jsonpath="{.data.password}" | base64 -d; echo
成功登入,就代表部署沒有問題!
4. 安裝argocd客戶端命令行工具修改密碼
# 下載
wget https://github.com/argoproj/argo-cd/releases/download/v3.0.12/argocd-linux-amd64root@k8s-master:~# mv argocd-linux-amd64 /usr/bin/argocd
root@k8s-master:~# chmod a+x /usr/bin/argocd
root@k8s-master:~# argocd version
argocd: v3.0.12+ed1e239BuildDate: 2025-07-25T20:01:42ZGitCommit: ed1e2397ef9af6d23b284e39d504308cdda1957bGitTreeState: cleanGoVersion: go1.24.4Compiler: gcPlatform: linux/amd64
{"level":"fatal","msg":"Argo CD server address unspecified","time":"2025-08-08T10:02:29+08:00"}root@k8s-master:~# argocd login 10.0.0.6:30080
WARNING: server certificate had error: tls: failed to verify certificate: x509: cannot validate certificate for 10.0.0.6 because it doesn't contain any IP SANs. Proceed insecurely (y/n)? y
Username: admin
Password:
'admin:login' logged in successfully
Context '10.0.0.6:30080' updatedroot@k8s-master:~# argocd account update-password
*** Enter password of currently logged in user (admin):
*** Enter new password for user admin:
*** Confirm new password for user admin:
Password updated
Context '10.0.0.6:30080' updated
注意密碼是有復雜度要求的:
{"level":"fatal","msg":"rpc error: code = Unknown desc = New password does not match the following expression: ^.{8,32}$.","time":"2025-08-08T10:06:30+08:00"}# 驗證一下我們的密碼
root@k8s-master:~# argocd logout 10.0.0.6:30080
Logged out from '10.0.0.6:30080'
root@k8s-master:~# argocd login 10.0.0.6:30080
WARNING: server certificate had error: tls: failed to verify certificate: x509: cannot validate certificate for 10.0.0.6 because it doesn't contain any IP SANs. Proceed insecurely (y/n)? y
Username: admin
Password:
'admin:login' logged in successfully
Context '10.0.0.6:30080' updated
root@k8s-master:~#
二、了解ArgoCD
1. ArgoCD設置介紹
2. 準備Git倉庫
這里我們用的是Gitee的公開庫,自行創建即可。
root@k8s-master:~# mkdir argocd-repo
root@k8s-master:~# cd argocd-reporoot@k8s-master:~/argocd-repo# ll
total 8
drwxr-xr-x 2 root root 4096 Aug 8 10:31 ./
drwx------ 10 root root 4096 Aug 8 10:31 ../
root@k8s-master:~/argocd-repo# git init
hint: Using 'master' as the name for the initial branch. This default branch name
hint: is subject to change. To configure the initial branch name to use in all
hint: of your new repositories, which will suppress this warning, call:
hint:
hint: git config --global init.defaultBranch <name>
hint:
hint: Names commonly chosen instead of 'master' are 'main', 'trunk' and
hint: 'development'. The just-created branch can be renamed via this command:
hint:
hint: git branch -m <name>
Initialized empty Git repository in /root/argocd-repo/.git/
root@k8s-master:~/argocd-repo# ll -a
total 12
drwxr-xr-x 3 root root 4096 Aug 8 10:31 ./
drwx------ 10 root root 4096 Aug 8 10:31 ../
drwxr-xr-x 7 root root 4096 Aug 8 10:31 .git/
root@k8s-master:~/argocd-repo# touch README.md
root@k8s-master:~/argocd-repo# git add README.md
root@k8s-master:~/argocd-repo# git commit -m "first commit"
[master (root-commit) 9576f67] first commit1 file changed, 0 insertions(+), 0 deletions(-)create mode 100644 README.md
root@k8s-master:~/argocd-repo# git remote add origin https://gitee.com/cao-facan/argocd-repo.git
root@k8s-master:~/argocd-repo# git push -u origin "master"
Username for 'https://gitee.com': 1951
Password for 'https://1951@gitee.com':
Enumerating objects: 3, done.
Counting objects: 100% (3/3), done.
Writing objects: 100% (3/3), 225 bytes | 225.00 KiB/s, done.
Total 3 (delta 0), reused 0 (delta 0), pack-reused 0
remote: Powered by GITEE.COM [1.1.5]
remote: Set trace flag d1477e9f
To https://gitee.com/cao-facan/argocd-repo.git* [new branch] master -> master
Branch 'master' set up to track remote branch 'master' from 'origin'.
root@k8s-master:~/argocd-repo#
3. 上傳我們的代碼
此步驟和和README.md一樣就是為了測試是否可以正常使用Gitee倉庫,可以跳過第四步配置Git倉庫。
root@k8s-master:~/argocd-repo# ll
total 228
drwxr-xr-x 6 root root 4096 Aug 8 10:35 ./
drwx------ 10 root root 4096 Aug 8 10:34 ../
drwxr-xr-x 2 root root 4096 Sep 19 2022 css/
drwxr-xr-x 8 root root 4096 Aug 8 10:36 .git/
-rw-r--r-- 1 root root 29627 Jun 29 2019 index.html
-rw-r--r-- 1 root root 0 Aug 8 10:31 README.mdroot@k8s-master:~/argocd-repo# git push -u origin "master"
Username for 'https://gitee.com': Nova
Password for 'https://Nova@gitee.com':
remote: [session-424d36a0] Nova: Incorrect username or password (access token)
fatal: Authentication failed for 'https://gitee.com/cao-facan/argocd-repo.git/'
root@k8s-master:~/argocd-repo# git push -u origin "master"
Username for 'https://gitee.com': 1951
Password for 'https://1951@gitee.com':
Enumerating objects: 91, done.
Counting objects: 100% (91/91), done.
Delta compression using up to 4 threads
Compressing objects: 100% (90/90), done.
Writing objects: 100% (90/90), 1.48 MiB | 2.17 MiB/s, done.
Total 90 (delta 10), reused 0 (delta 0), pack-reused 0
remote: Powered by GITEE.COM [1.1.5]
remote: Set trace flag f84085b7
To https://gitee.com/cao-facan/argocd-repo.git9576f67..495df2c master -> master
Branch 'master' set up to track remote branch 'master' from 'origin'.
4. 配置Git倉庫
然后點擊上方CONNECT連接,出現successful代表成功連接。
三、使用ArgoCD
1. 創建K8S資源清單
root@k8s-master:~/argocd-repo# cat myapp-deploy-svc.yml
apiVersion: apps/v1
kind: Deployment
metadata:name: myapp
spec:replicas: 1selector:matchLabels:app: myapptemplate:metadata:labels:app: myappspec:containers:- image: wangyanglinux/myapp:v1 # 容器鏡像name: myapp # 容器名稱(與 image 同層級縮進)ports:- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:name: myapp-svc
spec:type: NodePortselector:app: myappports:- port: 8080 # Service 集群內部端口(可自定義)targetPort: 80 # 映射到 Pod 的端口(需與上面 containerPort 一致)nodePort: 30088 # 節點暴露端口(可選,范圍 30000-32767,不指定則自動分配)
同步到代碼倉庫
2. 使用ArgoCD創建應用
3. 驗證連接并執行同步
root@k8s-master:~/argocd-repo# kubectl config get-contexts
CURRENT NAME CLUSTER AUTHINFO NAMESPACE
* kubernetes-admin@kubernetes kubernetes kubernetes-admin
root@k8s-master:~/argocd-repo# argocd cluster list
SERVER NAME VERSION STATUS MESSAGE PROJECT
https://kubernetes.default.svc in-cluster 1.32 Successful
root@k8s-master:~/argocd-repo#
點擊上方CREATE?
進行同步
4.查看同步狀態
可以看到每一步的詳情
root@k8s-master:~/argocd-repo# kubectl get ns
NAME STATUS AGE
argocd Active 129m
calico-apiserver Active 28d
calico-system Active 28d
default Active 28d
kube-node-lease Active 28d
kube-public Active 28d
kube-system Active 28d
myapp Active 111m
tigera-operator Active 28d
root@k8s-master:~/argocd-repo# kubectl get po -n myapp
NAME READY STATUS RESTARTS AGE
myapp-7c4fb5f6fc-qbg27 1/1 Running 0 111m
5.驗證pod
root@k8s-master:~/argocd-repo# kubectl get po,svc -n myapp -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
pod/myapp-7c4fb5f6fc-qbg27 1/1 Running 0 112m 10.100.36.70 k8s-node1 <none> <none>NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR
service/myapp-svc NodePort 10.200.91.180 <none> 8080:30088/TCP 112m app=myapp
root@k8s-master:~/argocd-repo# curl 10.100.36.70
Hello MyApp | Version: v1 | <a href="hostname.html">Pod Name</a>
沒有問題.
四、使用ArgoCD更新應用
1. 修改代碼
root@k8s-master:~/argocd-repo# cat myapp-deploy-svc.yml
apiVersion: apps/v1
kind: Deployment
metadata:name: myapp
spec:replicas: 1selector:matchLabels:app: myapptemplate:metadata:labels:app: myappspec:containers:- image: wangyanglinux/myapp:v1 # 容器鏡像name: myapp # 容器名稱(與 image 同層級縮進)ports:- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:name: myapp-svc
spec:type: NodePortselector:app: myappports:- port: 8080 # Service 集群內部端口(可自定義)targetPort: 80 # 映射到 Pod 的端口(需與上面 containerPort 一致)nodePort: 30088 # 節點暴露端口(可選,范圍 30000-32767,不指定則自動分配)root@k8s-master:~/argocd-repo# sed -i '/myapp:v1/s/v1/v2/' myapp-deploy-svc.yml
root@k8s-master:~/argocd-repo# grep 'image' myapp-deploy-svc.yml- image: wangyanglinux/myapp:v2 # 容器鏡像name: myapp # 容器名稱(與 image 同層級縮進)
2. 提交到倉庫
root@k8s-master:~/argocd-repo# git add .
root@k8s-master:~/argocd-repo# git commit -m "update image versio--->v2"
[master 8cd1683] update image versio--->v21 file changed, 1 insertion(+), 1 deletion(-)
root@k8s-master:~/argocd-repo# !305
git push -u origin master
Username for 'https://gitee.com': 1951
Password for 'https://19519921098@gitee.com':
Enumerating objects: 5, done.
Counting objects: 100% (5/5), done.
Delta compression using up to 4 threads
Compressing objects: 100% (3/3), done.
Writing objects: 100% (3/3), 313 bytes | 313.00 KiB/s, done.
Total 3 (delta 2), reused 0 (delta 0), pack-reused 0
remote: Powered by GITEE.COM [1.1.5]
remote: Set trace flag ce4cf793
To https://gitee.com/cao-facan/argocd-repo.git8130696..8cd1683 master -> master
Branch 'master' set up to track remote branch 'master' from 'origin'.
3. 使用ArgoCD同步
好了,那直接刷新頁面查看版本是否變成了v2
沒有問題,在K8S中之前的Podv1也會被清理掉,這是毋庸置疑的。
五、使用ArgoCD回滾版本
1. 使用ArgoCD進行回滾版本
2. 注意辨別
這時候就體現了我們commit代碼的時候,寫注解的好處了,我們可以通過注解來分辨我們提交代碼更新了什么,從而更精準的回滾版本。
那我們回滾到我們V1版本
然后點擊OK即可,等待同步完成。
刷新頁面,沒有任何問題。
六、總結與感想
1. K8S 的 CI/CD 中 Argo 與 Jenkins 的優劣勢
Argo(以 ArgoCD 為核心,含 Argo Workflows 等)
優勢:
- 云原生深度集成:專為 K8S 設計,通過 CRD(自定義資源)與 K8S 無縫對接,天然支持容器化部署流程。
- GitOps 理念落地:以 Git 倉庫為 “單一可信源”,通過聲明式配置定義應用最終狀態,自動同步集群狀態與 Git 配置,解決 “配置漂移” 問題。
- 自動化與自愈能力:持續監控集群狀態,發現偏差時自動糾偏;支持自動同步(Git 變更后自動部署),減少人工干預。
- 審計與回滾便捷:所有操作基于 Git 提交記錄,可追溯性強;通過 Git 版本直接回滾,操作簡單。
- 輕量化與可擴展性:組件精簡(如 repo-server、application-controller),適合大規模 K8S 集群部署。
劣勢:
- CI 能力薄弱:核心聚焦 CD(持續部署),CI(構建、測試等)需依賴外部工具(如 GitLab CI、Tekton)。
- 學習成本:需理解 GitOps 理念和 K8S 聲明式配置,對新手有一定門檻。
Jenkins
優勢:
- 全流程覆蓋:CI/CD 一體化,支持從代碼拉取、構建、測試到部署的全鏈路,插件生態豐富(超過 1800 個),適配多語言、多工具。
- 靈活性高:支持自由風格、流水線(Pipeline)等多種配置方式,可通過腳本定制復雜流程(如條件判斷、并行任務)。
- 兼容性強:不僅適用于 K8S,還支持物理機、虛擬機等混合環境,適合企業多環境并存的場景。
劣勢
- 非云原生原生設計:基于傳統架構,在 K8S 中部署需額外適配(如通過 Jenkins Agent 容器化),復雜度高。
- 狀態一致性難保證:依賴命令式腳本(如
kubectl apply
),配置分散在流水線腳本中,易出現 “實際狀態與預期不符” 的漂移問題。 - 維護成本高:插件版本兼容、節點管理(如 Agent 擴容)在大規模場景下易出問題,需專人維護。
2. 使用場景
-
Argo 適用場景:
- 純 K8S 環境,需嚴格遵循 GitOps 理念,強調 “配置即代碼” 和狀態一致性;
- 大規模集群部署(如多環境、多團隊協作),需要自動化糾偏、審計和快速回滾;
- 以 “部署一致性” 為核心訴求,CI 流程可依賴其他工具(如 Tekton)配合。
-
Jenkins 適用場景:
- 需復雜 CI 流程(如多語言構建、多輪測試、跨平臺打包),依賴豐富插件生態;
- 混合部署環境(K8S + 物理機 / 虛擬機),需統一流程管理;
- 需高度定制化流水線(如條件分支、第三方系統集成),對靈活性要求高于 “狀態一致性”。
3. 總結
Argo CD 是 “當下主流”,Kargo CD 是 “未來選項”
-
當前選擇:90% 以上的場景應優先采用 Argo CD,因其成熟、易用且能快速解決核心問題。
-
何時考慮 Kargo CD:
- 已全面落地 Argo CD 管理單集群;
- 需自動化多環境遞進式交付(如灰度→生產);
- 團隊規模較大(如管理超過 50 個應用或 10 個環境)。
-
類比關系:Argo CD 如同 “智能手機”(普及度高),Kargo CD 類似 “專業相機”(特定場景剛需)。二者結合可形成完整的 GitOps 解決方案,但現階段 Argo CD 仍是絕大多數用戶的首選。