# Prometheus 监控 k8s 集群节点、容器资源
https://prometheus.io/docs/prometheus/latest/configuration/configuration/#kubernetes_sd_config
# 前言
对于K8s集群的监控一般我们需要考虑以下几个方面:
- Kubernetes 节点的监控:比如节点的 cpu、load、disk、memory 等指标
- 内部系统组件的状态:比如 kube-scheduler、kube-controller-manager、kubedns/coredns 等组件的详细运行状态
- 编排级的 metrics:比如 Deployment 的状态、资源请求、调度和 API 延迟等数据指标
Kubernetes 集群的监控方案目前主要有以下几种方案:
- cAdvisor(Container Advisor)是由 Google 开发的一个开源工具,用于自动收集、处理和导出运行在 Linux 系统上的容器的性能指标。它是 Kubernetes 中的一个核心组件,广泛用于监控容器化应用程序的资源使用情况。
- Kubernetes Metrics Server 是 Kubernetes 生态系统中的一个轻量级指标收集工具,专门用于在集群内部收集资源使用数据。它是 Kubernetes 控制面板中用于资源监控的核心组件之一。
- kube-state-metrics 是一个开源项目,用于在 Kubernetes 集群中导出集群对象的状态指标。与监控集群节点和容器的资源使用情况的 metrics-server 不同,kube-state-metrics 专注于 Kubernetes API 对象的状态,而不是节点和容器资源消耗。
# 部署node_exporter
市面上有很多成熟的节点监控方案,常见的如zabbix、prometheus+node_exporter,这里通过daemonset方式部署node_exporter来采集k8s集群节点的数据
cat > node_exporter.yaml << EOF
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: node-exporter
namespace: monitor
labels:
name: node-exporter
spec:
selector:
matchLabels:
name: node-exporter
template:
metadata:
labels:
name: node-exporter
spec:
hostPID: true
hostIPC: true
hostNetwork: true
containers:
- name: node-exporter
image: quay.io/prometheus/node-exporter:v1.9.1
ports:
- containerPort: 19100
resources:
requests:
cpu: 0.15
securityContext:
privileged: true
args:
- --web.listen-address=:19100
- --path.procfs
- /host/proc
- --path.sysfs
- /host/sys
- --collector.filesystem.ignored-mount-points
- '"^/(sys|proc|dev|host|etc)($|/)"'
volumeMounts:
- name: dev
mountPath: /host/dev
- name: proc
mountPath: /host/proc
- name: sys
mountPath: /host/sys
- name: rootfs
mountPath: /rootfs
tolerations:
- key: "node-role.kubernetes.io/control-plane"
operator: "Exists"
effect: "NoSchedule"
volumes:
- name: proc
hostPath:
path: /proc
- name: dev
hostPath:
path: /dev
- name: sys
hostPath:
path: /sys
- name: rootfs
hostPath:
path: /
EOF
# 配置prometheus监控k8s节点
Prometheus 使用 kubernetes_sd_configs 允许 Prometheus 自动发现 Kubernetes 集群中的服务、节点、Pod 以及其他资源,并从中抓取监控指标。主要支持5种服务发现模式,分别是:Node、Service、Pod、Endpoints、Ingress。
# prometheus安装在k8s集群外
Kubernetes 在 v1.22 版本之前自动创建用来访问 Kubernetes API 的长期凭据。 这一较老的机制是基于创建令牌 Secret 对象来实现的,Secret 对象可被挂载到运行中的 Pod 内。 在最近的版本中,包括 Kubernetes v1.32,API 凭据可以直接使用 TokenRequest API 来获得,并使用一个投射卷挂载到 Pod 中。使用此方法获得的令牌具有受限的生命期长度,并且能够在挂载它们的 Pod 被删除时自动被废弃。
你仍然可以通过手动方式来创建服务账号令牌 Secret 对象,例如你需要一个永远不过期的令牌时。 不过,使用 TokenRequest 子资源来获得访问 API 的令牌的做法仍然是推荐的方式。
当 Prometheus 部署在 Kubernetes 集群外部,并希望使用 Kubernetes 服务发现特性(kubernetes_sd_configs),以便抓取集群内的节点或服务信息时,需要正确配置访问 Kubernetes API Server 的连接地址和认证信息。 因为在集群外部,Prometheus 无法通过集群内部的 DNS 名称 kubernetes.default.svc 访问 API Server。 同时,还需要提供访问 Kubernetes API Server 所需的认证信息,例如 Bearer Token 或 TLS 证书。
- 准备Bearer Token,用于API Server认证
kubectl create ns monitor
kubectl -n monitor create sa prometheus
# 自定义集群角色
kubectl create clusterrole prometheus --verb=get,list,watch --resource=nodes,nodes/proxy,services,endpoints,pods
# 创建集群角色绑定
kubectl create clusterrolebinding prometheus --clusterrole prometheus --serviceaccount monitor:prometheus
# 手动为 ServiceAccount 创建长期有效的 API 令牌
kubectl apply -f - <<EOF
apiVersion: v1
kind: Secret
metadata:
name: prometheus
namespace: monitor
annotations:
kubernetes.io/service-account.name: prometheus
type: kubernetes.io/service-account-token
EOF
# 从secret中提取token字段并base64解码,并写入k8s-sa-prometheus.token文件
kubectl -n monitor get secret prometheus -o jsonpath="{.data.token}" |base64 -d |tee k8s-sa-prometheus.token
# 从secret中提取ca.crt字段并base64解码,并写入k8s-sa-prometheus.ca.crt文件
kubectl -n monitor get secret prometheus -o jsonpath="{.data.ca\.crt}" | base64 -d |tee k8s-sa-prometheus.ca.crt
- 配置prometheus接入node_exporter监控指标数据
将上面的k8s-sa-prometheus.token和k8s-sa-prometheus.ca.crt文件复制到prometheus服务器的某个目录下存放,这里放置到 /usr/local/prometheus/secrets/目录下
vim prometheus.yml
...
- job_name: 'kubernetes-node'
kubernetes_sd_configs:
- role: node
api_server: https://<controlPlaneEndpoint>
tls_config:
ca_file: /usr/local/prometheus/secrets/k8s-sa-prometheus.ca.crt
bearer_token_file: /usr/local/prometheus/secrets/k8s-sa-prometheus.token
relabel_configs:
- source_labels: [__address__]
regex: '(.*):10250'
replacement: '${1}:19100'
target_label: __address__
action: replace
# prometheus安装在k8s集群内
由于prometheus在容器内部,这里不需要单独指定API Server地址和token文件,但是部署prometheus的时候需要单独指定一个sa才有权限
- 配置prometheus接入node_exporter监控指标数据
vim prometheus.yml
...
- job_name: 'kubernetes-node'
kubernetes_sd_configs:
- role: node
relabel_configs:
- source_labels: [__address__]
regex: '(.*):10250'
replacement: '${1}:19100'
target_label: __address__
action: replace
# 配置prometheus监控容器资源
前面说过,cAdvisor 广泛用于监控容器化应用程序的资源使用情况,在k8s中已经内置了该组件,所以不需要我们单独去安装
cAdvisor数据接口可以从以下2个路径获取:
- 直接通过 kubelet 获取:
https://<node-ip>:10250/metrics/cadvisor
- 通过 API Server 代理访问 kubelet:
https://<controlPlaneEndpoint>/api/v1/nodes/<node>/proxy/metrics
这里我们直接通过kubelet的10250获取数据
注意需要启用 kubelet 的认证和授权 Webhook,确保对请求的管理
添加权限,特别注意需要nodes/metrics的create权限
kubectl edit clusterrole prometheus
...
rules:
- apiGroups: [""]
resources: ["nodes", "nodes/proxy", "services", "endpoints", "pods"]
verbs: ["get", "list", "watch"]
- apiGroups: [""]
resources:
- nodes/metrics
verbs: ["create", "get", "list", "watch"]
# prometheus安装在k8s集群外
修改prometheus配置文件如下:
vim prometheus.yml
...
- job_name: 'kubernetes-cadvisor'
scheme: https
tls_config:
insecure_skip_verify: true
bearer_token_file: /usr/local/prometheus/secrets/k8s-sa-prometheus.token
kubernetes_sd_configs:
- role: node
api_server: https://<controlPlaneEndpoint>
tls_config:
ca_file: /usr/local/prometheus/secrets/k8s-sa-prometheus.ca.crt
bearer_token_file: /usr/local/prometheus/secrets/k8s-sa-prometheus.token
relabel_configs:
- target_label: __metrics_path__
replacement: /metrics/cadvisor
- action: labelmap
regex: __meta_kubernetes_node_label_(.+)
# prometheus安装在k8s集群内
修改prometheus的configmap
# 编辑prometheus资源清单文件
vim prometheus.yaml
...
- job_name: 'kubernetes-cadvisor'
scheme: https
tls_config:
insecure_skip_verify: true
bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token
kubernetes_sd_configs:
- role: node
relabel_configs:
- target_label: __metrics_path__
replacement: /metrics/cadvisor
- action: labelmap
regex: __meta_kubernetes_node_label_(.+)
快速跳转
