【K8S 运维实战】32-GitOps实践ArgoCD

GitOps 实践:ArgoCD 持续交付 > 从"手工 kubectl apply"到"Git 驱动、自动同步、可回滚"的部署体系

写在前面

你可能还在用 Jenkins/GitLab CI 构建镜像,然后一个 kubectl apply -f deployment.yaml 推到集群。这叫 CI 驱动部署------流水线"推"着集群走。问题很明显:谁改了集群配置没人知道,回滚靠人脑记 Git commit,多环境手动操作出错率高。GitOps 是另一条路:集群的状态永远由 Git 仓库定义,ArgoCD 自动拉取并同步。你改 Git,ArgoCD 改集群;集群有人偷偷 kubectl edit,ArgoCD 会自动拉回来(自愈)。这篇文章从 GitOps 四原则出发,带你落地 ArgoCD 多环境管理、渐进式交付(Argo Rollouts)、通知和 SSO,让部署从"手工活"变成"Git 驱动的自动化闭环"。

核心问题

部署怎么从"手工 kubectl"进化到"Git 驱动、自动同步、可回滚"的持续交付体系?


一、原理剖析

1.1 GitOps 四原则

GitOps 不是"把 kubectl 命令写进 CI pipeline"那么简单,它有四个核心原则,缺一个就不完整:

复制代码
┌──────────────────────────────────────────────────────────────┐
│  GitOps 四原则                                               │
├──────────────────┬───────────────────────────────────────────┤
│  1. 声明式       │  集群期望状态用声明式描述(YAML/Helm/Kust) │
│                  │  不写脚本,不写 kubectl 命令              │
├──────────────────┼───────────────────────────────────────────┤
│  2. 版本化       │  所有声明存入 Git,每次变更都是一个 commit │
│                  │  回滚 = git revert,审计 = git log        │
├──────────────────┼───────────────────────────────────────────┤
│  3. 自动拉取     │  自动化系统(ArgoCD)持续拉取 Git,        │
│                  │  发现差异后自动同步到集群                 │
├──────────────────┼───────────────────────────────────────────┤
│  4. 自愈         │  集群被手动修改后,ArgoCD 检测到          │
│                  │  OutOfSync 状态,自动拉回 Git 定义的状态  │
└──────────────────┴───────────────────────────────────────────┘

对比传统 CI Push 模型:

复制代码
传统 CI Push:
  Git → CI Pipeline → 构建镜像 → kubectl apply → 集群
  问题: 集群状态 ≠ Git 状态;没有自愈;回滚靠人

GitOps Pull:
  Git → ArgoCD 拉取 → 对比集群状态 → 自动/手动同步 → 集群
  优势: 集群状态 = Git 状态;自愈;回滚 = git revert

1.2 ArgoCD 架构

复制代码
                    ┌─────────────────────┐
                    │   Git Repositories   │
                    │ (Helm/Kust/YAML)    │
                    └──────────┬──────────┘
                               │
                    ┌──────────▼──────────┐
                    │    Repo Server       │
                    │ (拉取Git+渲染模板)   │
                    └──────────┬──────────┘
                               │ 渲染后的目标清单
                    ┌──────────▼──────────┐
                    │  Application Ctrl    │◄── UI/API/CLI
                    │ (对比目标vs实际状态) │
                    │  OutOfSync → Sync   │
                    └──────────┬──────────┘
                               │
                    ┌──────────▼──────────┐
                    │  Kubernetes Cluster  │
                    │ (实际运行状态)       │
                    └──────────┬──────────┘
                               │
                    ┌──────────▼──────────┐
                    │ Notification Ctrl    │
                    │ (Sync结果/健康变化   │
                    │  → Slack/Email/Webhook) │
                    └─────────────────────┘

核心组件:

  • Application Controller: 核心,持续对比 Git 目标状态与集群实际状态,发现差异触发 Sync
  • Repo Server: 从 Git 仓库拉取配置,渲染 Helm/Kustomize,输出最终 YAML 清单
  • API Server / UI: 用户交互入口,查看状态、手动同步、管理 Application
  • Notification Controller: 监听 Application 状态变化,发送通知(Slack/Email/Webhook)

关键概念:

  • Application: ArgoCD 的核心资源,定义"一个 Git 仓库的某个路径 → 同步到集群的某个 namespace"
  • Source: Git 仓库地址+路径+分支+revision,可指定 Helm values 覆盖
  • Project: 资源隔离边界,控制哪些 namespace/cluster/仓库可以被使用
  • Sync Policy : auto(自动同步) / manual(手动审批) / auto+prune(自动同步+自动删除不在 Git 里的资源)

1.3 多环境管理:App of Apps 与 ApplicationSet

当你的环境从 1 个变成 5 个(dev/staging/prod + 2 个区域),每个环境都要定义 Application,手动管理太痛了。

App of Apps 模式:

复制代码
Git: argocd-apps/
├── apps/
│   ├── dev.yaml        # dev 環境的 Application 列表
│   ├── staging.yaml    # staging 環境
│   └── prod.yaml       # prod 環境
│   └── root.yaml       # "App of Apps"------引用上面三个

root.yaml:

yaml 复制代码
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: root-app
  namespace: argocd
spec:
  source:
    repoURL: https://git.internal/argocd-apps
    path: apps
    targetRevision: main
  destination:
    server: https://kubernetes.default.svc
    namespace: argocd
  syncPolicy:
    automated:
      prune: true
      selfHeal: true

ApplicationSet 模式(推荐):

ApplicationSet 用模板+生成器批量创建 Application,比 App of Apps 更灵活:

复制代码
ApplicationSet 工作原理:
  Generator(生成目标列表) + Template(Application模板) = 多个 Application

  ┌─────────────┐      ┌──────────────┐
  │  Generator   │ ───► │  Template    │ ───► 生成 N 个 Application
  │ (集群列表/   │      │ (Application │
  │  Git目录/    │      │  定义模板)   │
  │  環境列表)   │      └──────────────┘
  └─────────────┘

1.4 Argo Rollouts:渐进式交付

ArgoCD 负责同步,Argo Rollouts 负责"怎么安全地推进新版本"。Rollouts 是 Deployment 的替代品,支持金丝雀/蓝绿/渐进式发布+自动化分析。

复制代码
Argo Rollouts 金丝雀流程:

  Stable (v1) ──► Canary (v2, 10%流量)
                    │
                    ├─ AnalysisTemplate: 检查错误率/延迟
                    │  ├─ Pass → 增加到 30% 流量
                    │  ├─ Fail → 自动回滚到 v1
                    │  └─ Continue → 等待下一步
                    │
                    ├─ 30% → Analysis again → Pass
                    │
                    ├─ 60% → Analysis again → Pass
                    │
                    └─ 100% → Promote, v2 成为 Stable

  关键组件:
  - Rollout: 替代 Deployment 的 CRD,定义发布策略
  - AnalysisTemplate: 定义指标检查条件(Prometheus/Web/Job)
  - AnalysisRun: 一次实际的分析执行
  - Experiment: 可在金丝雀期间运行并行实验

二、实战操作

2.1 ArgoCD 安装

bash 复制代码
# 安装 ArgoCD(K8s 1.30 兼容版本 v2.12)
kubectl create namespace argocd
kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/v2.12.0/stable/install.yaml

# 获取初始 admin 密码
kubectl -n argocd get secret argocd-initial-admin-secret \
  -o jsonpath="{.data.password}" | base64 -d

# 安装 argocd CLI
curl -sLO https://github.com/argoproj/argo-cd/releases/download/v2.12.0/argocd-linux-amd64
chmod +x argocd-linux-amd64
mv argocd-linux-amd64 /usr/local/bin/argocd

# 访问 UI(端口转发)
kubectl port-forward svc/argocd-server -n argocd 8080:443 &
# 浏览器访问 https://localhost:8080

# 登录
argocd login localhost:8080 --username admin --password <上面获取的密码>

2.2 ApplicationSet 多环境方案

cluster-appset.yaml --- 按集群生成 Application:

yaml 复制代码
apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
  name: myapp-clusters
  namespace: argocd
spec:
  generators:
    - list:
        elements:
          - cluster: dev-cluster
            url: https://dev.k8s.internal
            env: dev
            values:
              replicaCount: 1
              imageTag: latest
          - cluster: staging-cluster
            url: https://staging.k8s.internal
            env: staging
            values:
              replicaCount: 2
              imageTag: v2.4.1-rc1
          - cluster: prod-cluster
            url: https://prod.k8s.internal
            env: prod
            values:
              replicaCount: 3
              imageTag: v2.4.1
  template:
    metadata:
      name: "myapp-{{env}}"
      labels:
        env: "{{env}}"
    spec:
      project: default
      source:
        repoURL: https://git.internal/platform/myapp-deploy
        targetRevision: main
        path: helm/myapp
        helm:
          valueFiles:
            - values.yaml
            - "values-{{env}}.yaml"
          parameters:
            - name: replicaCount
              value: "{{values.replicaCount}}"
            - name: image.tag
              value: "{{values.imageTag}}"
      destination:
        server: "{{url}}"
        namespace: myapp
      syncPolicy:
        automated:
          prune: true
          selfHeal: true
        syncOptions:
          - CreateNamespace=true
          - ServerSideApply=true

Git 目录模式生成器 --- 每个环境一个目录:

yaml 复制代码
apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
  name: myapp-git-dir
  namespace: argocd
spec:
  generators:
    - git:
        repoURL: https://git.internal/platform/myapp-deploy
        revision: main
        directories:
          - path: envs/*  # 匹配 envs/dev、envs/staging、envs/prod
  template:
    metadata:
      name: "myapp-{{path.basename}}"
    spec:
      project: default
      source:
        repoURL: https://git.internal/platform/myapp-deploy
        targetRevision: main
        path: "{{path}}"
      destination:
        server: https://kubernetes.default.svc
        namespace: "myapp-{{path.basename}}"
      syncPolicy:
        automated:
          prune: true
          selfHeal: true

Git 仓库结构:

复制代码
myapp-deploy/
├── envs/
│   ├── dev/
│   │   └── kustomization.yaml
│   │   └── patch-replicas.yaml     # replicas: 1
│   ├── staging/
│   │   └── kustomization.yaml
│   │   └── patch-replicas.yaml     # replicas: 2
│   └── prod/
│   │   └── kustomization.yaml
│   │   └── patch-replicas.yaml     # replicas: 3
│   │   └── patch-resources.yaml    # 更大的资源限制

2.3 Argo Rollouts 金丝雀发布

先安装 Argo Rollouts:

bash 复制代码
kubectl create namespace argo-rollouts
kubectl apply -n argo-rollouts -f https://raw.githubusercontent.com/argoproj/argo-rollouts/v2.37.0/stable/install.yaml

# 安装 kubectl argo-rollouts 插件
curl -sLO https://github.com/argoproj/argo-rollouts/releases/download/v2.37.0/kubectl-argo-rollouts-linux-amd64
chmod +x ./kubectl-argo-rollouts-linux-amd64
mv ./kubectl-argo-rollouts-linux-amd64 /usr/local/bin/kubectl-argo-rollouts

rollout.yaml --- 金丝雀发布策略:

yaml 复制代码
apiVersion: argoproj.io/v1alpha1
kind: Rollout
metadata:
  name: myapp-rollout
  namespace: myapp
spec:
  replicas: 5
  strategy:
    canary:
      canaryService: myapp-canary      # 金丝雀 Service
      stableService: myapp-stable      # 稳定版 Service
      trafficRouting:
        istio:
          virtualService:
            name: myapp-vsvc
            routes:
              - primary
          destinationRules:
            name: myapp-dr
      steps:
        - setWeight: 10                 # 10% 流量到金丝雀
        - pause: {duration: 5m}        # 观察 5 分钟
        - analysis:
            templates:
              - templateName: error-rate-check
            args:
              - name: service-name
                value: myapp-canary.default.svc.cluster.local
        - setWeight: 30                # 分析通过,30% 流量
        - pause: {duration: 5m}
        - analysis:
            templates:
              - templateName: latency-check
        - setWeight: 60
        - pause: {duration: 2m}
        - setWeight: 100               # 全量发布
  revisionHistoryLimit: 3
  selector:
    matchLabels:
      app: myapp
  template:
    metadata:
      labels:
        app: myapp
    spec:
      containers:
        - name: myapp
          image: registry.internal/company/myapp:v2.4.1
          ports:
            - containerPort: 8080
          resources:
            requests:
              cpu: 100m
              memory: 128Mi

AnalysisTemplate --- 基于 Prometheus 的自动化分析:

yaml 复制代码
apiVersion: argoproj.io/v1alpha1
kind: AnalysisTemplate
metadata:
  name: error-rate-check
  namespace: myapp
spec:
  args:
    - name: service-name
  metrics:
    - name: error-rate
      interval: 30s
      count: 6                          # 6 次采样 = 3 分钟
      successLimit: 5                   # 至少 5 次通过
      failureLimit: 2                   # 2 次失败就中止金丝雀
      provider:
        prometheus:
          address: http://prometheus.monitoring:9090
          query: >
            sum(rate(http_requests_total{status_code=~"5..",
            app="{{args.service-name}}"}[1m]))
            /
            sum(rate(http_requests_total{app="{{args.service-name}"}[1m]))
      successCondition: result[0] < 0.01   # 错误率 < 1%
      failureCondition: result[0] >= 0.05   # 错误率 >= 5%
yaml 复制代码
apiVersion: argoproj.io/v1alpha1
kind: AnalysisTemplate
metadata:
  name: latency-check
  namespace: myapp
spec:
  metrics:
    - name: p99-latency
      interval: 30s
      count: 4
      successLimit: 3
      failureLimit: 2
      provider:
        prometheus:
          address: http://prometheus.monitoring:9090
          query: >
            histogram_quantile(0.99,
            sum(rate(http_request_duration_seconds_bucket{app="myapp-canary"}[1m]))
            by (le))
      successCondition: result[0] < 2    # P99 < 2秒
      failureCondition: result[0] >= 5   # P99 >= 5秒

Istio VirtualService + DestinationRule 配合金丝雀流量分割:

yaml 复制代码
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
  name: myapp-vsvc
  namespace: myapp
spec:
  hosts:
    - myapp.company.com
  gateways:
    - myapp-gateway
  http:
    - name: primary
      route:
        - destination:
            host: myapp-stable
          weight: 100
        - destination:
            host: myapp-canary
          weight: 0
yaml 复制代码
apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:
  name: myapp-dr
  namespace: myapp
spec:
  host: myapp-stable
  trafficPolicy:
    connectionPool:
      http:
        h2UpgradePolicy: DEFAULT

操作命令:

bash 复制代码
# 查看发布状态
kubectl argo-rollouts get rollout myapp-rollout -n myapp

# 手动推进金丝雀(如果设了 pause)
kubectl argo-rollouts promote myapp-rollout -n myapp

# 手动回滚
kubectl argo-rollouts undo myapp-rollout -n myapp

# 查看分析结果
kubectl argo-rollouts list analysisruns -n myapp

2.4 ArgoCD SSO/OIDC 认证

生产环境不能用 admin 账号,必须接 SSO。

argocd-cm.yaml --- OIDC 配置(以公司内部 IdP 为例):

yaml 复制代码
apiVersion: v1
kind: ConfigMap
metadata:
  name: argocd-cm
  namespace: argocd
data:
  url: https://argocd.company.com
  oidc.config: |
    name: CompanySSO
    issuer: https://idp.company.com/realms/platform
    clientID: argocd-prod
    clientSecret: $oidc.company.clientSecret  # 引用 argocd-secret 中的值
    requestedScopes: ["openid", "profile", "email", "groups"]
    requestedIDTokenClaims: {"groups": {"essential": true}}

RBAC 配置 --- argocd-rbac-cm.yaml:

yaml 复制代码
apiVersion: v1
kind: ConfigMap
metadata:
  name: argocd-rbac-cm
  namespace: argocd
data:
  policy.csv: |
    # 管理员组:全局读写
    g, platform-admins, role:admin
    # 开发组:只能操作 dev 環境的 Application
    g, dev-team, role:dev-developer
    # 定义自定义角色
    p, role:dev-developer, applications, get, dev/*, allow
    p, role:dev-developer, applications, sync, dev/*, allow
    p, role:dev-developer, applications, create, dev/*, allow
    # 生产组:只能查看,不能自动同步
    g, prod-team, role:prod-viewer
    p, role:prod-viewer, applications, get, prod/*, allow
    p, role:prod-viewer, applications, sync, prod/*, deny
  policy.default: role:readonly

2.5 通知配置

argocd-notification-cm.yaml:

yaml 复制代码
apiVersion: v1
kind: ConfigMap
metadata:
  name: argocd-notifications-cm
  namespace: argocd
data:
  template.app-deployed: |
    email:
      subject: "[ArgoCD] {{ .app.metadata.name }} deployed to {{ .app.spec.destination.namespace }}"
    slack:
      blocks:
        - type: section
          text:
            type: mrkdwn
            text: ":white_check_mark: **{{ .app.metadata.name }}** synced to **{{ .app.spec.destination.namespace }}**"
        - type: context
          elements:
            - type: mrkdwn
              text: "Revision: {{ .app.status.operationState.syncResult.revision }}"
    webhook:
      myapp-deployed:
        method: POST
        path: /deployments
        body: |
          {"app": "{{ .app.metadata.name }}", "env": "{{ .app.spec.destination.namespace }}", "revision": "{{ .app.status.operationState.syncResult.revision }}"}

  trigger.on-deployed: |
    - description: Application deployed
      oncePer: app.metadata.name
      send:
        - template.app-deployed
      when: app.status.operationState.phase in [Succeeded]

  trigger.on-sync-failed: |
    - description: Sync failed
      send:
        - template.app-sync-failed
      when: app.status.operationState.phase in [Failed, Error]

  service.slack: |
    apiUrl: https://slack.com/api/chat.postMessage
    token: $slack-token
    channels:
      - name: argocd-deployments
  service.email: |
    host: smtp.company.com
    port: 587
    from: argocd@company.com
    username: argocd@company.com
    password: $email-password

给 Application 添加通知订阅:

yaml 复制代码
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: myapp
  namespace: argocd
  annotations:
    notifications.argoproj.io/subscribe.on-deployed.slack: argocd-deployments
    notifications.argoproj.io/subscribe.on-sync-failed.slack: argocd-deployments
    notifications.argoproj.io/subscribe.on-deployed.email: dev-team@company.com
spec:
  # ... (Application 定义)

三、踩坑与排查

踩坑 1:ArgoCD Sync 成功但 Application 状态一直 Progressing

现象 : argocd app get myapp 显示 Sync Status: Synced,但 Health Status: Progressing,永远不变成 Healthy。

原因: ArgoCD 的 Health Check 不仅看资源是否创建成功,还看资源是否"就绪"。Deployment 必须所有 Pod Ready;Pod 必须所有 Container Running;Job 必须 Completed。如果你的 Pod 因为 readinessProbe 不通过而一直 Not Ready,Health 就卡在 Progressing。

bash 复制代码
# 查看 ArgoCD 的健康判断逻辑
kubectl get deploy myapp -n myapp -o jsonpath='{.status.conditions}'
# 常见问题:replicas=3,availableReplicas=2,updatingReplicas=1

解决:

bash 复制代码
# 方法 1:检查 Pod 状态
kubectl get pods -n myapp -l app=myapp
kubectl describe pod <pod-name> -n myapp | grep -A5 "Readiness"

# 方法 2:如果 Probe 配置合理但 ArgoCD 仍不识别,自定义 Health Check
# argocd-cm 中添加自定义健康规则:
yaml 复制代码
apiVersion: v1
kind: ConfigMap
metadata:
  name: argocd-cm
  namespace: argocd
data:
  resource.customizations.health.apps_Deployment: |
    hs = {}
    if obj.status ~= nil then
      if obj.status.readyReplicas == obj.status.replicas then
        hs.status = "Healthy"
        hs.message = "All replicas ready"
      else
        hs.status = "Progressing"
        hs.message = "Waiting for replicas: " .. obj.status.readyReplicas .. "/" .. obj.status.replicas
      end
    end
    return hs

蹈坑 2:SelfHeal 把紧急手动修复又"拉回"了错误状态

现象 : 生产出了严重 bug,运维手动 kubectl scale deployment myapp --replicas=10 应急,ArgoCD 检测到 OutOfSync,5 分钟后自动把 replicas 拉回 Git 里的 3,应急措施失效。

原因 : selfHeal: true 会让 ArgoCD 在检测到任何偏差时自动同步。这在平时是好事(防止手动修改漂移),但在紧急场景下会" Undo"你的应急操作。

解决:

yaml 复制代码
# 方法 1:临时关闭自愈(推荐)
# 在 Application 上加 annotation:
annotations:
  argocd.argoproj.io/sync-options: SelfHeal=false

# 方法 2:先改 Git 再让 ArgoCD 同步(最安全)
# kubectl scale 后,立即在 Git 仓库改 values-prod.yaml 的 replicaCount=10
# ArgoCD 同步后集群状态和 Git 一致

# 方法 3:使用 ArgoCD 的 "Sync Window" 限制自愈时间
# 只在非工作时间自愈:
yaml 复制代码
apiVersion: argoproj.io/v1alpha1
kind: AppProject
metadata:
  name: default
  namespace: argocd
spec:
  syncWindows:
    - kind: allow
      schedule: "10 1 * * *"     # 每天凌晨 1:10 允许同步
      duration: 8h               # 持续 8 小时
      applications:
        - name: myapp-prod
      manualSync: true           # 其他时间只允许手动同步

踩坑 3:Argo Rollouts 金丝雀 AnalysisTemplate 查不到 Prometheus 数据

现象 : 金丝雀到 analysis 步骤时,AnalysisRun 一直 Running 不出结果,最终金丝雀超时回滚。

原因: AnalysisTemplate 的 Prometheus query 写错了 service-name 变量,或者 Prometheus 在另一个集群,Argo Rollouts 网络不通。

bash 复制代码
# 查看 AnalysisRun 详细状态
kubectl get analysisrun -n myapp -l rollouts=myapp-rollout
kubectl describe analysisrun <analysisrun-name> -n myapp
# 常见错误: "failed to query prometheus: connection refused"

解决:

bash 复制代码
# 1. 验证 Prometheus 可达
kubectl run curl-test --rm -it --restart=Never --image=curlimages/curl \
  -- curl -s "http://prometheus.monitoring:9090/api/v1/query?query=up"

# 2. 验证 query 语法(在 Prometheus UI 先试)
# 把 AnalysisTemplate 里的 query 拿到 Prometheus Graph 页面跑一遍

# 3. 确保 args 替换正确
# AnalysisTemplate 中 {{args.service-name}} 必须与 Rollout 的 analysis.args 匹配
# Rollout 定义:
#   analysis:
#     templates:
#       - templateName: error-rate-check
#     args:
#       - name: service-name
#         value: myapp-canary.myapp.svc.cluster.local  # 完整 DNS 名称

踩坑 4:ApplicationSet 生成太多 Application 导致 ArgoCD 性能下降

现象 : ArgoCD UI 加载缓慢,argocd app list 响应慢,Application Controller CPU 持续高。

原因: ApplicationSet 的 List Generator 有 30 个集群 × 20 个应用 = 600 个 Application,ArgoCD 每个都要持续对比 Git 状态,API Server 扛不住。

解决:

yaml 复制代码
# 方法 1:减少对比频率(降低 reconcile 循环)
# argocd-cm:
data:
  timeout.reconciliation: 300s    # 从默认 180s 改为 300s

# 方法 2:用 Git Directory Generator 替代 List Generator
# 让 Git 仓库结构决定 Application 数量,而不是硬编码

# 方法 3:按环境拆分多个 ApplicationSet
# 不要一个 AppSet 生成所有环境,每个环境一个 AppSet:
yaml 复制代码
# prod-appset.yaml (只管 prod)
apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
  name: myapp-prod
  namespace: argocd
spec:
  generators:
    - clusters:
        selector:
          matchLabels:
            env: prod   # 只选择 prod 集群
  template:
    # ...

四、最佳实践

ArgoCD 生产部署清单

项目 建议 说明
HA 部署 Application Controller 3 replicas 生产必须 HA
Redis 用外部 Redis(HA) 不用内置单节点 Redis
Repo Server 2+ replicas Git 仓库压力大时需要
资源限制 Controller 2CPU/2Gi,Repo 1CPU/1Gi 防止 OOM
SSO 必须接 OIDC 不用 admin 密码
RBAC 精细到 project+namespace dev 不能操作 prod
自愈 prod 环境建议 manual sync 紧急修改不被 Undo
通知 必须配置 Slack/Email 同步失败第一时间知道
Git 分支 prod 用 main 分支,dev 用 develop 分支与环境对应
资源跟踪 使用 annotation-based tracking 防止命名冲突
Secret 管理 用 Sealed Secrets / SOPS Secret 不裸放 Git

GitOps 仓库结构推荐

复制代码
platform-deploy/
├── argocd/
│   ├── appsets/           # ApplicationSet 定义
│   │   ├── dev.yaml
│   │   ├── staging.yaml
│   │   └── prod.yaml
│   ├── projects/          # AppProject 定义
│   └── notifications/     # 通知模板
├── envs/
│   ├── dev/
│   │   ├── myapp/
│   │   │   ├── kustomization.yaml
│   │   │   └── patch.yaml
│   ├── staging/
│   │   ├── myapp/
│   ├── prod/
│   │   ├── myapp/
├── base/                  # Kustomize 基础(所有环境共享)
│   ├── myapp/
│   │   ├── deployment.yaml
│   │   ├── service.yaml
│   │   ├── kustomization.yaml

Argo Rollouts 最佳实践

  1. 金丝雀步骤必须有 analysis 节点,不能只靠人肉观察
  2. AnalysisTemplate 至少检查错误率和 P99 延迟两个指标
  3. failureLimit 设为 2(两次失败就中止),不要设太高
  4. 生产环境 Rollout 先 pause,人工确认后再 promote
  5. revisionHistoryLimit 设为 3,避免保留太多旧 ReplicaSet
  6. 蓝绿发布比金丝雀简单但资源消耗翻倍,流量波动大的场景选金丝雀
  7. Istio/SMI trafficRouting 精确到百分比,Nginx Ingress 只能按权重近似

五、小结

GitOps 的核心转变是:从"人推集群"变成"集群自己拉 Git"。ArgoCD 是这个转变的落地工具------声明式 Application 定义目标,Repo Server 拉取渲染,Controller 对比同步,Notification Controller 通知结果。多环境用 ApplicationSet 模板化,金丝雀发布用 Argo Rollouts + AnalysisTemplate 自动化,认证用 OIDC+RBAC 分权限,通知用 Slack+Email 全覆盖。关键教训:生产的 selfHeal 不要盲目开启,紧急场景下自愈会 Undo 应急操作;AnalysisTemplate 的 Prometheus query 必须提前验证,否则金丝雀会卡死在 analysis 步骤。

思考题

  1. 如果你的公司有 5 个集群(dev/staging/prod-cn/prod-us/prod-eu),怎么设计 ApplicationSet 让每个集群自动生成对应环境的 Application?
  2. ArgoCD 的 selfHeal 和手动 kubectl 修改之间如何平衡?生产环境应该 auto sync 还是 manual sync?
  3. 金丝雀发布的 AnalysisTemplate 除了 Prometheus,还支持 Web hook 和 Job 类型。什么场景下用 Web hook 比 Prometheus 更合适?

延伸阅读

相关推荐
硅基手札16 小时前
【linux内核专栏 08】时间与定时器
linux·运维·服务器
想做小南娘,发现自己是女生喵16 小时前
Linux之Ubuntu入门篇知识总结
linux·运维·服务器
帷幕落秋17 小时前
Redis哨兵模式
运维·数据库
吴声子夜歌18 小时前
Nginx应用与运维——Nginx编译及部署(部署)
java·运维·nginx
帷幕落秋18 小时前
Redis主从复制
运维·数据库
帷幕落秋18 小时前
Mysql主从复制
运维·数据库
暖核18 小时前
MySQL 高级运维核心:备份恢复、主从复制与 MHA 高可用复习总结
运维·数据库·mysql
jackletter18 小时前
linux:systemd之守护进程
linux·运维·服务器·systemd
Ruiery20 小时前
Linux 6.6内核 CPU 深度解析(五):CPU 空闲状态机 cpuidle
linux·运维·服务器
XS03010620 小时前
Nginx 学习指南
运维·nginx