ArgoCD GitOps 实战——声明式部署,让 K8s 配置变成 Git 仓库
ArgoCD GitOps 实战——声明式部署,让 K8s 配置变成 Git 仓库
适读人群:想把 K8s 部署流程标准化的工程师,了解 GitOps 理念但还没落地的人 | 阅读时长:约 16 分钟 | 核心价值:ArgoCD 从安装到生产使用的完整实践,理解 GitOps 的真正价值
我是在一次"配置漂移"事故之后,开始认真研究 ArgoCD 的。
那次事故是这样的:某个工程师在紧急处理线上 Bug 时,直接 kubectl edit deployment 改了生产环境的环境变量,问题解决了,但没有把改动更新回 Git 仓库。三周后,有人用 CI/CD 重新部署这个服务,环境变量被还原成了旧版,Bug 又出现了,排查了一个多小时才想起三周前的那次手动修改。
"Git 说是什么就是什么"——这就是 GitOps 的核心理念。有了 ArgoCD,生产集群的配置始终和 Git 仓库保持一致,任何手动改动都会被标记为 "OutOfSync",自动或提示回滚。
GitOps 和传统 CI/CD 的区别
传统 CI/CD(Push 模式):
代码提交 → CI 构建 → CI 推送镜像 → CI 执行 kubectl apply → K8s 集群更新GitOps(Pull 模式):
代码提交 → CI 构建 → CI 推送镜像 + 更新 Git 仓库里的 image tag
↓
ArgoCD 监听 Git 仓库变化
↓
ArgoCD 自动同步到 K8s 集群关键区别:
- CI 不再直接操作集群,只更新 Git
- ArgoCD 是"拉取"而不是"推送",K8s 集群不需要向外暴露 API
- 集群状态永远以 Git 为准
安装 ArgoCD
kubectl create namespace argocd
kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml
# 等待所有 Pod 就绪
kubectl wait --for=condition=Ready pods --all -n argocd --timeout=300s
# 获取初始密码(admin 用户)
kubectl -n argocd get secret argocd-initial-admin-secret \
-o jsonpath="{.data.password}" | base64 -d
# 通过 Port-forward 访问 UI(临时)
kubectl port-forward svc/argocd-server -n argocd 8080:443
# 访问 https://localhost:8080,用户名 admin生产环境通过 Ingress 暴露:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: argocd-server-ingress
namespace: argocd
annotations:
nginx.ingress.kubernetes.io/ssl-passthrough: "true"
nginx.ingress.kubernetes.io/backend-protocol: "HTTPS"
spec:
ingressClassName: nginx
rules:
- host: argocd.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: argocd-server
port:
number: 443
tls:
- hosts:
- argocd.example.com
secretName: argocd-tlsGit 仓库结构设计
GitOps 的核心是 Git 仓库的结构设计。推荐用应用代码仓库和配置仓库分离的模式:
app-source-repo/ # 应用代码(开发者写代码的地方)
└── src/
└── Dockerfile
k8s-config-repo/ # 配置仓库(ArgoCD 监听这个)
├── apps/ # 各应用的 K8s 配置
│ ├── user-service/
│ │ ├── base/ # Kustomize base
│ │ │ ├── deployment.yaml
│ │ │ ├── service.yaml
│ │ │ └── kustomization.yaml
│ │ └── overlays/
│ │ ├── staging/
│ │ │ ├── kustomization.yaml
│ │ │ └── patch.yaml # 环境差异
│ │ └── production/
│ │ ├── kustomization.yaml
│ │ └── patch.yaml
│ └── order-service/
│ └── ...
└── argocd-apps/ # ArgoCD Application 配置
├── user-service-staging.yaml
├── user-service-production.yaml
└── ...创建 ArgoCD Application
ArgoCD 通过 Application CRD 定义"哪个 Git 仓库的哪个路径,部署到哪个集群的哪个命名空间":
# argocd-apps/user-service-production.yaml
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: user-service-production
namespace: argocd # ArgoCD 自己的命名空间
finalizers:
- resources-finalizer.argocd.argoproj.io # 删除 Application 时,同步删除 K8s 资源
spec:
project: production # ArgoCD Project(权限隔离)
# 配置来源
source:
repoURL: https://github.com/your-org/k8s-config-repo.git
targetRevision: main # 监听 main 分支
path: apps/user-service/overlays/production # 配置文件路径
# 部署目标
destination:
server: https://kubernetes.default.svc # 当前集群
namespace: production
# 同步策略
syncPolicy:
automated:
prune: true # 自动删除 Git 里已删除的资源
selfHeal: true # 自动修复漂移(有人手动改了,自动还原)
syncOptions:
- CreateNamespace=true # 命名空间不存在自动创建
- PrunePropagationPolicy=foreground
- ApplyOutOfSyncOnly=true # 只同步有变化的资源,提高效率
retry:
limit: 5
backoff:
duration: 5s
factor: 2
maxDuration: 3mCI/CD 流水线与 ArgoCD 的集成
当应用代码提交后,CI 构建新镜像,然后自动更新配置仓库里的 image tag:
# .github/workflows/deploy.yml
name: Build and Deploy
on:
push:
branches: [main]
jobs:
build:
runs-on: ubuntu-latest
outputs:
image_tag: ${{ steps.meta.outputs.tags }}
steps:
- uses: actions/checkout@v4
- name: Build and push image
uses: docker/build-push-action@v5
with:
push: true
tags: registry.example.com/user-service:${{ github.sha }}
- name: Update config repo
env:
GH_TOKEN: ${{ secrets.CONFIG_REPO_TOKEN }}
run: |
git clone https://github.com/your-org/k8s-config-repo.git
cd k8s-config-repo
# 更新 production 环境的镜像 tag(使用 kustomize)
cd apps/user-service/overlays/production
kustomize edit set image \
registry.example.com/user-service:${{ github.sha }}
git config user.email "ci@example.com"
git config user.name "CI Robot"
git add .
git commit -m "deploy user-service:${{ github.sha }}"
git push
# ArgoCD 会自动检测到 Git 变化并同步踩坑实录一:selfHeal 导致关键操作被还原
现象:生产出了紧急问题,我直接 kubectl edit 改了一个环境变量,5 分钟后发现改动被还原了。
原因:selfHeal: true 就是干这个的——检测到集群状态和 Git 不一致,自动还原。
解法:
方案一:紧急操作时先在 ArgoCD UI 里暂停自动同步(Application → Disable Auto-sync),操作完后再同步回 Git,然后重新开启。
方案二:对于经常需要手动调整的应用,不设 selfHeal: true,只设 automated: {prune: true},漂移时发告警但不自动还原。
# 命令行暂停/恢复自动同步
argocd app set user-service-production --sync-policy none
# ... 手动操作 ...
argocd app set user-service-production --sync-policy automated踩坑实录二:Application 误删后,K8s 资源也被删了
现象:测试环境,有人误删了一个 ArgoCD Application,结果 K8s 里对应的 Deployment、Service 等资源也全部被删了,服务中断。
原因:Application 配置了 finalizers: resources-finalizer.argocd.argoproj.io,这个 finalizer 会在 Application 删除时级联删除所有受管的 K8s 资源。
解法:
- 生产环境 Application 删除前,先去掉 finalizer:
kubectl patch application user-service-production -n argocd \
-p '{"metadata":{"finalizers":[]}}' --type=merge- 考虑是否需要 finalizer——对于测试环境,cascade delete 是方便的;对于生产环境,应该谨慎。
ArgoCD Project:多团队权限隔离
ArgoCD Project 用来隔离不同团队的应用,控制哪些仓库、哪些集群命名空间可以被访问:
apiVersion: argoproj.io/v1alpha1
kind: AppProject
metadata:
name: order-team
namespace: argocd
spec:
description: "订单团队项目"
# 允许从这些仓库部署
sourceRepos:
- "https://github.com/your-org/k8s-config-repo.git"
# 允许部署到这些目标
destinations:
- namespace: "team-order"
server: "https://kubernetes.default.svc"
- namespace: "team-order-staging"
server: "https://kubernetes.default.svc"
# 集群资源权限(不允许创建 ClusterRole 等集群级资源)
clusterResourceWhitelist: []
# 命名空间级资源权限
namespaceResourceWhitelist:
- group: "*"
kind: "*"
roles:
- name: order-team-developer
description: "订单团队开发者"
policies:
- p, proj:order-team:order-team-developer, applications, get, order-team/*, allow
- p, proj:order-team:order-team-developer, applications, sync, order-team/*, allow
# 不允许创建/删除 Application
groups:
- order-team-devs踩坑实录三:Git 仓库配置了分支保护,ArgoCD 同步失败
现象:CI 更新完配置仓库,ArgoCD 检测到变化,但同步时报错"sync failed",查看日志发现是权限问题。
原因:配置仓库的 main 分支开了分支保护,只允许 PR 合并,CI 机器人直接 push 被拒绝了。
解法:
方案一:给 CI 机器人用户加入允许直接 push 的白名单(不推荐,破坏了分支保护的意义)
方案二:CI 更新配置时创建新分支,自动创建 PR,触发 review + 自动合并(适合生产级团队)
方案三:把配置仓库的 main 分支保护关掉,对 source code 仓库保持保护(生产配置仓库只有 CI 机器人写,可以接受)
我们用的是方案三,配置仓库不需要 Code Review 流程,CI 直接写,但所有变更都有 git 历史可追溯。
ArgoCD 是近三年来我觉得最值得引入的 K8s 周边工具。它把"K8s 配置的单一事实来源"这件事落地了,彻底解决了配置漂移问题,也让出了问题时回滚变得非常简单(git revert + 等 ArgoCD 同步)。
