在 K8s 1.36 集群上部署 kube-prometheus:离线环境全流程实战指南

摘要: 本文记录了在 Kubernetes 1.36(代号 Haru)集群上,基于 kube-prometheus main 分支,从零搭建一套完整监控体系的全过程。涵盖版本兼容性检查、内网镜像替换、Grafana 调优、NetworkPolicy 处理以及 Nginx 反向代理配置等实战细节,适合内网/离线环境参考

一、为什么选择 kube-prometheus?

kube-prometheus 是 Prometheus Operator 官方提供的一站式监控方案,一套 YAML 文件即可部署以下全套组件:

组件

作用

Prometheus

时序数据采集与存储

Alertmanager

告警管理与路由

Grafana

监控数据可视化

node-exporter

节点级指标采集

kube-state-metrics

K8s 对象状态指标

blackbox-exporter

黑盒探测(HTTP/TCP/ICMP)

prometheus-adapter

自定义指标 API(支持 HPA)

相比 Helm Chart 方式,kube-prometheus 直接提供静态 YAML 清单,更适合内网离线环境——不需要 Helm,不需要联网拉 Chart,改好镜像地址直接 kubectl apply。

二、版本兼容性检查

这是部署前最关键的一步。kube-prometheus 的 main 分支跟随最新 K8s 版本,我们需要确认版本对应关系。

2.1 环境信息

项目

版本

Kubernetes

v1.36

(2026年4月22日发布,代号 Haru)

kube-prometheus

main 分支

Prometheus Operator

v0.91.0

Prometheus

v3.12.0

Grafana

13.0.1

Alertmanager

v0.32.1

/

2.2 下载代码

访问 GitHub克隆代码即可:

git clone https://g.1ab.asia/https://github.com/prometheus-operator/kube-prometheus.git

三、镜像替换:从公网到内网仓库

3.1 检索所有用到的镜像

进入 manifests 目录,一条命令找出所有镜像引用:

cd kube-prometheus/manifests
grep "image:" ./*

输出结果如下:

./alertmanager-alertmanager.yaml:       image: quay.io/prometheus/alertmanager:v0.32.1
./blackboxExporter-deployment.yaml:     image: quay.io/prometheus/blackbox-exporter:v0.28.0
./blackboxExporter-deployment.yaml:     image: ghcr.io/jimmidyson/configmap-reload:v0.15.0
./blackboxExporter-deployment.yaml:     image: quay.io/brancz/kube-rbac-proxy:v0.22.0
./grafana-deployment.yaml:              image: grafana/grafana:13.0.1
./kubeStateMetrics-deployment.yaml:     image: registry.k8s.io/kube-state-metrics/kube-state-metrics:v2.19.0
./kubeStateMetrics-deployment.yaml:     image: quay.io/brancz/kube-rbac-proxy:v0.22.0
./nodeExporter-daemonset.yaml:          image: quay.io/prometheus/node-exporter:v1.11.1
./nodeExporter-daemonset.yaml:          image: quay.io/brancz/kube-rbac-proxy:v0.22.0
./prometheusAdapter-deployment.yaml:    image: registry.k8s.io/prometheus-adapter/prometheus-adapter:v0.12.0
./prometheusOperator-deployment.yaml:   image: quay.io/prometheus-operator/prometheus-operator:v0.91.0
./prometheusOperator-deployment.yaml:   image: quay.io/brancz/kube-rbac-proxy:v0.22.0
./prometheus-prometheus.yaml:           image: quay.io/prometheus/prometheus:v3.12.0

共计 10 个不同的镜像(kube-rbac-proxy 被多个组件复用)。

3.3 批量操作脚本

在一台能同时访问公网和内网仓库的机器上执行:

#!/bin/bash
REGISTRY="register.abc.cn"

images=(
  "quay.io/prometheus/alertmanager:v0.32.1"
  "quay.io/prometheus/blackbox-exporter:v0.28.0"
  "ghcr.io/jimmidyson/configmap-reload:v0.15.0"
  "quay.io/brancz/kube-rbac-proxy:v0.22.0"
  "grafana/grafana:13.0.1"
  "registry.k8s.io/kube-state-metrics/kube-state-metrics:v2.19.0"
  "quay.io/prometheus/node-exporter:v1.11.1"
  "registry.k8s.io/prometheus-adapter/prometheus-adapter:v0.12.0"
  "quay.io/prometheus-operator/prometheus-operator:v0.91.0"
  "quay.io/prometheus/prometheus:v3.12.0"
)

for img in "${images[@]}"; do
  echo ">>> Pulling $img"
  docker pull "$img"
  echo ">>> Tagging $img -> $REGISTRY/$img"
  docker tag "$img" "$REGISTRY/$img"
  echo ">>> Pushing $REGISTRY/$img"
  docker push "$REGISTRY/$img"
  echo ">>> Done: $img"
  echo "---"
done

3.4 修改 YAML 文件中的镜像地址

使用 sed 批量替换:

cd manifests/

# 替换所有镜像地址为内网仓库
sed -i 's|quay.io/|register.abc.cn/quay.io/|g' *.yaml
sed -i 's|ghcr.io/|register.abc.cn/ghcr.io/|g' *.yaml
sed -i 's|grafana/grafana|register.abc.cn/grafana/grafana|g' *.yaml
sed -i 's|registry.k8s.io/|register.abc.cn/registry.k8s.io/|g' *.yaml

替换后再次验证:

grep "image:" ./*

确认所有镜像都已指向 register.abc.cn 前缀即可。

四、Grafana 服务暴露:改为 NodePort

默认 Grafana Service 是 ClusterIP 类型,只能在集群内访问。我们将其改为 NodePort,配合后续 Nginx 反向代理对外提供服务。

修改 manifests/grafana-service.yaml:

apiVersion: v1
kind: Service
metadata:
  labels:
    app.kubernetes.io/component: grafana
    app.kubernetes.io/name: grafana
    app.kubernetes.io/part-of: kube-prometheus
    app.kubernetes.io/version: 13.0.1
  name: grafana
  namespace: monitoring
spec:
  ports:
  - name: http
    nodePort: 30002
    port: 3000
    targetPort: http
  selector:
    app.kubernetes.io/component: grafana
    app.kubernetes.io/name: grafana
    app.kubernetes.io/part-of: kube-prometheus
  type: NodePort

关键改动:

  • • type: ClusterIP → type: NodePort

  • • 新增 nodePort: 30002,指定固定端口

⚠️ 注意:NodePort 范围为 30000-32767,确保 30002 未被其他服务占用。

五、Grafana 资源调优:解决查询崩溃问题

5.1 问题描述

kube-prometheus 默认给 Grafana 设置的资源限制非常保守:

resources:
  limits:
    cpu: 200m
    memory: 200Mi
  requests:
    cpu: 100m
    memory: 100Mi

在实际使用中,当执行大范围时间区间查询或加载多个 Dashboard 时,200Mi 的内存限制极易触发 OOMKilled,导致 Grafana Pod 反复重启。

5.2 调整方案

将 limits 提升至 2000m CPU / 2000Mi 内存,requests 保持不变:

resources:
  limits:
    cpu: 2000m
    memory: 2000Mi
  requests:
    cpu: 100m
    memory: 100Mi

修改 manifests/grafana-deployment.yaml 中对应的 resources 段即可。完整的 Deployment 文件较长,核心改动部分如下:

# manifests/grafana-deployment.yaml(节选)
spec:
  template:
    spec:
      containers:
      - name: grafana
        image: register.abc.cn/grafana/grafana:13.0.1  # 已替换为内网镜像
        resources:
          limits:
            cpu: 2000m        # ← 从 200m 提升
            memory: 2000Mi    # ← 从 200Mi 提升
          requests:
            cpu: 100m
            memory: 100Mi

💡 经验值参考:

  • • 小型集群(<50 节点):limits 500m/500Mi 通常够用

  • • 中型集群(50-200 节点):建议 1000m/1000Mi

  • • 大型集群(200+ 节点)或 Dashboard 较多:建议 2000m/2000Mi 起步

六、部署 kube-prometheus

6.1 部署顺序

必须先部署 setup 目录(包含 CRD、Namespace、RBAC 等基础资源),再部署 manifests 目录:

# 第一步:部署 CRD 和基础资源(使用 server-side apply)
kubectl apply --server-side -f ./setup

# 第二步:部署所有监控组件
kubectl create -f ./

⚠️ setup 目录必须使用 --server-side 参数,因为部分 CRD 资源体积较大,客户端 apply 可能因 annotations 超长而失败。

6.2 验证部署状态

kubectl get pods -n monitoring

预期所有 Pod 均为 Running 状态:

NAME                                   READY   STATUS    RESTARTS   AGE
alertmanager-main-0                    2/2     Running   0          5m
alertmanager-main-1                    2/2     Running   0          5m
alertmanager-main-2                    2/2     Running   0          5m
blackbox-exporter-xxx                  3/3     Running   0          5m
grafana-xxx                            1/1     Running   0          5m
kube-state-metrics-xxx                 3/3     Running   0          5m
node-exporter-xxx                      2/2     Running   0          5m
prometheus-adapter-xxx                 1/1     Running   0          5m
prometheus-k8s-0                       2/2     Running   0          5m
prometheus-k8s-1                       2/2     Running   0          5m
prometheus-operator-xxx                2/2     Running   0          5m

七、删除 NetworkPolicy(重要!)

kube-prometheus 默认为 Prometheus、Grafana、Alertmanager 创建了 NetworkPolicy,限制了只允许特定来源的流量。在大多数内网环境中,这会导致外部无法直接访问这些服务。

需要手动删除这三个 NetworkPolicy:

kubectl delete -f manifests/prometheus-networkPolicy.yaml
kubectl delete -f manifests/grafana-networkPolicy.yaml
kubectl delete -f manifests/alertmanager-networkPolicy.yaml

💡 安全建议: 如果你的集群部署了 Calico 等支持 NetworkPolicy 的 CNI,且对网络安全有更高要求,建议不删除而是修改 NetworkPolicy 规则,放行特定 IP 段。

八、Nginx 反向代理配置

为了让团队通过域名 + HTTPS 访问 Grafana,我们在前端 Nginx 上配置反向代理。

8.1 HTTP 自动跳转 HTTPS

server {
    listen       80;
    server_name  grafana.abc.cn;
    rewrite ^ https://$server_name$request_uri? permanent;
}

8.2 HTTPS 主配置

server {
    listen       443 ssl;
    server_name  grafana.abc.cn;

    ssl_certificate     /opt/ssl/all.abc.cn/abc.cn.pem;
    ssl_certificate_key /opt/ssl/all.abc.cn/abc.cn.key;

    ssl_session_cache    shared:SSL:1m;
    ssl_session_timeout  5m;
    ssl_ciphers 'HIGH:!aNULL:!MD5:!SHA:!DSS';
    ssl_prefer_server_ciphers  on;

    # Grafana 主代理
    location / {
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_set_header Host $host;
        proxy_read_timeout 86400;
        proxy_send_timeout 86400;
        proxy_pass   http://ip:30002;
    }

    # Grafana Live WebSocket 支持(实时面板刷新)
    location /api/live/ws {
        proxy_pass   http://ip:30002;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection $connection_upgrade;
        proxy_set_header Host $host;
        proxy_read_timeout 86400;
    }
}

配置要点:

配置项

说明

proxy_set_header Upgrade

支持 WebSocket 升级,Grafana Live 功能必需

proxy_read_timeout 86400

长连接超时设为 24 小时,防止 Grafana 实时面板断开

/api/live/ws

 单独配置

Grafana 13.x 的 Live 功能使用独立的 WebSocket 通道

proxy_pass

 指向 NodePort

ip:30002

 为 K8s 节点 IP + NodePort

⚠️ 需要在 Nginx 的 http 块中定义 $connection_upgrade 变量:

map $http_upgrade $connection_upgrade {
    default upgrade;
    ''      close;
}

8.3 验证访问

配置完成后:

1. 访问 https://grafana.abc.cn

2. 默认账号密码:admin / admin(首次登录会要求修改密码)

3. 进入 Dashboard 页面,即可看到预置的 K8s 集群监控面板

九、部署后的检查清单

部署完成后,建议按以下清单逐项确认:

# ✅ 1. 所有 Pod 正常运行
kubectl get pods -n monitoring | grep -v Running

# ✅ 2. Prometheus Targets 正常(Web UI → Status → Targets)
# 所有 targets 状态应为 UP

# ✅ 3. Grafana 数据源连通(Data Sources → Prometheus → Test)

# ✅ 4. Dashboard 数据正常显示
# 重点关注:K8s Resources Cluster、Nodes、Pods 等核心面板

# ✅ 5. Alertmanager 可访问
# https://grafana2.abc.cn 同节点 9093 端口

# ✅ 6. 资源使用正常,无 OOMKilled
kubectl get pods -n monitoring -o wide
kubectl top pods -n monitoring

z

十、常见问题 FAQ

Q1:Pod 一直 ImagePullBackOff?

确认内网仓库地址可被所有 K8s 节点访问,且节点已配置仓库认证(如需要):

# 在每个节点上测试拉取
crictl pull register.abc.cn/grafana/grafana:13.0.1

Q2:Grafana 面板显示 "No Data"?

检查 Prometheus 数据源配置是否正确,通常 URL 为 http://prometheus-k8s.monitoring.svc:9090。

Q3:NetworkPolicy 删了还是不生效?

确认你的 CNI 插件支持 NetworkPolicy。如果用的是 Flannel 等不支持的 CNI,NetworkPolicy 本身就不会生效,无需删除。

Q4:prometheus-operator 的 CRD 冲突?

如果集群已有旧版 CRD,使用 --server-side --force-conflicts 参数:

kubectl apply --server-side --force-conflicts -f ./setup

十一、总结

本文完整记录了在 K8s 1.36 + 内网离线环境 下部署 kube-prometheus 的全流程:

下载代码 → 镜像替换 → Grafana NodePort → 资源调优 → 部署 → 删除 NetworkPolicy → Nginx 代理

关键经验总结:

1. 版本对齐是前提 —— main 分支对应最新 K8s,务必确认兼容性矩阵

2. 镜像替换要彻底 —— 用 grep 全量检索,不要遗漏任何 YAML 文件

3. Grafana 默认 limit 太低 —— 生产环境至少给到 1000Mi 内存

4. NetworkPolicy 是隐形杀手 —— 部署后访问不通,首先排查它

5. WebSocket 配置别遗漏 —— Grafana 13.x 的 Live 功能需要单独的 WS 代理配置

Comment