将 Falco 告警通过 Webhook 接入企业微信的完整配置

解读

面试官想验证三件事:

  1. 你是否真的在生产环境跑过 Falco(能说出内核驱动、eBPF、Rules 文件位置、输出通道)。
  2. 你是否熟悉 中国企业微信机器人 的调用限制(JSON 格式、@all 开关、Markdown 支持度、单条 4 KB、频率 20 条/分钟)。
  3. 你是否能把“容器安全事件”无缝嵌入 DevOps 闭环:镜像 → Helm → 日志 → 告警 → 值班群 → 自动创建 Jira。
    答得太浅(只改两行 yaml)会被追问“高并发丢告警怎么办”;答得太深(自己写 gRPC 网关)会被嫌过度设计。最佳策略是给出“最小可运行方案 + 生产级加固清单”,让面试官既能听懂,又能感受到你踩过坑。

知识点

  • Falco 输出通道:file/syslog/http/program,生产推荐 http_output=true
  • Falco 内置模板字段:rule、priority、time、output_fields、tags
  • 企业微信 Webhook 只接受 POST,Content-Type: application/json,必须带 msgtype 和对应内容字段
  • 国内云主机到 wxapi 的 443 出口需备案域名,否则会被运营商丢包
  • 容器化场景下,Falco 用户空间程序跑在 DaemonSet,内核驱动挂载 /dev/falco0,升级内核后需重建驱动
  • 高并发时,用 Falcosidecar + Kafka 做削峰,再吐给企业微信,避免 20 条/分钟限流
  • 敏感信息(容器名、镜像 tag)需脱敏,否则会把内部仓库地址暴露在微信群

答案

以下方案基于 Kubernetes 1.28 + Falco 0.36 + 企业微信机器人,全部镜像使用国内加速器,可直接落地

  1. 创建企业微信机器人
    在企业微信群里右键“添加机器人”,复制 key=xxxxxxxx 备用。

  2. 准备 Falco 规则(可选,演示用)
    新建 /etc/falco/rules.d/whitelist.yaml

    - rule: 可疑的 kubectl exec
      desc: 非运维时间执行 kubectl exec
      condition: >
        spawned_process and proc.name = "kubectl" and proc.args contains "exec"
        and not user.name in ("ops1", "ops2")
      output: >
        异常kubectl exec: user=%user.name pod=%k8s.pod.name container=%container.name cmd=%proc.cmdline
      priority: WARNING
      tags: [k8s, exec]
    
  3. 构建“翻译器”镜像(Python 3.11-alpine,仅 55 MB)
    Dockerfile

    FROM python:3.11-alpine
    WORKDIR /app
    RUN pip install -U pip && pip install flask gunicorn requests
    COPY webhook2wx.py .
    CMD ["gunicorn", "-b", "0.0.0.0:8080", "webhook2wx:app"]
    

    webhook2wx.py 核心逻辑

    import os, flask, requests, json, time
    app = flask.Flask(__name__)
    WX_KEY = os.getenv("WX_KEY")
    @app.route("/", methods=["POST"])
    def index():
        falco = flask.request.json
        txt = (f"**{falco['priority']}**  {falco['rule']}\n"
               f">时间: {falco['time']}\n"
               f">Pod: {falco['output_fields'].get('k8s.pod.name', 'N/A')}\n"
               f">容器: {falco['output_fields'].get('container.name', 'N/A')}\n"
               f">详情: {falco['output']}")
        body = {"msgtype": "markdown", "markdown": {"content": txt}}
        r = requests.post(f"https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key={WX_KEY}",
                          json=body, timeout=5)
        if r.status_code != 200 or r.json()['errcode'] != 0:
            app.logger.error("wx send fail: %s", r.text)
            return "fail", 500
        return "ok", 200
    
  4. 部署翻译器为 ClusterIP Service

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: falco-webhook2wx
      namespace: kube-system
    spec:
      replicas: 2
      selector:
        matchLabels: {app: falco-webhook2wx}
      template:
        metadata:
          labels: {app: falco-webhook2wx}
        spec:
          containers:
          - name: wx
            image: registry.cn-hangzhou.aliyuncs.com/yourrepo/webhook2wx:1.0.0
            imagePullPolicy: IfNotPresent
            env:
            - name: WX_KEY
              value: "xxxxxxxx"
            ports:
            - containerPort: 8080
              name: http
            resources:
              limits: {cpu: "200m", memory: "128Mi"}
              requests: {cpu: "50m", memory: "64Mi"}
    ---
    apiVersion: v1
    kind: Service
    metadata:
      name: falco-webhook2wx
      namespace: kube-system
    spec:
      selector: {app: falco-webhook2wx}
      ports:
      - port: 80
        targetPort: 8080
    
  5. 修改 Falco 配置打开 http_output
    在 /etc/falco/falco.yaml 末尾追加

    http_output:
      enabled: true
      url: "http://falco-webhook2wx.kube-system.svc.cluster.local"
      user_agent: "falco/webhook"
    

    若需 TLS,可改为 https 并在翻译器侧挂证书,或走 Ingress + 自签证书。

  6. 重启 Falco DaemonSet

    kubectl rollout restart ds/falco -n kube-system
    
  7. 验证
    手动触发规则

    kubectl exec -it nginx-xxx -- ls
    

    企业微信立刻收到 Markdown 卡片,优先级、Pod 名、容器名、完整命令行 一目了然。

  8. 生产级加固(面试加分项,逐条说清)

    • 限流:翻译器里加令牌桶,单 Pod 10 条/秒,超量写日志丢告警,避免微信 20 条/分钟限流触发 errcode 45009。
    • 重试:对 5xx 使用指数退避,最多 3 次,防止微信群刷屏。
    • 多集群:每个集群独立机器人 key,告警路由按集群前缀加 emoji,如【PROD】【TEST】。
    • 敏感脱敏:镜像仓库域名统一替换为 <registry>防止外泄内部地址
    • 高可用:翻译器 Deployment 配 HPA,CPU>60% 扩容到 5 副本;Falco 本身用 DaemonSet + 亲和性打散
    • 可观测:翻译器暴露 /metrics,Prometheus 采集 webhook_send_total、wx_fail_total,Grafana 大盘联动值班。
    • 灰度:利用 Falco 的 tags 字段,先只把 priority>=ERROR 的告警发到微信群,其余走邮件,降低噪音。
    • 备份通道:关键集群再并接一条 钉钉机器人双通道互备,微信挂掉自动切钉钉。

拓展思考

  1. 如果企业微信机器人到达上限,如何零改动切换到企业微信“应用”
    答:只需把翻译器里的 URL 换成 https://qyapi.weixin.qq.com/cgi-bin/message/send?access_token=XXXbody 改为 touser/@all 的 textcard 格式,其余字段不变;access_token 通过 corpid+secret 换取,用 CronJob 每 1 小时刷新一次 Secret

  2. 面对每天 50 万条事件,如何做到不丢、不重、不延迟
    答:

    • Falco → Kafka(三副本)→ Falcosidecar 消费 → Redis 去重(rule+pod+md5)企业微信批量接口(最多 100 条/次)
    • 采用 OTEL TraceID 串联,Prometheus + Alertmanager 监控 lag,超过 5 分钟直接电话告警值班。
  3. 安全团队要求 闭环处置:收到 Falco 告警后 30 分钟内必须有人认领,否则升级。
    答:

    • 翻译器在 Markdown 卡片里带 “一键认领” 按钮,回调 URL 指向内部 Ops 平台
    • Ops 平台收到回调后,调用 Jira API 自动创建 SECURITY 类型工单,并把 issue key 回写到企业微信卡片,实现 ChatOps 闭环

把以上三步讲清楚,面试官会默认你既懂容器安全,又懂国内 IM 生态,还具备高可用和自动化闭环思维,基本锁定 offer。