Skip to content

K3s部署监控栈

K3s 上部署 Prometheus 监控栈,核心检查点是采集链路是否覆盖 Kubernetes 对象、节点、容器和控制平面入口。kube-prometheus-stack 会同时安装 Prometheus Operator、Prometheus、Alertmanager、Grafana、node-exporter、kube-state-metrics 和相关 CRD。

监控栈部署在 K3s 上。Prometheus、Grafana、Alertmanager、kube-state-metrics、node-exporter 都会长期占用内存,日志、链路追踪和 CI/CD 组件也会继续叠加。K3s 保留 Kubernetes 资源模型,同时减少控制平面和基础组件的维护负担,更适合小规格集群承载这些平台。K3s 环境部署参考 Kubernetes 系列里的 K3s 安装部署

当前 K3s 集群是三节点单 server 架构:

节点IP角色
k3s-server01192.168.10.11control-plane
k3s-agent01192.168.10.12agent
k3s-agent02192.168.10.13agent

这套 K3s 默认使用 SQLite,不存在 etcd 采集端点。etcd 监控归到 embedded etcd 场景单独处理。

一、资源控制

默认 kube-prometheus-stack 会创建大量规则和 Grafana dashboard,小机器上容易把内存打满。当前三台机器内存并不宽裕,k3s-server013.5Gik3s-agent012.4Gik3s-agent021.9Gi。部署时做了几项收口:

项目处理
默认规则关闭 defaultRules.create,按场景单独补规则
Grafana 默认看板关闭默认 dashboard,减少 ConfigMap 和 sidecar 压力
Grafana sidecar关闭 dashboard/datasource sidecar,改成静态数据源
Prometheus 保留周期12hretentionSize 限制为 1000MB
Prometheus 采集周期60s,小环境先降低抓取频率
Prometheus 存储local-path PVC 5Gi
Alertmanager 存储local-path PVC 1Gi
Grafana 存储local-path PVC 1Gi
etcd/scheduler/controller-manager/kube-proxy当前 K3s 形态先关闭对应抓取项

local-path PVC 会绑定到首次运行 Pod 的节点。Grafana 如果已经在某个节点创建过 PVC,再直接改 nodeSelector 到另一个节点,Pod 会因为本地卷节点亲和性卡在 Pending。当前 Grafana 固定到 k3s-agent01,避免继续占用内存更小的 k3s-agent02

二、镜像源

监控栈常用镜像分布在 quay.ioregistry.k8s.iodocker.ioghcr.io。国内环境直接拉取经常不稳定,三台节点都配置 containerd mirror。

bash
base=/var/lib/rancher/k3s/agent/etc/containerd/certs.d
mkdir -p "$base/docker.io" "$base/quay.io" "$base/registry.k8s.io" "$base/ghcr.io" "$base/gcr.io"

cat >"$base/docker.io/hosts.toml" <<'EOF'
server = "https://registry-1.docker.io"

[host."https://docker.1ms.run"]
  capabilities = ["pull", "resolve"]
EOF

cat >"$base/quay.io/hosts.toml" <<'EOF'
server = "https://quay.io"

[host."https://quay.m.daocloud.io"]
  capabilities = ["pull", "resolve"]
EOF

cat >"$base/registry.k8s.io/hosts.toml" <<'EOF'
server = "https://registry.k8s.io"

[host."https://k8s.m.daocloud.io"]
  capabilities = ["pull", "resolve"]
EOF

cat >"$base/ghcr.io/hosts.toml" <<'EOF'
server = "https://ghcr.io"

[host."https://ghcr.m.daocloud.io"]
  capabilities = ["pull", "resolve"]
EOF

cat >"$base/gcr.io/hosts.toml" <<'EOF'
server = "https://gcr.io"

[host."https://gcr.m.daocloud.io"]
  capabilities = ["pull", "resolve"]
EOF

重启 K3s 服务让 containerd 重新读取配置:

bash
# server 节点
systemctl restart k3s

# agent 节点
systemctl restart k3s-agent

三、安装 Helm

bash
cd /tmp

# Helm 安装在执行部署的管理节点上
curl -L --connect-timeout 10 --retry 3 \
  https://get.helm.sh/helm-v3.18.6-linux-amd64.tar.gz \
  -o helm-v3.18.6-linux-amd64.tar.gz

tar -zxf helm-v3.18.6-linux-amd64.tar.gz
install -m 0755 linux-amd64/helm /usr/local/bin/helm

helm version --short

K3s 的 kubeconfig 在 /etc/rancher/k3s/k3s.yaml。Helm 执行前设置:

bash
export KUBECONFIG=/etc/rancher/k3s/k3s.yaml

四、values 配置

/root/monitoring/kps-lite-values.yaml

yaml
fullnameOverride: kps

crds:
  enabled: true

defaultRules:
  create: false

kubeEtcd:
  enabled: false
kubeControllerManager:
  enabled: false
kubeScheduler:
  enabled: false
kubeProxy:
  enabled: false

kubeApiServer:
  enabled: true
coreDns:
  enabled: true
kubelet:
  enabled: true
nodeExporter:
  enabled: true
kubeStateMetrics:
  enabled: true

prometheusOperator:
  resources:
    requests:
      cpu: 50m
      memory: 128Mi
    limits:
      memory: 256Mi
  nodeSelector:
    kubernetes.io/hostname: k3s-server01

prometheus-node-exporter:
  resources:
    requests:
      cpu: 20m
      memory: 32Mi
    limits:
      memory: 128Mi

kube-state-metrics:
  resources:
    requests:
      cpu: 30m
      memory: 96Mi
    limits:
      memory: 192Mi
  nodeSelector:
    kubernetes.io/hostname: k3s-server01

grafana:
  enabled: true
  adminPassword: "admin123"
  defaultDashboardsEnabled: false
  defaultDashboardsTimezone: Asia/Shanghai
  service:
    type: NodePort
    nodePort: 30300
  nodeSelector:
    kubernetes.io/hostname: k3s-agent01
  resources:
    requests:
      cpu: 50m
      memory: 128Mi
    limits:
      memory: 384Mi
  persistence:
    enabled: true
    type: pvc
    storageClassName: local-path
    accessModes:
      - ReadWriteOnce
    size: 1Gi
  sidecar:
    dashboards:
      enabled: false
    datasources:
      enabled: false
  datasources:
    datasources.yaml:
      apiVersion: 1
      datasources:
        - name: Prometheus
          type: prometheus
          uid: prometheus
          access: proxy
          url: http://kps-prometheus.monitoring:9090
          isDefault: true
          editable: true

alertmanager:
  service:
    type: NodePort
    nodePort: 30903
  alertmanagerSpec:
    replicas: 1
    nodeSelector:
      kubernetes.io/hostname: k3s-server01
    resources:
      requests:
        cpu: 30m
        memory: 64Mi
      limits:
        memory: 192Mi
    storage:
      volumeClaimTemplate:
        spec:
          storageClassName: local-path
          accessModes:
            - ReadWriteOnce
          resources:
            requests:
              storage: 1Gi

prometheus:
  service:
    type: NodePort
    nodePort: 30900
  prometheusSpec:
    replicas: 1
    retention: 12h
    retentionSize: 1000MB
    scrapeInterval: 60s
    evaluationInterval: 60s
    nodeSelector:
      kubernetes.io/hostname: k3s-server01
    resources:
      requests:
        cpu: 100m
        memory: 384Mi
      limits:
        memory: 768Mi
    storageSpec:
      volumeClaimTemplate:
        spec:
          storageClassName: local-path
          accessModes:
            - ReadWriteOnce
          resources:
            requests:
              storage: 5Gi
    serviceMonitorSelectorNilUsesHelmValues: false
    podMonitorSelectorNilUsesHelmValues: false
    ruleSelectorNilUsesHelmValues: false
    probeSelectorNilUsesHelmValues: false

这份配置偏向小环境。Grafana 默认 dashboard 和 sidecar 关闭后,Grafana 只保留一个主容器,内存占用明显更低。Prometheus 保留 12h,抓取周期放到 60s,适合当前集群先验证采集链路;长期保留通常要配远端存储,或者把 Prometheus 单独放到资源更宽裕的节点。

五、安装监控栈

bash
export KUBECONFIG=/etc/rancher/k3s/k3s.yaml

helm repo add prometheus-community https://prometheus-community.github.io/helm-charts
helm repo update

helm upgrade --install kps prometheus-community/kube-prometheus-stack \
  --namespace monitoring --create-namespace \
  --version 85.3.3 \
  -f /root/monitoring/kps-lite-values.yaml \
  --timeout 15m

网络不稳定时,可以提前下载 chart 包,再用本地包升级:

bash
helm upgrade --install kps /root/monitoring/kube-prometheus-stack-85.3.3.tgz \
  --namespace monitoring --create-namespace \
  -f /root/monitoring/kps-lite-values.yaml \
  --timeout 15m

六、组件状态

bash
kubectl -n monitoring get pods -o wide
kubectl -n monitoring get svc -o wide
kubectl -n monitoring get pvc
kubectl -n monitoring top pods

本次部署后的核心 Pod:

text
alertmanager-kps-alertmanager-0           2/2 Running
kps-grafana-56fb658cf7-l2tfh              1/1 Running
kps-kube-state-metrics-7845f765c4-szf5z   1/1 Running
kps-operator-5c67bb6dd7-5gdbp             1/1 Running
kps-prometheus-node-exporter-78cnk        1/1 Running
kps-prometheus-node-exporter-mnnb5        1/1 Running
kps-prometheus-node-exporter-mxjsm        1/1 Running
prometheus-kps-prometheus-0               2/2 Running

NodePort:

组件地址
Grafanahttp://192.168.10.11:30300
Prometheushttp://192.168.10.11:30900
Alertmanagerhttp://192.168.10.11:30903

Grafana 账号:

用户密码
adminadmin123

PVC:

text
alertmanager-kps-alertmanager-db-alertmanager-kps-alertmanager-0   1Gi
kps-grafana                                                        1Gi
prometheus-kps-prometheus-db-prometheus-kps-prometheus-0           5Gi

七、Target 验证

Prometheus ready:

bash
# Prometheus ready 接口返回 200,说明服务已经能处理请求
curl -sS -o /dev/null -w 'prometheus %{http_code}\n' \
  http://192.168.10.11:30900/-/ready

Grafana ready:

bash
# Grafana 登录页返回 200,只用于验证 Web 入口可访问
curl -sS -o /dev/null -w 'grafana %{http_code}\n' \
  http://192.168.10.11:30300/login

Alertmanager ready:

bash
# Alertmanager ready 接口返回 200,说明告警接收服务已经就绪
curl -sS -o /dev/null -w 'alertmanager %{http_code}\n' \
  http://192.168.10.11:30903/-/ready

三者都返回 200。Prometheus Status -> Targets 里已经有这些 target:

job说明
apiserverK3s API Server
coredns集群 DNS
kubelet三台节点 kubelet、cAdvisor、probes
node-exporter三台节点主机指标
kube-state-metricsK8s 对象状态
kps-prometheusPrometheus 自身
kps-alertmanagerAlertmanager
kps-grafanaGrafana

几个查询验证:

bash
# 当前抓取目标数量
curl -sG http://127.0.0.1:30900/api/v1/query \
  --data-urlencode 'query=count(up)'

# K8s Pod 对象指标
curl -sG http://127.0.0.1:30900/api/v1/query \
  --data-urlencode 'query=count(kube_pod_info)'

# 三台节点 node-exporter 指标
curl -sG http://127.0.0.1:30900/api/v1/query \
  --data-urlencode 'query=count(node_uname_info)'

# 容器 CPU 指标,来自 kubelet/cAdvisor
curl -sG http://127.0.0.1:30900/api/v1/query \
  --data-urlencode 'query=count(container_cpu_usage_seconds_total)'

# API Server 请求指标
curl -sG http://127.0.0.1:30900/api/v1/query \
  --data-urlencode 'query=count(apiserver_request_total)'

本次验证结果里,count(up)21count(node_uname_info)3,说明三台节点都被 node-exporter 覆盖。kube_pod_infocontainer_cpu_usage_seconds_totalapiserver_request_total 都能查到数据,说明对象状态、容器资源和 API Server 指标已经进入 Prometheus。

资源占用也要同时看一下:

bash
# 看节点整体资源压力
kubectl top nodes

# 看 monitoring 命名空间里每个容器的 CPU 和内存
kubectl -n monitoring top pods --containers

当前 Prometheus 主容器约 289Mi,Grafana 约 349Mi,Alertmanager 主容器约 45Mi。Grafana 启动时会有一段镜像拉取和 readiness 探测失败记录,只要最终 Pod 进入 Running,访问 /login 返回 200,就不是内存把服务打崩。

八、当前未启用项

当前 values 里关闭了几类 target:

项目原因
kubeEtcd当前 K3s 是 SQLite,不存在 etcd 指标端点
kubeSchedulerK3s 将控制面组件打包在 k3s server 进程里,默认监听回环地址
kubeControllerManager同上,控制平面监控单独处理
kubeProxyK3s 默认不一定按独立 kube-proxy 形态暴露指标
default rules小环境先降低规则数量和内存压力
default dashboards手动导入或按截图需要创建看板

这些关闭项和当前 K3s 形态有关。当前集群先保留已经能稳定采到的指标,控制平面、节点组件、对象状态、应用指标和告警规则分别展开;etcd 放到 embedded etcd 场景处理。