一、概述
1.1 背景介绍
GitOps 作为云原生时代的运维范式,将 Git 作为基础设施和应用配置的单一事实来源,通过声明式配置和自动化同步机制,实现了配置管理的版本控制、审计追溯和快速回滚。ArgoCD 作为 CNCF 毕业项目,提供了完整的 GitOps 工作流,支持多集群管理、RBAC 权限控制、SSO 集成等企业级特性。结合 Kustomize 的配置管理能力,能够优雅地解决多环境配置差异、敏感信息管理、配置复用等问题。
在传统的 CI/CD 流程中,往往由 CI 工具直接执行 kubectl apply,这种推模式存在权限管理复杂、审计困难、状态漂移等问题。ArgoCD 采用拉模式,由运行在集群内的 Controller 主动从 Git 仓库拉取配置并应用,实现了部署权限的收敛和状态的持续同步。
1.2 技术特点
声明式部署:基于 Kubernetes 资源清单定义期望状态,ArgoCD 自动检测并消除实际状态与期望状态的偏差 多集群管理:单个 ArgoCD 实例可管理数百个 Kubernetes 集群,支持集群级别的 RBAC 和资源隔离 自动同步策略:支持手动同步、自动同步、自动修剪(Prune)、自愈(Self-Heal)等多种策略组合 回滚与审计:完整记录每次同步操作,支持一键回滚到任意历史版本,所有变更可追溯到 Git commit 健康检查:内置对 Deployment、StatefulSet、Service、Ingress 等资源的健康检查,支持自定义健康检查脚本 SSO 集成:支持 OAuth2、OIDC、SAML、LDAP 等多种认证方式,可与企业统一认证系统集成 渐进式交付:集成 Argo Rollouts 实现蓝绿部署、金丝雀发布、流量分析等高级发布策略
1.3 适用场景
场景一:多环境配置管理,通过 Kustomize overlay 机制管理 dev/staging/prod 等环境的配置差异,避免重复维护相似配置 场景二:多集群应用分发,使用 ApplicationSet 批量创建 Application,实现应用在多个集群、多个命名空间的标准化部署 场景三:基础设施即代码,将集群基础组件(Ingress Controller、监控栈、日志收集等)以 GitOps 方式管理,实现集群配置的版本化 场景四:合规审计与权限管控,所有变更通过 Git PR 审批,部署操作由 ArgoCD 执行,开发人员无需直接访问生产集群 场景五:灾难恢复,集群配置存储在 Git,可快速在新集群重建全部应用,Recovery Time 从小时级降至分钟级
1.4 环境要求
二、详细步骤
2.1 准备工作
2.1.1 系统检查
# 验证 Kubernetes 集群状态
kubectl cluster-info
kubectl get nodes
kubectl version --short
# 检查集群资源配额
kubectl top nodes
kubectl describe quota --all-namespaces
# 验证存储类(ArgoCD 需要持久化存储)
kubectl get storageclass
2.1.2 安装依赖
# 创建 ArgoCD 命名空间
kubectl create namespace argocd
# 安装 ArgoCD(使用官方稳定版本)
kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml
# 等待所有组件就绪
kubectl wait --for=condition=available --timeout=600s \
deployment/argocd-server \
deployment/argocd-repo-server \
deployment/argocd-dex-server \
deployment/argocd-redis \
-n argocd
# 安装 ArgoCD CLI
VERSION=$(curl -s https://api.github.com/repos/argoproj/argo-cd/releases/latest | grep tag_name | cut -d '"' -f 4)
curl -sSL -o argocd-linux-amd64 "https://github.com/argoproj/argo-cd/releases/download/${VERSION}/argocd-linux-amd64"
sudo install -m 555 argocd-linux-amd64 /usr/local/bin/argocd
rm argocd-linux-amd64
# 验证安装
argocd version
2.2 核心配置
2.2.1 暴露 ArgoCD API Server
# 方式一:LoadBalancer(云环境推荐)
kubectl patch svc argocd-server -n argocd -p '{"spec": {"type": "LoadBalancer"}}'
# 方式二:Ingress(内网环境推荐)
cat <<EOF | kubectl apply -f -
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:
name: https
tls:
- hosts:
- argocd.example.com
secretName: argocd-server-tls
EOF
# 方式三:端口转发(开发测试)
kubectl port-forward svc/argocd-server -n argocd 8080:443
说明:生产环境建议使用 Ingress + TLS 证书,避免暴露 LoadBalancer 公网 IP。SSL Passthrough 保证端到端加密,ArgoCD Server 使用自签名证书或配置自定义证书。
2.2.2 初始化 ArgoCD
# 获取初始 admin 密码
ARGOCD_PASSWORD=$(kubectl -n argocd get secret argocd-initial-admin-secret \
-o jsonpath="{.data.password}" | base64 -d)
echo "ArgoCD admin password: ${ARGOCD_PASSWORD}"
# 登录 ArgoCD
argocd login argocd.example.com --username admin --password "${ARGOCD_PASSWORD}" --grpc-web
# 修改 admin 密码
argocd account update-password
# 删除初始密码 Secret(安全加固)
kubectl -n argocd delete secret argocd-initial-admin-secret
2.2.3 配置 Git 仓库凭证
# 方式一:HTTPS 认证(使用 Personal Access Token)
argocd repo add https://github.com/your-org/your-repo.git \
--username git \
--password ghp_xxxxxxxxxxxxxxxxxxxx \
--name my-repo
# 方式二:SSH 认证(推荐)
# 生成 SSH 密钥对
ssh-keygen -t ed25519 -C "argocd@example.com" -f ~/.ssh/argocd_ed25519 -N ""
# 将公钥添加到 Git 仓库的 Deploy Keys
cat ~/.ssh/argocd_ed25519.pub
# 添加私钥到 ArgoCD
argocd repo add git@github.com:your-org/your-repo.git \
--ssh-private-key-path ~/.ssh/argocd_ed25519 \
--name my-repo
# 验证仓库连接
argocd repo list
参数说明:
--insecure-skip-server-verification:跳过 Git 服务器 TLS 验证(自签名证书场景)--proxy:配置代理服务器访问外部 Git 仓库--enable-lfs:启用 Git LFS 支持大文件
2.3 启动和验证
2.3.1 创建 Application
# application.yaml
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: guestbook
namespace: argocd
# Finalizer 确保删除 Application 时同步删除已部署资源
finalizers:
- resources-finalizer.argocd.argoproj.io
spec:
project: default
source:
# Git 仓库地址
repoURL: https://github.com/argoproj/argocd-example-apps.git
targetRevision: HEAD
path: guestbook
destination:
server: https://kubernetes.default.svc
namespace: default
syncPolicy:
automated:
prune: true # 自动删除 Git 中不存在的资源
selfHeal: true # 自动修复手动修改
allowEmpty: false
syncOptions:
- CreateNamespace=true # 自动创建目标命名空间
retry:
limit: 5
backoff:
duration: 5s
factor: 2
maxDuration: 3m
# 应用配置
kubectl apply -f application.yaml
# 查看 Application 状态
argocd app get guestbook
# 查看同步历史
argocd app history guestbook
# 手动触发同步
argocd app sync guestbook
# 查看实时日志
argocd app logs guestbook --follow
2.3.2 功能验证
# 验证 Application 健康状态
argocd app list
# 预期输出:
# NAME CLUSTER NAMESPACE PROJECT STATUS HEALTH SYNCPOLICY
# guestbook https://kubernetes.default.svc default default Synced Healthy Auto-Prune
# 验证资源同步状态
kubectl get all -n default -l app.kubernetes.io/instance=guestbook
# 测试自愈功能(手动修改资源)
kubectl scale deployment guestbook-ui -n default --replicas=5
# 等待 3 秒,ArgoCD 自动恢复副本数
# 测试修剪功能(从 Git 删除资源)
# 1. 从 Git 仓库删除某个 YAML 文件并提交
# 2. 观察 ArgoCD 自动删除对应资源
argocd app wait guestbook --health
三、示例代码和配置
3.1 完整配置示例
3.1.1 Kustomize 多环境配置结构
# 仓库目录结构
├── base/
│ ├── kustomization.yaml
│ ├── deployment.yaml
│ ├── service.yaml
│ └── configmap.yaml
├── overlays/
│ ├── dev/
│ │ ├── kustomization.yaml
│ │ ├── replica-patch.yaml
│ │ └── configmap-patch.yaml
│ ├── staging/
│ │ ├── kustomization.yaml
│ │ └── resources-patch.yaml
│ └── prod/
│ ├── kustomization.yaml
│ ├── replica-patch.yaml
│ ├── hpa.yaml
│ └── pdb.yaml
# base/kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- deployment.yaml
- service.yaml
- configmap.yaml
commonLabels:
app: myapp
managed-by: argocd
namespace: myapp
images:
- name: myapp
newName: registry.example.com/myapp
newTag: latest
# base/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp
spec:
replicas: 1
selector:
matchLabels:
app: myapp
template:
metadata:
labels:
app: myapp
spec:
containers:
- name: myapp
image: myapp
ports:
- containerPort: 8080
resources:
requests:
cpu: 100m
memory: 128Mi
limits:
cpu: 500m
memory: 512Mi
envFrom:
- configMapRef:
name: myapp-config
livenessProbe:
httpGet:
path: /health
port: 8080
initialDelaySeconds: 30
periodSeconds: 10
readinessProbe:
httpGet:
path: /ready
port: 8080
initialDelaySeconds: 5
periodSeconds: 5
# overlays/prod/kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
namespace: myapp-prod
bases:
- ../../base
patchesStrategicMerge:
- replica-patch.yaml
resources:
- hpa.yaml
- pdb.yaml
images:
- name: myapp
newTag: v1.2.3 # 生产环境固定版本
configMapGenerator:
- name: myapp-config
behavior: merge
literals:
- LOG_LEVEL=info
- ENVIRONMENT=production
- DB_POOL_SIZE=50
# overlays/prod/replica-patch.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp
spec:
replicas: 5
template:
spec:
containers:
- name: myapp
resources:
requests:
cpu: 500m
memory: 1Gi
limits:
cpu: 2000m
memory: 4Gi
# overlays/prod/hpa.yaml
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: myapp
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: myapp
minReplicas: 5
maxReplicas: 20
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 70
- type: Resource
resource:
name: memory
target:
type: Utilization
averageUtilization: 80
behavior:
scaleDown:
stabilizationWindowSeconds: 300
policies:
- type: Percent
value: 50
periodSeconds: 60
scaleUp:
stabilizationWindowSeconds: 0
policies:
- type: Percent
value: 100
periodSeconds: 30
- type: Pods
value: 4
periodSeconds: 30
selectPolicy: Max
3.1.2 ApplicationSet 批量管理
# applicationset.yaml - 多集群部署
apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
name: myapp-multi-cluster
namespace: argocd
spec:
generators:
- matrix:
generators:
- git:
repoURL: https://github.com/your-org/your-repo.git
revision: HEAD
directories:
- path: overlays/*
- clusters:
selector:
matchLabels:
environment: production
template:
metadata:
name: 'myapp-{{path.basename}}-{{name}}'
spec:
project: default
source:
repoURL: https://github.com/your-org/your-repo.git
targetRevision: HEAD
path: '{{path}}'
destination:
server: '{{server}}'
namespace: 'myapp-{{path.basename}}'
syncPolicy:
automated:
prune: true
selfHeal: true
syncOptions:
- CreateNamespace=true
3.2 实际应用案例
案例一:配置敏感信息管理
场景描述:使用 Sealed Secrets 或 External Secrets Operator 管理数据库密码、API Key 等敏感信息,避免明文存储在 Git 仓库。
实现代码:
# 安装 Sealed Secrets Controller
kubectl apply -f https://github.com/bitnami-labs/sealed-secrets/releases/download/v0.24.0/controller.yaml
# 创建 Secret 并加密
echo -n 'my-db-password' | kubectl create secret generic db-credentials \
--dry-run=client \
--from-file=password=/dev/stdin \
-o yaml | \
kubeseal -o yaml > sealed-secret.yaml
# sealed-secret.yaml(可安全提交到 Git)
apiVersion: bitnami.com/v1alpha1
kind: SealedSecret
metadata:
name: db-credentials
namespace: default
spec:
encryptedData:
password: AgBy3i4OJSWK+PiTySYZZA9rO43cGDEq...
template:
metadata:
name: db-credentials
namespace: default
type: Opaque
运行结果:
# ArgoCD 同步后自动解密为 Secret
kubectl get secret db-credentials -o jsonpath='{.data.password}' | base64 -d
# 输出:my-db-password
案例二:RBAC 权限配置
场景描述:为开发团队配置只读权限,仅允许查看 dev 环境应用状态,禁止同步操作;为运维团队配置全部环境的管理权限。
实现步骤:
创建 AppProject 隔离资源
# project-dev.yaml
apiVersion: argoproj.io/v1alpha1
kind: AppProject
metadata:
name: dev-project
namespace: argocd
spec:
description: Development environment project
sourceRepos:
- 'https://github.com/your-org/*'
destinations:
- namespace: 'dev-*'
server: https://kubernetes.default.svc
clusterResourceWhitelist:
- group: ''
kind: Namespace
namespaceResourceWhitelist:
- group: 'apps'
kind: Deployment
- group: ''
kind: Service
- group: ''
kind: ConfigMap
roles:
- name: developer
description: Read-only access to dev apps
policies:
- p, proj:dev-project:developer, applications, get, dev-project/*, allow
- p, proj:dev-project:developer, logs, get, dev-project/*, allow
groups:
- dev-team
配置 ArgoCD RBAC
# argocd-rbac-cm ConfigMap
apiVersion: v1
kind: ConfigMap
metadata:
name: argocd-rbac-cm
namespace: argocd
data:
policy.default: role:readonly
policy.csv: |
# 运维团队全部权限
g, ops-team, role:admin
# 开发团队限制权限
p, role:developer, applications, get, */*, allow
p, role:developer, applications, sync, dev-project/*, allow
p, role:developer, logs, get, */*, allow
g, dev-team, role:developer
# 禁止删除生产应用
p, role:developer, applications, delete, prod-project/*, deny
集成 OIDC SSO(以 Keycloak 为例)
# argocd-cm ConfigMap
apiVersion: v1
kind: ConfigMap
metadata:
name: argocd-cm
namespace: argocd
data:
url: https://argocd.example.com
oidc.config: |
name: Keycloak
issuer: https://keycloak.example.com/realms/master
clientID: argocd
clientSecret: $oidc.keycloak.clientSecret
requestedScopes:
- openid
- profile
- email
- groups
