k8s 集群需要监控的目标:
- k8s 集群运行的服务
- 组件服务:kube-apiserver、 kube-scheduler、kube-controller-manager、etcd、coredns
- 业务服务:业务 pod
- 业务服务必须要暴漏 /metrics 接口,如果 Pod 里的服务没有暴漏该接口,那么应该塞进一个 sidecar 容器(exporter)来负责暴漏。
- 创建一个 svc,svc 会自动生成 endpoint 资源,以便被 prometheus server 筛选到。
- svc 带上指定的注解或标签。如 prometheus.io/scrape: “true”
- 监控资源的状态:Pod、DaemonSet、Deployment、Job、CronJob 等各种资源状态的监控。
- 监控容器的状态:需要用到组件 cAdvisor,而 cAdvisor 已经内置在了 kubelet 组件之中。
实现示例:
- 抓取 apiserver 的监控指标
- job_name: 'kubernetes-apiservers' # 作业名称:用于监控 Kubernetes API Server
kubernetes_sd_configs:
- role: endpoints # 使用 endpoints 服务发现角色
scheme: https # API Server 使用 HTTPS 协议
tls_config:
# 使用 Pod 内默认挂载的 Service Account 的 CA 证书
ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt
# 跳过 TLS 证书验证(生产环境不建议)
insecure_skip_verify: true
# 使用 Service Account token 进行认证
bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token
# Prometheus 服务发现会找到所有的 endpoints,但通过这个重标签规则,只保留:
# 命名空间 = default
# Service名称 = kubernetes
# 端口名称 = https
relabel_configs:
- source_labels:
[__meta_kubernetes_namespace, __meta_kubernetes_service_name, __meta_kubernetes_endpoint_port_name]
action: keep # 保留匹配的 target,丢弃不匹配的
regex: default;kubernetes;https # 匹配规则:命名空间;服务名称;端口名称
YAML- 抓取 kube-controller-manager 的监控指标
# 1、创建 Service,通过标签选择器关联到 kube-controller-manager
apiVersion: v1
kind: Service
metadata:
labels:
app.kubernetes.io/component: kube-controller-manager
app.kubernetes.io/name: kube-controller-manager
k8s-app: kube-controller-manager
name: kube-controller-manager
namespace: kube-system
spec:
clusterIP: None # 使用 Headless Service,不分配 ClusterIP
ports:
- name: https-metrics # 端口名称,在 Prometheus 重标签中会用到
port: 10257 # Service 端口
targetPort: 10257 # 目标 Pod 端口
protocol: TCP
selector:
component: kube-controller-manager # 选择标签为 component: kube-controller-manager 的 Pod
YAML注意:每台机器上的 controller-manager 都监听在127.0.0.1,所以是无法访问的,需要修改其默认监听。
# 2、在 /etc/kubernetes/manifests/kube-controller-manager.yaml 中修改
--bind-address=0.0.0.0 # 从 127.0.0.1 改为 0.0.0.0
Bash# 3、添加 Prometheus 监控配置
- job_name: 'kube-controller-manager' # 作业名称
kubernetes_sd_configs:
- role: endpoints # 使用 endpoints 服务发现
scheme: https # 使用 HTTPS 协议
tls_config:
ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt # CA 证书路径
insecure_skip_verify: true # 跳过 TLS 证书验证(生产环境不推荐)
bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token # 认证 token
relabel_configs:
- source_labels: [__meta_kubernetes_namespace, __meta_kubernetes_service_name, __meta_kubernetes_endpoint_port_name]
action: keep # 只保留匹配的 target
regex: kube-system;kube-controller-manager;https-metrics # 匹配规则
YAML- 抓取 kube-scheduler 的监控指标,配置方式同上。
- 抓取 etcd 的监控指标
# 在每个 master 节点上修改 etcd 的静态 Pod 配置
# 文件位置:/etc/kubernetes/manifests/etcd.yaml
spec:
containers:
- command:
- etcd
# 添加或修改以下参数:
- --listen-metrics-urls=http://0.0.0.0:2381 # 从 127.0.0.1 改为 0.0.0.0
# 其他原有参数...
YAML# 创建 etcd Service
apiVersion: v1
kind: Service
metadata:
namespace: kube-system
name: etcd
labels:
k8s-app: etcd
spec:
selector:
component: etcd # 选择标签为 component: etcd 的 Pod
type: ClusterIP
clusterIP: None # Headless Service,直接使用 Pod IP
ports:
- name: http # 端口名称,在 Prometheus 重标签中会用到
port: 2381 # Service 端口
targetPort: 2381 # Pod 实际监听的端口
protocol: TCP
YAML# 添加 etcd 监控配置
- job_name: 'etcd' # 作业名称
kubernetes_sd_configs:
- role: endpoints # 使用 endpoints 服务发现
scheme: http # etcd metrics 使用 HTTP 协议(非加密)
relabel_configs:
- source_labels: [__meta_kubernetes_namespace, __meta_kubernetes_service_name, __meta_kubernetes_endpoint_port_name]
action: keep # 只保留匹配的 target
regex: kube-system;etcd;http # 匹配规则:命名空间;服务名称;端口名称
YAML- 配置自动发现业务服务 Pod
- job_name: 'kubernetes-endpoints'
kubernetes_sd_configs:
- role: endpoints # 发现所有 Kubernetes endpoints
relabel_configs:
# 1. 根据注解过滤:只保留包含 prometheus.io/scrape=true 的 Service
- source_labels: [__meta_kubernetes_service_annotation_prometheus_io_scrape]
action: keep # 保留匹配的 target
regex: true # 匹配注解值为 "true"
# 2. 设置抓取协议:根据注解动态配置 HTTP/HTTPS
- source_labels: [__meta_kubernetes_service_annotation_prometheus_io_scheme]
action: replace # 替换操作
target_label: __scheme__ # 设置协议标签(http/https)
regex: (https?) # 匹配 "http" 或 "https"
# 3. 设置指标路径:自定义 metrics 端点路径
- source_labels: [__meta_kubernetes_service_annotation_prometheus_io_path]
action: replace
target_label: __metrics_path__ # 设置指标路径
regex: (.+) # 匹配任意非空字符串
# 4. 重构访问地址:组合 IP 和端口
- source_labels:
[__address__, __meta_kubernetes_service_annotation_prometheus_io_port]
action: replace
target_label: __address__ # 设置最终访问地址
regex: ([^:]+)(?::\d+)?;(\d+) # 正则表达式解析
replacement: $1:$2 # 格式:IP:Port
# 5. 映射 Service 标签
- action: labelmap
regex: __meta_kubernetes_service_label_(.+) # 匹配所有 Service 标签
# 6. 添加命名空间标签
- source_labels: [__meta_kubernetes_namespace]
action: replace
target_label: kubernetes_namespace # 标准化命名空间标签名
# 7. 添加 Service 名称标签
- source_labels: [__meta_kubernetes_service_name]
action: replace
target_label: kubernetes_service # 标准化服务名称标签名
# 8. 添加 Pod 名称标签
- source_labels: [__meta_kubernetes_pod_name]
action: replace
target_label: kubernetes_pod_name # 标准化 Pod 名称标签名
YAML这是一个通用配置,允许通过 Service 注解来自动发现和监控应用:
apiVersion: v1
kind: Service
metadata:
name: my-app
annotations:
prometheus.io/scrape: "true" # 启用抓取
prometheus.io/scheme: "https" # 协议(可选,默认http)
prometheus.io/path: "/custom/metrics" # 路径(可选,默认/metrics)
prometheus.io/port: "9090" # 端口(可选,默认Service端口)
spec:
ports:
- port: 80
targetPort: 8080
YAML测试示例:
# prome-redis.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: redis
namespace: monitor
spec:
selector:
matchLabels:
app: redis
template:
metadata:
labels:
app: redis
spec:
containers:
- name: redis
image: redis:4
resources:
requests:
cpu: 100m
memory: 100Mi
ports:
- containerPort: 6379
- name: redis-exporter
image: oliver006/redis_exporter:latest
resources:
requests:
cpu: 100m
memory: 100Mi
ports:
- containerPort: 9121
---
apiVersion: v1
kind: Service
metadata:
name: redis
namespace: monitor
annotations: # --------------------------------》 Prometheus 自动发现注解
prometheus.io/scrape: 'true' # 启用 Prometheus 抓取
prometheus.io/port: '9121' # 指定 metrics 端口
spec:
selector:
app: redis
ports:
- name: redis # Redis 服务端口
port: 6379
targetPort: 6379
- name: prom # Prometheus metrics 端口
port: 9121
targetPort: 9121
YAML- 资源的状态监控
需要部署 kube-state-metrics 来采集资源信息,metrics server 提供实时的资源监控指标给 HPA做决策用,不擅长做历史数据分析。kube-state-metrics 擅长做历史数据监控与分析,对接prometheus server。
# 下载
# 国外:git clone https://github.com/kubernetes/kube-state-metrics.git
# 国内:git clone https://gitee.com/egonlin/kube-state-metrics.git
cd kube-state-metrics/examples/standard
$ ls
cluster-role-binding.yaml cluster-role.yaml deployment.yaml service-account.yaml service.yaml
# 根据需要修改镜像地址
# 此外我们上面为 Prometheus 配置了 Endpoints 的自动发现,所以我们可以给 kube-state-metrics 的 Service 配置上对应的 annotations 来自动被发现,然后直接创建即可。
apiVersion: v1
kind: Service
metadata:
labels:
app.kubernetes.io/component: exporter
app.kubernetes.io/name: kube-state-metrics
app.kubernetes.io/version: 2.12.0
annotations:
prometheus.io/scrape: "true"
prometheus.io/port: "8080"
# kube-state-metrics暴露两个端口
# 8080端口:Kubernetes资源指标(主要监控数据)
# 8081端口:kube-state-metrics自身性能指标
# 这里只监控了 8080 端口,如果想监控多个端口,可以单独配置一个 job 或者修改上面的 Endpoints 的自动发现逻辑,实现多端口监控
name: kube-state-metrics
namespace: kube-system
spec:
clusterIP: None
ports:
- name: http-metrics
port: 8080 # 暴漏的监控端口
targetPort: http-metrics
- name: telemetry
port: 8081
targetPort: telemetry
selector:
app.kubernetes.io/name: kube-state-metrics
Bash- 容器的状态监控
需要用到组件 cAdvisor,而 cAdvisor 已经内置在了 kubelet 组件之中。
- job_name: 'kubernetes-cadvisor' # 作业名称:用于收集容器和Pod的资源使用情况指标
kubernetes_sd_configs:
- role: node # 自动发现集群中的所有节点
scheme: https # cAdvisor 通过 kubelet 的 HTTPS 接口暴露指标
tls_config:
ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt
insecure_skip_verify: true
bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token
relabel_configs:
# 1. 将 Kubernetes 节点标签映射为 Prometheus 标签
- action: labelmap
regex: __meta_kubernetes_node_label_(.+) # 匹配所有节点标签
replacement: $1 # 将匹配到的部分作为新标签名(去掉前缀)
# 2. 重写指标路径:将默认的 /metrics 改为 /metrics/cadvisor
- source_labels: [__meta_kubernetes_node_name] # 源标签:节点名称
regex: (.+) # 匹配任何节点名称(实际上这个匹配在这里只是占位符)
replacement: /metrics/cadvisor # 替换为 cAdvisor 的指标路径
target_label: __metrics_path__ # 目标标签:指定指标采集路径
kubectl apply -f prometheus-cm.yaml
curl -X POST "http://10.244.4.8:9090/-/reload"
ShellScript- Prometheus 监控 kubelet 组件示例
- job_name: 'kubelet' # 作业名称,用于监控 Kubernetes 节点上的 kubelet 组件
kubernetes_sd_configs:
- role: node # 使用 Kubernetes 服务发现,自动发现集群中的所有节点
scheme: https # kubelet 的 API 使用 HTTPS 协议
tls_config:
# 使用 Kubernetes Pod 内默认挂载的 Service Account 的 CA 证书来验证 kubelet 的 TLS 证书
ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt
# 设置为 true 跳过 TLS 证书验证(生产环境不建议,但在某些自签名证书环境下可能需要)
insecure_skip_verify: true
# 使用 Service Account 的 token 进行认证,kubelet 需要认证才能访问 metrics 接口
bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token
relabel_configs:
# 将 Kubernetes 节点的标签自动映射为 Prometheus 的标签
- action: labelmap
regex: __meta_kubernetes_node_label_(.+)
kubectl apply -f prometheus-cm.yaml
curl -X POST "http://10.244.4.8:9090/-/reload"
Bash上面的示例只实现了基本监控,而且要更新监控项配置也很繁琐,推荐使用 Prometheus Operator。