Skip to content

uat1 集群 Rancher Monitoring 部署与故障排查手册

  • 日期:2026-08-01
  • 目标集群uat1(RKE2 v1.35.6+rke2r1,Rancher v2.14.3 管理的下游集群,集群 ID c-m-5dx2sdbr
  • 节点:sza122023/24/29/30/31(192.168.122.23/24/29/30/31,Rocky 9.8,amd64)
  • 组件:rancher-monitoring 109.0.4+up80.9.1-rancher.18 + nfs-subdir-external-provisioner 4.0.18(app v4.0.2)
  • 镜像/Chart 仓库:内网 Harbor 192.168.122.156:30000(镜像项目 ranchersig-storage;chart OCI 项目 charts
  • NFS192.168.122.1:/mnt/xfs/rancher/uat1

1. 背景与目标

在 uat1 集群部署 Rancher Monitoring 全栈(Prometheus / Alertmanager / Grafana / node-exporter / kube-state-metrics / adapter),要求:

  1. 镜像与 Helm chart 全部走内网 Harbor(离线可用);
  2. 监控数据持久化到 NFS;
  3. 通过 Rancher UI 正常访问 Grafana。

过程中解决了 3 个独立故障:集群 DNS 瘫痪、helm-operation 卡死、Grafana 代理访问 404。以下按处理顺序记录。

2. 故障一:集群 DNS 瘫痪(根因,隐蔽 40 小时)

2.1 现象

在 Rancher UI 点击安装 Monitoring 后,cattle-monitoring-system 命名空间一直为空,cattle-system 中大量 helm-operation-* Pod 报错:

Waiting for Kubernetes API to be available
Timeout waiting for kubernetes

2.2 排查链

检查结果
Pod → API Server 直连(wget https://10.23.0.1:443✅ 通(401 为正常响应)
nslookup kubernetes.default.svc.cluster.local❌ NXDOMAIN,两个 CoreDNS Pod 均如此
CoreDNS SA 权限(用其 token 调 API)✅ 可正常 list endpoints,RBAC 无问题
Corefile发现自定义 local 域配置

2.3 根因

集群的 HelmChartConfig/rke2-coredns 中自定义了 extraConfig,其中有一条防 mDNS 泄漏的规则:

local {
    template IN ANY local {
        rcode NXDOMAIN
    }
}

CoreDNS 域名路由按最长后缀匹配cluster.local 也是 local 的子域,于是所有集群内部 Service 域名查询都被这条模板拦截返回 NXDOMAIN。该配置在集群创建初期(约 40 小时前)就已生效,但下游 agent 通信全部走 IP 直连,故障一直隐蔽,直到安装 Monitoring 需要解析 kubernetes.default 才爆发。

2.4 修复

HelmChartConfig/rke2-coredns 的 extraConfig 中显式补充 cluster.local(更长后缀优先匹配,恢复 kubernetes 插件应答),保留原有自定义域:

yaml
apiVersion: helm.cattle.io/v1
kind: HelmChartConfig
metadata:
  name: rke2-coredns
  namespace: kube-system
spec:
  failurePolicy: reinstall
  valuesContent: |-
    extraConfig:
      ai-ear.cn:            # 原有:内网域名指向 Rancher 节点
        parameters: |
          {
              template IN A ai-ear.cn {
                  answer "{{ .Name }} 60 IN A 192.168.122.20"
                  answer "{{ .Name }} 60 IN A 192.168.122.21"
                  answer "{{ .Name }} 60 IN A 192.168.122.22"
                  fallthrough
              }
              template IN AAAA ai-ear.cn {
                  rcode NOERROR
              }
              }
      cluster.local:        # 新增:显式接管集群域,避免落入 local 域
        parameters: |
          {
              kubernetes cluster.local {
                  pods insecure
                  ttl 30
              }
              forward . /etc/resolv.conf
              cache 30
              loadbalance
              }
      local:                # 原有:屏蔽 .local mDNS 泄漏
        parameters: |
          {
              template IN ANY local {
                  rcode NXDOMAIN
              }
              }

修改后 CoreDNS reload 插件约 30 秒自动加载,无需重启。验证:

bash
nslookup kubernetes.default.svc.cluster.local   # ✅ 10.23.0.1
nslookup sza122031.local                        # ✅ NXDOMAIN(符合 local 域预期)
nslookup ai-ear.cn                              # ✅ 192.168.122.20~22

DNS 恢复后,Rancher 积压的 rancher-webhook、system-upgrade-controller 升级自动完成。教训:CoreDNS 自定义短后缀域(如 localinternal)时,必须检查是否会吞掉 cluster.local 等关键域。

3. helm CLI 部署 Monitoring

Rancher UI 的安装记录已失效(管理面 apps.catalog.cattle.io 无记录),改为 helm CLI 手动部署。Rancher 通过命名空间和 release 名识别,与 UI 安装效果一致。

bash
# kubeconfig 取自任一 control-plane 节点 /etc/rancher/rke2/rke2.yaml,
# server 地址 127.0.0.1:6443 改为节点 IP

# ① CRD chart(prometheus-operator 的全部 CRD)
helm upgrade --install rancher-monitoring-crd \
  rancher-monitoring-crd-109.0.4+up80.9.1-rancher.18.tgz \
  --namespace cattle-monitoring-system --wait

# ② 主 chart,systemDefaultRegistry 指向内网 Harbor
helm upgrade --install rancher-monitoring \
  rancher-monitoring-109.0.4+up80.9.1-rancher.18.tgz \
  --namespace cattle-monitoring-system \
  --set global.cattle.systemDefaultRegistry=192.168.122.156:30000 \
  --wait --timeout 10m

注:节点 containerd 已配置通配镜像仓库(registries.yamlmirrors."*" 指向 Harbor),且 Harbor rancher 项目为 public,镜像拉取无需认证。

部署结果:10 个 Pod 全部 Running,镜像全部来自内网 Harbor,Prometheus targets 27/27 up。

4. 部署 NFS 动态供给(nfs-subdir-external-provisioner)

4.1 NFS 服务端(192.168.122.1,libvirt 宿主机)

bash
echo '/mnt/xfs/rancher/uat1 *(rw,sync,no_subtree_check,no_root_squash)' >> /etc/exports
exportfs -ra
# 任一集群节点验证
mount -t nfs 192.168.122.1:/mnt/xfs/rancher/uat1 /tmp/nfs-test && touch /tmp/nfs-test/.t && rm /tmp/nfs-test/.t && umount /tmp/nfs-test

4.2 镜像与 chart 同步到内网 Harbor

bash
# Harbor 建项目(API)
curl -X POST -u '<用户名>:<密码>' -H 'Content-Type: application/json' \
  -d '{"project_name":"sig-storage","public":true}' http://192.168.122.156:30000/api/v2.0/projects
curl -X POST -u '<用户名>:<密码>' -H 'Content-Type: application/json' \
  -d '{"project_name":"charts","public":true}' http://192.168.122.156:30000/api/v2.0/projects

# 镜像:registry.k8s.io 经华为云 SWR 国内源同步
skopeo copy --all --dest-tls-verify=false \
  docker://swr.cn-north-4.myhuaweicloud.com/ddn-k8s/registry.k8s.io/sig-storage/nfs-subdir-external-provisioner:v4.0.2 \
  docker://192.168.122.156:30000/sig-storage/nfs-subdir-external-provisioner:v4.0.2

# chart:github releases 经 gh-proxy 加速下载,再以 OCI 方式推送 Harbor
curl -sL -o nfs-subdir-external-provisioner-4.0.18.tgz \
  https://gh-proxy.com/https://github.com/kubernetes-sigs/nfs-subdir-external-provisioner/releases/download/nfs-subdir-external-provisioner-4.0.18/nfs-subdir-external-provisioner-4.0.18.tgz
helm registry login 192.168.122.156:30000 -u '<用户名>' -p '<密码>' --insecure
helm push nfs-subdir-external-provisioner-4.0.18.tgz oci://192.168.122.156:30000/charts --plain-http

4.3 从内网仓库部署

bash
helm upgrade --install nfs-subdir-external-provisioner \
  oci://192.168.122.156:30000/charts/nfs-subdir-external-provisioner \
  --version 4.0.18 --plain-http \
  --namespace nfs-provisioner --create-namespace \
  --set nfs.server=192.168.122.1 \
  --set nfs.path=/mnt/xfs/rancher/uat1 \
  --set image.repository=192.168.122.156:30000/sig-storage/nfs-subdir-external-provisioner \
  --set image.tag=v4.0.2 \
  --set storageClass.name=nfs \
  --set storageClass.defaultClass=true \
  --wait

验证:StorageClass nfs (default) 就绪;测试 PVC 秒级 Bound,NFS 服务端动态生成子目录;删 PVC 后自动归档为 archived-*

5. Monitoring 开启持久化

新建 monitoring-persistence-values.yaml

yaml
prometheus:
  prometheusSpec:
    storageSpec:
      volumeClaimTemplate:
        spec:
          storageClassName: nfs
          accessModes: ["ReadWriteOnce"]
          resources:
            requests:
              storage: 20Gi
alertmanager:
  alertmanagerSpec:
    storage:
      volumeClaimTemplate:
        spec:
          storageClassName: nfs
          accessModes: ["ReadWriteOnce"]
          resources:
            requests:
              storage: 5Gi
grafana:
  persistence:
    enabled: true
    type: pvc
    storageClassName: nfs
    size: 5Gi
    accessModes: ["ReadWriteOnce"]
bash
helm upgrade rancher-monitoring rancher-monitoring-109.0.4+up80.9.1-rancher.18.tgz \
  -n cattle-monitoring-system --reuse-values -f monitoring-persistence-values.yaml \
  --wait --timeout 10m

验证:3 个 PVC Bound,TSDB 数据持续写入 NFS(du -sh 可见增长),targets 31/31 up。

注意:NFS 承载 Prometheus TSDB 属于"可用但非最佳实践",大规模场景建议 local-path/Longhorn。Pod 重建期间 nginx 缓存的 502 约 5 分钟自愈,无需干预。

6. 故障三:Rancher UI 访问 Grafana 失败

6.1 现象

Rancher UI → Monitoring → Grafana,报错:

lost connection to cluster: failed to find Session for client stv-cluster-api

6.2 原因一:瞬时隧道中断(可自愈)

该错误是 Rancher remotedialer 隧道在 cluster-agent 重启窗口的瞬时表现(Rancher 3 副本同时记录 tunnel disconnect,agent 数秒后自动重连)。确认方法:

bash
# 管理面查看集群状态
kubectl get clusters.management.cattle.io c-m-5dx2sdbr   # Connected / Ready
# 各 rancher 副本近期无 "failed to find Session" 日志

6.3 原因二:chart 缺少集群 ID(必须修复)

helm CLI 手动安装时 global.cattle.clusterId 为空(UI 安装会自动注入),导致 Grafana nginx 代理的 appSubUrl 变为 /k8s/clusters//api/...(空集群 ID),前端资源 URL 全部错乱。修复:

bash
helm upgrade rancher-monitoring ... --reuse-values \
  --set global.cattle.clusterId=c-m-5dx2sdbr \
  --set global.cattle.clusterName=uat1
# configmap 变更不会自动滚动,需手动重启
kubectl rollout restart deployment -n cattle-monitoring-system rancher-monitoring-grafana

6.4 验证代理链路

流量真实路径:浏览器 → Rancher → 下游 apiserver → service → nginx(:8080)。apiserver 会剥离 /api/v1/.../proxy 前缀,nginx 收到的是 /login 这类短路径;appSubUrl 只用于前端生成回链 URL。按真实路径验证:

bash
curl -s -o /dev/null -w "%{http_code}" http://<grafana-svc>/login        # 200
curl -s http://<grafana-svc>/login | grep -o 'appSubUrl[^,]*'           # 含 c-m-5dx2sdbr
curl -s http://<grafana-svc>/api/health                                 # {"database": "ok"}

7. 最终验证清单

项目结果
helm releaserancher-monitoring + rancher-monitoring-crd deployed(109.0.4)
Pod10/10 Running
镜像全部来自 192.168.122.156:30000
Prometheus targets31/31 up
PVCprometheus 20Gi / alertmanager 5Gi / grafana 5Gi 全部 Bound
NFS 数据TSDB 持续写入 /mnt/xfs/rancher/uat1/cattle-monitoring-system-*
GrafanaRancher UI 代理访问正常,{"database": "ok"}
DNScluster.local / ai-ear.cn / .local 三类解析均符合预期

8. 经验总结

  1. CoreDNS 自定义域先做后缀冲突检查:localinternalcorp 这类短后缀域极易吞掉 cluster.local,且故障可长期隐蔽(agent 类组件走 IP 直连不受影响)。
  2. 排查 DNS 不要停在"Pod→API 通不通":应用层的 kubernetes.default 解析才是大多数组件的真实依赖。
  3. helm CLI 安装 rancher-monitoring 必须补三个值:systemDefaultRegistry(离线镜像)、clusterIdclusterName(否则 Grafana 代理和指标集群标签都会残缺)。
  4. Harbor OCI 托管 chart + 通配镜像仓库:内网集群可实现"chart 与镜像全内网"的离线部署模式,可复用到任意上游 chart。