【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 更合适?

延伸阅读

相关推荐
Nuanyt1 小时前
Linux系统的 Shell 常见指令和常见知识点(以bash为主)
linux·运维·chrome·bash
星恒随风1 小时前
Linux 权限详解:从 rwx、chmod 到 umask、目录权限与粘滞位
linux·运维·服务器·笔记·学习
拳里剑气1 小时前
Linux:进程间通信
linux·运维·数据库·进程
运维大师1 小时前
【K8S 运维实战】31-Helm包管理
运维·算法·kubernetes
阳光九叶草LXGZXJ2 小时前
达梦数据库-报错-12-[-7184]:对象定义[XXX]被修改,版本检查失败
linux·运维·服务器·数据库·sql·学习
AI大佬的小弟2 小时前
私有化 Dify 应用开发(3):Docker 核心原理与零基础实战
运维·docker·容器技术·ai 应用开发·私有化 ai 部署·docker 教程·dify 运维
沉迷学习 日益消瘦2 小时前
20-综合实战:微服务部署
微服务·云原生·架构·kubernetes
JXCY13S5052 小时前
集群及lvs基础知识
运维·服务器
小此方2 小时前
Re:Linux系统篇(四十九)线程篇 · 二:为什么现代操作系统选择分页式存储?分页如何解决物理内存碎片?分页结构如何演化到页表、页目录、MMU?
linux·运维·驱动开发