igozhang

——

    K8s集群DNS被Mihomo劫持导致 Zabbix Web 无法 Ready

    ENV

    类别 信息
    操作系统 Ubuntu 20.04 LTS
    节点 单节点 K8s,igo-k8s-node01(1/1 Ready)
    容器运行时 containerd
    CNI Calico(Pod 网段 192.168.0.0/16
    Service CIDR 10.96.0.0/12
    存储 local-path(StorageClass)
    应用 Zabbix Helm 4.4.1 / PostgreSQL 15 / Zabbix Web 6.0
    命名空间 igo-zabbix
    代理 Mihomo(Clash Meta,自 Clash Verge deb 提取)
    上游代理 HTTP Squid 10.80.238.40:3128
    DNS 模式 TUN + fake-ip(198.18.0.0/16

    现象

    部署 Zabbix 后 Pod 状态异常:

    zabbix-postgresql-0                   1/1  Running   (初期曾 Pending,PVC 绑定后恢复)
    zabbix-zabbix-server-xxx              2/2  Running
    zabbix-zabbix-web-xxx                 0/1  Running   (多次 Restart)
    zabbix-zabbix-webservice-xxx          1/1  Running
    
    • Web 探针报 connection refused(8080)
    • Web 日志循环:PostgreSQL server is not available. Waiting 5 seconds...
    • PostgreSQL Service / Endpoint 正常:10.102.122.177:5432 → Pod 192.168.x.x:5432

    结论与根因

    结论: 问题不在 PostgreSQL 本身,而是 Mihomo TUN 的 dns-hijack: any:53 劫持了 Pod 到 CoreDNS 的 DNS 流量,集群内部域名被解析为 fake-ip(198.18.x.x),导致 Web 连库失败。

    根因: dns-hijack: any:53 拦截所有 53 端口查询(含 Pod → 10.96.0.10 CoreDNS),*.svc.cluster.local 返回假 IP;TCP 5432 连假 IP 失败 → nginx 未启动 → Readiness 探针失败。


    定位推导

    1. Web 连不上数据库

    kubectl logs zabbix-zabbix-web-xxx -n igo-zabbix --tail=60
    

    关键输出:

    **** PostgreSQL server is not available. Waiting 5 seconds...
    

    Service / Endpoint 正常,排除 PG 未启动:

    kubectl get svc,endpoints -n igo-zabbix -o wide | grep postgresql
    
    service/zabbix-postgresql    ClusterIP  10.102.122.177  ...  5432/TCP
    endpoints/zabbix-postgresql  192.168.x.x:5432
    

    2. DNS 返回 fake-ip

    Pod 内解析(修复前):

    kubectl exec -n igo-zabbix zabbix-postgresql-0 -- getent hosts zabbix-postgresql
    
    198.18.0.30     zabbix-postgresql.zabbix.svc.cluster.local   # 修复前
    10.102.122.177  zabbix-postgresql.zabbix.svc.cluster.local   # 修复后
    

    节点 resolv.conf 含代理 DNS 198.18.0.2;CoreDNS Pod 直连查询亦返回 fake-ip:

    dig @192.168.x.x zabbix-postgresql.igo-zabbix.svc.cluster.local +short
    # 198.18.0.30
    

    3. 形成原因推测

    Mihomo 按 TUN 全局分流方案 部署,dns-hijack: any:53 在网卡层劫持全部 DNS。K8s Pod 使用 nameserver 10.96.0.10,该流量同样被劫持;fake-ip-filter / nameserver-policy 无法可靠绕过。rules10.0.0.0/8 DIRECT 仅影响流量路由,不影响 DNS 解析阶段 的 fake-ip 分配。


    方案

    核心配置变更(/etc/mihomo/config.yaml

    tun:
      auto-route: true
      auto-detect-interface: true
      # 【改】排除 K8s 网段,集群内流量不走 TUN
      route-exclude-address:
        - 10.96.0.0/12      # Service CIDR
        - 192.168.0.0/16    # Pod CIDR(Calico)
      # 【改】仅劫持本机 systemd-resolved,不劫持 Pod → CoreDNS
      dns-hijack:
        - 127.0.0.53:53     # 原值: any:53
    
    参数 当前值(问题配置) 建议值 原因 预期效果
    dns-hijack any:53 127.0.0.53:53 避免劫持 Pod→CoreDNS Pod 内解析得真实 ClusterIP
    route-exclude-address Service + Pod CIDR 集群内流量绕过 TUN 降低劫持与延迟
    fake-ip-filter(曾尝试) 无 / 不完整 不必依赖 无法根本解决 hijack

    已移除无效的 fake-ip-filternameserver-policy 补丁,保持配置简洁。

    部署步骤

    备份:

    sudo cp /etc/mihomo/config.yaml /etc/mihomo/config.yaml.bak.$(date +%Y%m%d%H%M%S)
    

    写入配置后校验并重启:

    sudo /usr/local/bin/mihomo -t -d /etc/mihomo && sudo systemctl restart mihomo
    

    ⚠️ 重启 mihomo 时 TUN 分流短暂中断 1~2 秒。

    重启 Web:

    kubectl rollout restart deployment zabbix-zabbix-web -n igo-zabbix
    

    验证

    Pod 内 DNS(核心验证):

    sleep 3
    kubectl exec -n igo-zabbix zabbix-postgresql-0 -- getent hosts zabbix-postgresql
    

    预期:10.102.122.177 zabbix-postgresql...

    全组件状态:

    kubectl get pods -n igo-zabbix
    

    预期:全部 1/12/2 Running,web 无 Restart。

    Web 日志:

    kubectl logs -n igo-zabbix -l app.kubernetes.io/name=zabbix-web --tail=20
    

    预期:无 PostgreSQL server is not available


    后续预防

    1. K8s 节点禁止 dns-hijack: any:53,改用 127.0.0.53:53 仅劫持宿主机 DNS。
    2. 必须配置 route-exclude-address,覆盖 Service CIDR 与 Pod CIDR;CIDR 变更后同步更新。
    3. 部署 Zabbix 前做 DNS 冒烟测试:
    kubectl exec -n igo-zabbix <任意 Running Pod> -- getent hosts zabbix-postgresql
    

    若出现 198.18.x.x 或无输出,先修 mihomo 再部署应用。

    1. Service CIDR 非默认时,先确认再写入 exclude:
    kubectl cluster-info dump 2>/dev/null | grep -m1 service-cluster-ip-range
    
    1. 文档参考:Ubuntu 20.04 Mihomo TUN 分流部署 — 适用于无 K8s 的纯服务器;K8s 节点需额外增加本文 exclude 与 dns-hijack 收窄

    附:初期 PostgreSQL Pending(已自愈)

    阶段 现象 原因
    初期 zabbix-postgresql-0 Pending,PVC Pending local-path WaitForFirstConsumer,Pod 与 PVC 互相等待
    中期 删除 PVC 后重建 短暂 FailedScheduling: pvc is being deleted
    后期 PG 1/1 Running PVC 绑定完成,Pod 调度成功

    PG Pending 与 Web 问题独立;Web 根因始终是 DNS fake-ip。


    附录:覆盖完整配置

    备份现有配置:

    sudo cp /etc/mihomo/config.yaml /etc/mihomo/config.yaml.bak.$(date +%Y%m%d%H%M%S)
    

    覆盖写入完整配置(K8s 节点适用版):

    ⚠️ 会覆盖 /etc/mihomo/config.yaml;写入后需重启 mihomo,TUN 分流短暂中断 1~2 秒。

    sudo tee /etc/mihomo/config.yaml > /dev/null <<'EOF'
    mixed-port: 7890
    allow-lan: false
    bind-address: '*'
    mode: rule
    log-level: info
    ipv6: false
    external-controller: 127.0.0.1:9090
    
    tun:
      enable: true
      stack: system
      auto-route: true
      auto-detect-interface: true
      route-exclude-address:
        - 10.96.0.0/12
        - 192.168.0.0/16
      dns-hijack:
        - 127.0.0.53:53
    
    dns:
      enable: true
      ipv6: false
      enhanced-mode: fake-ip
      fake-ip-range: 198.18.0.1/16
      respect-rules: true
      default-nameserver:
        - 223.5.5.5
        - 119.29.29.29
      nameserver:
        - 223.5.5.5
        - 119.29.29.29
      proxy-server-nameserver:
        - 223.5.5.5
        - 119.29.29.29
      fallback:
        - 8.8.8.8
        - 1.1.1.1
      fallback-filter:
        geoip: true
        geoip-code: CN
    
    proxies:
      - name: igoproxy
        type: http
        server: 10.80.238.40
        port: 3128
    
    proxy-groups:
      - name: PROXY
        type: select
        proxies:
          - igoproxy
          - DIRECT
    
    rules:
      - IP-CIDR,127.0.0.0/8,DIRECT,no-resolve
      - IP-CIDR,10.0.0.0/8,DIRECT,no-resolve
      - IP-CIDR,172.16.0.0/12,DIRECT,no-resolve
      - IP-CIDR,192.168.0.0/16,DIRECT,no-resolve
      - IP-CIDR,::1/128,DIRECT,no-resolve
      - AND,((NETWORK,UDP),(DST-PORT,443)),REJECT
      - DOMAIN-SUFFIX,cursor.com,DIRECT
      - DOMAIN-SUFFIX,igozhang.cn,DIRECT
      - DOMAIN-SUFFIX,igozhang.cc,DIRECT
      - GEOIP,CN,DIRECT,no-resolve
      - MATCH,PROXY
    EOF
    

    校验并重启:

    sudo /usr/local/bin/mihomo -t -d /etc/mihomo && sudo systemctl restart mihomo
    

    MP3