ArgoCD 与 GitOps:K8S 原生持续部署的实操指南
容器技术的爆发让 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 仍是绝大多数用户的首选。