deadman-switch · worker3 infra 节点的外部存活心跳

deadman-switch 是一个钉在 worker3 上的 CronJob 心跳器:它每分钟从 worker3 向集群外的 Uptime Kuma 推送一次心跳。

worker3 是唯一承担 workload=infra 的节点,同时托管全部数据库(node-role=database)和 infra 组件,是集群的单点。把心跳 Job 通过 nodeSelector: workload=infra 钉死在 worker3 上,当 worker3 宕机或不可达时 Job 无法调度、心跳随之停止,集群外(Oracle 主机上)的 Uptime Kuma 在其宽限窗口后告警。它监控的是 worker3 自身与出网链路的存活,而不是 Prometheus / Alertmanager 这条告警流水线本身——后者跑在同一个可能一起挂掉的集群里,无法自证存活,所以需要这个独立于集群的外部探针来兜底。

部署形态

  • Name
    命名空间
    Description
    deadman-switch(独立 namespace,本仓库 namespace.yaml 创建)
  • Name
    工作负载类型
    Description
    CronJob(batch/v1),schedule * * * * *(每分钟)
  • Name
    镜像
    Description
    curlimages/curl:8.20.0
  • Name
    调度
    Description
    nodeSelector workload: infra —— 钉死在 worker3(集群中唯一带该标签的节点)
  • Name
    并发策略
    Description
    concurrencyPolicy Forbid,startingDeadlineSeconds 30,单 Job activeDeadlineSeconds 40,backoffLimit 0,restartPolicy Never
  • Name
    历史保留
    Description
    successfulJobsHistoryLimit 1 / failedJobsHistoryLimit 3
  • Name
    资源
    Description
    requests 10m CPU / 16Mi mem,limits 100m CPU / 64Mi mem
  • Name
    安全上下文
    Description
    runAsNonRoot(uid 65534)、readOnlyRootFilesystem、allowPrivilegeEscalation false、drop ALL capabilities、seccomp RuntimeDefault、automountServiceAccountToken false

容器的全部逻辑就是一行 curl:

curl -4 -fsS -m 20 "$PUSH_URL" && echo "heartbeat sent"

-4 强制走 IPv4:心跳目标 uptime.yldm.tech(Cloudflare)同时有 AAAA 记录,但 Pod 网络没有可用的 IPv6 出口,不加 -4 时 curl 约一半概率选到 IPv6 地址而连接失败,导致心跳抖动。

配置与依赖

心跳推送地址 PUSH_URL 不写进 git,而是通过 ExternalSecret 从 Vault 拉取,沿用 alertmanager-telegram 的模式。

  • Name
    ExternalSecret
    Description
    deadman-switch-kuma,secretStoreRef 指向 ClusterSecretStore vault-backend,refreshInterval 1h,creationPolicy Owner
  • Name
    Vault 路径
    Description
    monitoring/deadman-switch/kuma(dataFrom.extract),key push_url;写入时对应 vault kv put secret/monitoring/deadman-switch/kuma push_url=...
  • Name
    env 注入
    Description
    PUSH_URL 来自 secretKeyRef deadman-switch-kumapush_url
  • Name
    外部依赖
    Description
    Uptime Kuma(部署在集群外的 Oracle 主机上),经 uptime.yldm.tech(Cloudflare 前置)接收 push 心跳

ArgoCD 侧:Application deadman-switch 归属 project platform,开启 automated: {prune: true, selfHeal: true}CreateNamespace=false(namespace 由仓库内 namespace.yaml 显式创建)。三类资源用 sync-wave 排序:namespace -2 → ExternalSecret / NetworkPolicy -1 → CronJob 0,确保 namespace 和 secret 先于心跳 Job 就绪。

访问与监控

这是一个纯出站心跳器,没有 Service、Ingress、ServiceMonitor、HPA/VPA/PDB——监控由集群外的 Uptime Kuma 反向承担:有心跳即存活,停跳即告警。

namespace 内有一条默认拒绝的 NetworkPolicy(podSelector 选中全部 Pod):

方向规则
Ingress全部拒绝(ingress: []
Egress仅允许到 CoreDNS(k8s-app: kube-dns,UDP/TCP 53)解析域名,以及对 0.0.0.0/0 的 TCP 443 出站 HTTPS

出站 HTTPS 不能锁到单个源 IP:uptime.yldm.tech 现已挪到 Cloudflare 后面,边缘 IP 轮换,旧的 129.150.55.22/32 固定 pin 会因 deadman Pod 生命周期极短、抢在 NetworkPolicy 编程完成之前发起请求而间歇性失败。

注意事项

这个组件本身就是对 worker3 单点风险的兜底手段,理解时要抓住几点。

监控对象是 worker3 节点 + 出网链路的存活,不是 Prometheus / Alertmanager 流水线。infra 单点宕机后的处置顺序、哪些工作负载能漂移、哪些必须恢复,见仓库内的 docs/infra-node-down-runbook.md(H3 段专门讲到该心跳)。

心跳停跳到告警之间有一个宽限窗口,由集群外 Uptime Kuma 一侧配置;CronJob 这侧每分钟一跳、Forbid 并发、单 Job 40 秒超时,意味着探针对调度延迟敏感,worker3 一旦无法调度 Job,心跳会很快归零。

curl 的 -4 与 NetworkPolicy 放开 0.0.0.0/0:443 都是为修过往的间歇性失败而存在的(IPv6 误选、Cloudflare 动态边缘 IP),不要在"加固"时把它们改回固定 IP pin 或去掉 -4,否则心跳会重新抖动而误报。

返回 infrastructure 总览

评论