WEBKT

ArgoCD 原生不支持健康度自动回滚?用 argocd-notifications 实现告警触发式回滚

45 0 0 0

在持续部署(CD)流程中,自动化回滚是保障生产环境稳定性的关键一环。虽然 ArgoCD 提供了强大的应用健康度检查,但其原生功能并不支持在检测到应用不健康时自动触发回滚操作。这是一个常见的运维痛点。

然而,我们可以通过 ArgoCD 生态系统中的另一个重要组件——argocd-notifications,来巧妙地实现这一目标。其核心思路是:将健康度检查的失败事件,通过 Webhook 通知到外部系统,再由该系统执行回滚操作。

下面我将详细介绍如何配置和实现这一方案。

核心原理:事件驱动的工作流

整个流程可以概括为:

  1. 健康度检查:ArgoCD 定期检查部署应用的健康状态(例如,Pod 是否就绪,服务端点是否可访问)。
  2. 事件触发:当健康度检查从 Healthy 变为 DegradedMissing 时,ArgoCD 会生成一个事件。
  3. 通知分发argocd-notifications 监听这些事件,并通过配置的 TriggerTemplate 将事件信息包装成通知。
  4. Webhook 发送:配置一个 Trigger,使其在收到特定健康度事件时,向一个外部 Webhook URL 发送 HTTP POST 请求。请求体中可以包含应用名称、健康度状态、时间戳等关键信息。
  5. 外部执行回滚:一个独立的、轻量级的 Webhook 服务(例如,一个用 Python Flask 或 Go 编写的简单服务)接收该请求,然后调用 ArgoCD 的 API(或 argocd CLI)来执行回滚操作。

实现步骤

1. 部署 argocd-notifications

如果你尚未部署,首先需要安装 argocd-notifications。通常它与 ArgoCD 部署在同一命名空间。

# 假设你已经有一个可用的 ArgoCD 实例
kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj-labs/argocd-notifications/master/manifests/install.yaml

2. 配置 Webhook 服务

你需要一个简单的服务来接收通知并执行回滚。这里提供一个 Python Flask 示例:

# webhook_receiver.py
from flask import Flask, request, jsonify
import subprocess
import logging

app = Flask(__name__)
logging.basicConfig(level=logging.INFO)

@app.route('/argocd/rollback', methods=['POST'])
def handle_rollback():
    data = request.json
    app_name = data.get('app_name')
    # 这里可以添加更多验证,比如签名验证
    if not app_name:
        return jsonify({"error": "Missing app_name"}), 400

    logging.info(f"Received rollback request for app: {app_name}")
    
    # 执行回滚命令(确保运行此服务的Pod有权限访问ArgoCD API或CLI)
    # 方式1: 使用 argocd CLI
    # cmd = ["argocd", "app", "rollback", app_name, "--grpc-web"]
    # 方式2: 使用 ArgoCD REST API (更推荐)
    # 这里为了简化,展示CLI方式,生产环境建议使用API并配置认证
    try:
        # 注意:实际部署时,需要配置argocd的认证信息
        # 示例命令,需根据实际环境调整
        result = subprocess.run(
            ["argocd", "app", "rollback", app_name, "-n", "default"],
            capture_output=True,
            text=True,
            timeout=30
        )
        if result.returncode == 0:
            logging.info(f"Rollback successful for {app_name}")
            return jsonify({"status": "success", "message": f"Rollback triggered for {app_name}"}), 200
        else:
            logging.error(f"Rollback failed: {result.stderr}")
            return jsonify({"status": "error", "message": result.stderr}), 500
    except Exception as e:
        logging.error(f"Error executing rollback: {str(e)}")
        return jsonify({"status": "error", "message": str(e)}), 500

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=5000)

将此服务部署为一个 Kubernetes Service,并暴露一个 ClusterIP 端口(例如 http://rollback-service:5000/argocd/rollback)。

3. 配置 argocd-notifications

这是最关键的一步。你需要创建 ConfigMapSecret 来配置 argocd-notifications

a. 创建 Secret (用于存储 Webhook URL)

apiVersion: v1
kind: Secret
metadata:
  name: argocd-notifications-secret
  namespace: argocd
type: Opaque
stringData:
  # 将上面部署的Webhook服务地址填入
  webhook-url: "http://rollback-service.default.svc.cluster.local:5000/argocd/rollback"

b. 创建 ConfigMap (定义触发器和模板)

apiVersion: v1
kind: ConfigMap
metadata:
  name: argocd-notifications-cm
  namespace: argocd
data:
  # 1. 定义模板:将事件数据格式化为JSON,用于发送给Webhook
  template.rollback-webhook: |
    webhook:
      # 使用上面创建的Secret中的URL
      url: $webhook-url
      body: |
        {
          "app_name": "{{.app.metadata.name}}",
          "health_status": "{{.app.status.health.status}}",
          "sync_status": "{{.app.status.sync.status}}",
          "timestamp": "{{.app.status.operationState.startedAt}}",
          "message": "Application health degraded, triggering rollback."
        }

  # 2. 定义触发器:当应用健康度变为Degraded或Missing时触发
  trigger.on-health-degraded: |
    - send:
      - rollback-webhook
    - when: app.status.health.status in ['Degraded', 'Missing']
      oncePer: app.metadata.name

  # 3. (可选) 定义订阅,让通知器知道要监听哪些应用
  # 通常,我们通过 Annotation 订阅特定应用

c. 为需要监控的应用添加订阅 Annotation

在需要实现此功能的 ArgoCD Application 资源上,添加以下 Annotation:

apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: my-critical-app
  namespace: argocd
  annotations:
    # 订阅到 on-health-degraded 触发器
    notifications.argoproj.io/subscribe.on-health-degraded: ""
    # (可选) 指定订阅者,可以是邮箱、Slack等,这里我们只关心Webhook
    # notifications.argoproj.io/subscribe.on-health-degraded: "my-team-email"
spec:
  # ... 应用配置

4. 重启或更新配置

配置更改后,需要重启 argocd-notifications 的 Pod 以使配置生效。

kubectl rollout restart deployment/argocd-notifications-controller -n argocd

最佳实践与注意事项

  1. 安全第一:生产环境务必对 Webhook 进行认证(如使用 Secret Token 验证),防止未授权调用。可以在 argocd-notificationstemplate 中通过 headers 字段传递认证信息。
  2. 幂等性:确保回滚操作是幂等的,即重复执行不会产生负面影响。ArgoCD 的 app rollback 命令是幂等的。
  3. 避免循环:确保回滚操作本身不会再次触发健康度告警。例如,如果回滚到的版本本身就不健康,可能会导致无限循环。建议在 Webhook 服务中增加逻辑,例如设置一个冷却时间或检查最近的回滚历史。
  4. 监控与日志:为你的 Webhook 服务和 argocd-notifications 配置详细的日志,以便追踪每次告警和回滚的执行情况。
  5. 测试:在非生产环境充分测试整个流程。可以通过手动将应用标记为 Degraded(例如,删除一个必需的 Pod)来触发告警,观察 Webhook 是否收到请求并正确执行回滚。
  6. 替代方案:对于更复杂的工作流(如需要人工审批、多步骤回滚),可以考虑将 argocd-notifications 的 Webhook 指向一个更强大的工作流引擎,如 Argo Workflows 或 Tekton,由它们来编排后续的回滚和验证步骤。

通过上述配置,我们就成功地将 ArgoCD 的健康度检查与自动化回滚能力结合起来,构建了一个响应式的、事件驱动的部署后自愈系统。这极大地提升了运维效率和系统稳定性。

DevOps 老王 ArgoCD自动化回滚

评论点评