Prometheus监控Kubernetes

cAdvisor 和 KubeStateMetrics 简介

在部署监控组件监控 Kubernetes 集群服务之前,先了解下监控组件 cAdvisorKube State Metrics 都是什么。本人从相应的俩个组件的 Github 和相关网址收集了一些信息,分别对其进行描述。

什么是 cAdvisor

cAdvisor (Container Advisor) 是 Google 开源的一个容器监控工具,可用于对容器资源的使用情况和性能进行监控。它以守护进程方式运行,用于收集、聚合、处理和导出正在运行容器的有关信息。具体来说,该组件对每个容器都会记录其资源隔离参数、历史资源使用情况、完整历史资源使用情况的直方图和网络统计信息。

cAdvisor 本身就对 Docker 容器支持,并且还对其它类型的容器尽可能的提供支持,力求兼容与适配所有类型的容器。

由以上介绍我们可以知道,cAdvisor 是用于监控容器引擎的。由于其监控的实用性,Kubernetes 已经默认将其与 Kubelet 融合,所以我们无需再单独部署 cAdvisor 组件来暴露节点中容器运行的信息,直接使用 Kubelet 组件提供的指标采集地址即可。

什么是 KubeStateMetrics

Kube State Metrics 是一个简单的服务,该服务通过监听 Kubernetes API 服务器来生成不同资源的状态的 Metrics 数据。它不关注 Kubernetes 节点组件的运行状况,而是关注集群内部各种资源对象 (例如 deployment、node 和 pod) 的运行状况。

Kube State Metrics 是直接从 Kubernetes API 对象中获取生成的指标数据,这个过程中不会对指标数据进行修改。这样可以确保该组件提供的功能具有与 Kubernetes API 对象本身具有相同级别的稳定性。反过来讲,这意味着在某些情况下 Kube State Metrics 的 metrics 数据可能不会显示与 Kubectl 完全相同的值,因为 Kubectl 会应用某些启发式方法来显示可理解的消息。Kube State Metrics 公开了未经 Kubernetes API 修改的原始数据,这样用户可以拥有所需的所有数据,并根据需要执行启发式操作。

由于该组件 Kubernetes 并未与其默认集成在一起,所以需要我们单独部署。
Kube-State-Metrics下载

总结

要让 Prometheus 能监控 kubernetes 中容器的性能指标和 kubernetes 资源对象指标,需要部署 cadvisorkube-state-metrics。目前 cAdvisor 已经被 Kubernetes 默认集成,而Kube State Metrics 并没有被默认集成,所以我们需要在 Kubernetes 中部署 Kube State Metrics 组件,这样才能够将集群中的服务资源指标数据暴露出来,以便于我们对不同资源进行监控。

Prometheus使用kubernetes_sd_config

要想监控Kubernetes中的资源,Prometheus要使用 kubernetes_sd_config 来自动注册和自动发现。Kubernetes SD 配置允许从 Kubernetes 的REST API检索抓取目标,并始终与集群状态保持同步。

kubernetes_sd_config 这个是以角色(role)来定义收集的,<role>必须是endpointsservicepodnodeingress

以下是生产环境实际配置:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
scrape_configs:
- job_name: kube-apiserver/0
honor_timestamps: true
scrape_interval: 30s
scrape_timeout: 10s
metrics_path: /metrics
scheme: https
authorization:
credentials_file: /var/run/secrets/kubernetes.io/serviceaccount/token
tls_config:
ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt
server_name: kubernetes
insecure_skip_verify: false
follow_redirects: true
kubernetes_sd_configs:
- role: endpoints # 使用的role
namespaces: # 指定抓取的名称空间,如不指定则表示抓取所有名称空间
names:
- default

点击此查看官方示例

Role可配置的发现目标

点击此查看官方介绍

node

node角色发现每个群集节点有一个目标,其地址默认为Kubelet的HTTP端口。 目标地址默认为NodeInternalIP,NodeExternalIP,NodeLegacyHostIP和NodeHostName的地址类型顺序中Kubernetes节点对象的第一个现有地址。
可用元标签:

1
2
3
4
5
6
__meta_kubernetes_node_name:节点对象的名称。
__meta_kubernetes_node_label_<labelname>:节点对象中的每个标签。
__meta_kubernetes_node_labelpresent_<labelname>:true对于节点对象中的每个标签。
__meta_kubernetes_node_annotation_<annotationname>:来自节点对象的每个注释。
__meta_kubernetes_node_annotationpresent_<annotationname>:true对于节点对象中的每个注释。
__meta_kubernetes_node_address_<address_type>:每个节点地址类型的第一个地址(如果存在)。

另外,对于节点的instance标签,将会被设置成从API服务中获取的节点名称。

service

该service角色为每个服务发现每个服务端口的目标。这对于服务的黑盒监控通常很有用。该地址将设置为服务的Kubernetes DNS名称和相应的服务端口。
可用元标签:

1
2
3
4
5
6
7
8
9
10
__meta_kubernetes_namespace:服务对象的命名空间。
__meta_kubernetes_service_annotation_<annotationname>:来自服务对象的每个注释。
__meta_kubernetes_service_annotationpresent_<annotationname>:“true”表示服务对象的每个注释。
__meta_kubernetes_service_cluster_ip:服务的群集IP地址。(不适用于ExternalName类型的服务)
__meta_kubernetes_service_external_name:服务的DNS名称。(适用于ExternalName类型的服务)
__meta_kubernetes_service_label_<labelname>:来自服务对象的每个标签。
__meta_kubernetes_service_labelpresent_<labelname>:true对于服务对象的每个标签。
__meta_kubernetes_service_name:服务对象的名称。
__meta_kubernetes_service_port_name:目标服务端口的名称。
__meta_kubernetes_service_port_protocol:目标服务端口的协议。

pod

该pod角色发现所有pod并将其容器公开为目标。对于容器的每个声明端口,将生成单个目标。如果容器没有指定端口,则会创建每个容器的无端口目标,以通过重新标记手动添加端口。
可用元标签:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
__meta_kubernetes_namespace:pod对象的命名空间。
__meta_kubernetes_pod_name:pod对象的名称。
__meta_kubernetes_pod_ip:pod对象的pod IP。
__meta_kubernetes_pod_label_<labelname>:pod对象中的每个标签。
__meta_kubernetes_pod_labelpresent_<labelname>:true对于pod对象中的每个标签。
__meta_kubernetes_pod_annotation_<annotationname>:pod对象中的每个注释。
__meta_kubernetes_pod_annotationpresent_<annotationname>:true对于pod对象中的每个注释。
__meta_kubernetes_pod_container_init:true如果容器是InitContainer
__meta_kubernetes_pod_container_name:目标地址指向的容器的名称。
__meta_kubernetes_pod_container_port_name:容器端口的名称。
__meta_kubernetes_pod_container_port_number:容器端口号。
__meta_kubernetes_pod_container_port_protocol:容器端口的协议。
__meta_kubernetes_pod_ready:设置为truefalse准备好pod的就绪状态。
__meta_kubernetes_pod_phase:设置为Pending,Running,Succeeded,Failed或Unknown在生命周期。
__meta_kubernetes_pod_node_name:pod安排到的节点的名称。
__meta_kubernetes_pod_host_ip:pod对象的当前主机IP。
__meta_kubernetes_pod_uid:pod对象的UID。
__meta_kubernetes_pod_controller_kind:对象类型的pod控制器。
__meta_kubernetes_pod_controller_name:pod控制器的名称。

endpoints

该endpoints角色从列出的服务端点发现目标。对于每个端点地址,每个端口发现一个目标。如果端点由pod支持,则pod的所有其他容器端口(未绑定到端点端口)也会被发现为目标。
可用元标签:

1
2
3
4
5
6
7
8
9
__meta_kubernetes_namespace:端点对象的命名空间。
__meta_kubernetes_endpoints_name:端点对象的名称。对于直接从端点列表中发现的所有目标(不是从底层pod中另外推断的那些),附加以下标签:
__meta_kubernetes_endpoint_hostname:端点的主机名。
__meta_kubernetes_endpoint_node_name:托管端点的节点的名称。
__meta_kubernetes_endpoint_ready:设置为truefalse为端点的就绪状态。
__meta_kubernetes_endpoint_port_name:端点端口的名称。
__meta_kubernetes_endpoint_port_protocol:端点端口的协议。
__meta_kubernetes_endpoint_address_target_kind:端点地址目标的种类。类型不同看到的标签不同。
__meta_kubernetes_endpoint_address_target_name:端点地址目标的名称

如果端点属于服务,则附加role: service发现的所有标签。
对于由pod支持的所有目标,将附加role: pod发现的所有标签。

ingress

该ingress角色发现了一个目标,为每个进入的每个路径。这通常用于黑盒监控入口。地址将设置为入口规范中指定的主机。
可用元标签:

1
2
3
4
5
6
7
8
__meta_kubernetes_namespace:入口对象的命名空间。
__meta_kubernetes_ingress_name:入口对象的名称。
__meta_kubernetes_ingress_label_<labelname>:入口对象中的每个标签。
__meta_kubernetes_ingress_labelpresent_<labelname>:true对于入口对象中的每个标签
__meta_kubernetes_ingress_annotation_<annotationname>:来自入口对象的每个注释。
__meta_kubernetes_ingress_annotationpresent_<annotationname>:true对于来自入口对象的每个注释。
__meta_kubernetes_ingress_scheme:入口的协议方案,https如果设置了TLS配置。默认为http。
__meta_kubernetes_ingress_path:来自入口规范的路径。默认为/。

配置抓取

service 监控写法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 集群 内部 Service 监控
cat << EOF | kubectl apply -f -
apiVersion: v1
kind: Service
metadata:
labels:
app: prometheus-k8s
name: prometheus-k8s
annotations:
prometheus.io/scrape: 'true' # 多端口 prometheus.io/port: '9090' # 监控路径 prometheus.io/path: '/metrics' # 监控http协议 prometheus.io/scheme: 'http' 或者https
namespace: monitoring
spec:
ports:
- name: web
port: 9090
targetPort: web
selector:
app: prometheus-k8s
sessionAffinity: ClientIP
EOF
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
# 集群外部 Service 模式监控
cat << EOF | kubectl apply -f -
apiVersion: v1
kind: Service
metadata:
annotations:
prometheus.io/port: "10257"
prometheus.io/scrape: "true"
prometheus.io/scheme: "https"
labels:
k8s-app: kube-controller-manager
name: kube-controller-manager
namespace: monitoring
spec:
clusterIP: None
ports:
- name: https-metrics
port: 10257
protocol: TCP
targetPort: 10257
sessionAffinity: None
type: ClusterIP
---
apiVersion: v1
kind: Endpoints
metadata:
labels:
k8s-app: kube-controller-manager
name: kube-controller-manager
namespace: monitoring
subsets:
- addresses:
- ip: 192.168.2.175
- ip: 192.168.2.176
- ip: 192.168.2.177
ports:
- name: https-metrics
port: 10257
protocol: TCP
EOF

service写法使用的role

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
- job_name: kubernetes-endpoints
honor_timestamps: true
scrape_interval: 10s
scrape_timeout: 10s
metrics_path: /metrics
scheme: http
kubernetes_sd_configs:
- role: endpoints
bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token
tls_config:
ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt
insecure_skip_verify: true
relabel_configs:
- source_labels: [__meta_kubernetes_service_annotation_prometheus_io_scrape]
separator: ;
regex: "true"
replacement: $1
action: keep
- source_labels: [__meta_kubernetes_service_annotation_prometheus_io_scheme] # 如有此元标签则使用正则表达匹配 https,如果能匹配到,则把https赋值给__scheme__,替换上面的metrics的值,如没有此标签则此规则不生效
separator: ;
regex: (https?)
target_label: __scheme__
replacement: $1
action: replace
- source_labels: [__meta_kubernetes_service_annotation_prometheus_io_path] # 如有此元标签则使用正则表达匹配所有内容,把匹配到的内容赋值给__metrics_path__,替换上面默认的metrics_path的值,如没有此标签则此规则不生效
separator: ;
regex: (.+)
target_label: __metrics_path__
replacement: $1
action: replace
- source_labels: [__address__, __meta_kubernetes_service_annotation_prometheus_io_port] # 如果在添加注释时,没添加端口注释就是所有端口都监控了,如果一个service有5个端口那么会创建5个target。
separator: ;
regex: ([^:]+)(?::\d+)?;(\d+)
target_label: __address__
replacement: $1:$2
action: replace

POD 监控写法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
apiVersion: v1
kind: Pod
metadata:
creationTimestamp: null
labels:
component: kube-apiserver-ha-proxy
tier: control-plane
annotations:
prometheus.io/port: "8404" # 多端口指定监控端口 prometheus.io/port: '8084' # 监控路径 prometheus.io/path: '/metrics' # 监控http协议 prometheus.io/scheme: 'http' 或者https
prometheus.io/scrape: "true"
name: kube-apiserver-ha-proxy
namespace: kube-system
spec:
containers:
- args:
- "CP_HOSTS=192.168.2.175,192.168.2.176,192.168.2.177"
image: docker.io/juestnow/nginx-proxy:1.21.0
imagePullPolicy: IfNotPresent
name: kube-apiserver-ha-proxy
env:
- name: CPU_NUM
value: "4"
- name: BACKEND_PORT
value: "5443"
- name: HOST_PORT
value: "6443"
- name: CP_HOSTS
value: "192.168.2.175,192.168.2.176,192.168.2.177"
hostNetwork: true
priorityClassName: system-cluster-critical
status: {}
1
2
3
4
5
6
7
8
9
10
11
12
13
# daemonsets deployments statefulsets 写法
spec:
selector:
matchLabels:
k8s-app: traefik
template:
metadata:
creationTimestamp: null
labels:
k8s-app: traefik
annotations:
prometheus.io/port: '8080' # 多端口指定监控端口 prometheus.io/port: '8080' # 监控路径 prometheus.io/path: '/metrics' # 监控http协议 prometheus.io/scheme: 'http' 或者https
prometheus.io/scrape: 'true'

pod监控使用的role

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
- job_name: kubernetes-pods
honor_timestamps: true
scrape_interval: 10s
scrape_timeout: 10s
metrics_path: /metrics
scheme: http
bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token
tls_config:
ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt
insecure_skip_verify: true
kubernetes_sd_configs:
- role: pod
relabel_configs:
- source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_scrape]
separator: ;
regex: "true"
replacement: $1
action: keep
- source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_scheme]
separator: ;
regex: (https?)
target_label: __scheme__
replacement: $1
action: replace
- source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_path]
separator: ;
regex: (.+)
target_label: __metrics_path__
replacement: $1
action: replace
- source_labels: [__address__, __meta_kubernetes_pod_annotation_prometheus_io_port]
separator: ;
regex: ([^:]+)(?::\d+)?;(\d+)
target_label: __address__
replacement: $1:$2
action: replace

blackbox-exporter 集群内部监控注释方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
# service 写法 http 模式 监控
cat << EOF | kubectl apply -f -
apiVersion: v1
kind: Service
metadata:
labels:
app: prometheus-k8s
name: prometheus-k8s
annotations:
prometheus.io/web: 'true' # 开启http 监控 # prometheus.io/tls: 'https' # 默认http # 多端口指定监控端口 prometheus.io/port: '9090'
prometheus.io/healthz: "/-/healthy" #监控url
namespace: monitoring
spec:
ports:
- name: web
port: 9090
targetPort: web
selector:
app: prometheus-k8s
sessionAffinity: ClientIP
EOF


# service 写法 tcp 模式 监控
cat << EOF | kubectl apply -f -
apiVersion: v1
kind: Service
metadata:
labels:
app: prometheus-k8s
name: prometheus-k8s
annotations:
prometheus.io/tcp: 'true' # 开启tcp 监控 所以端口都会监控
namespace: monitoring
spec:
ports:
- name: web
port: 9090
targetPort: web
selector:
app: prometheus-k8s
sessionAffinity: ClientIP
EOF


# service 写法 icmp 模式 监控
cat << EOF | kubectl apply -f -
apiVersion: v1
kind: Service
metadata:
labels:
app: prometheus-k8s
name: prometheus-k8s
annotations:
prometheus.io/icmp: 'true' # ping service name
namespace: monitoring
spec:
ports:
- name: web
port: 9090
targetPort: web
selector:
app: prometheus-k8s
sessionAffinity: ClientIP
EOF


### blackbox-exporter 集群内部ingresses监控注释方法 由于prometheus 不还不支持1.22 ingresses api 所以只能监控1.22版本一下ingresses
cat << EOF | kubectl apply -f -
kind: Ingress
apiVersion: networking.k8s.io/v1
metadata:
name: prometheus-dashboard
annotations:
prometheus.io/probed: 'true' # 开启ingresses 监控
namespace: monitoring
spec:
rules:
- host: prometheus.tycng.com
http:
paths:
- pathType: ImplementationSpecific
path: /
backend:
service:
name: prometheus-k8s
port:
number: 9090

EOF

Kubernetes 组件指标

Kubernetes自身的组件也是通过/metrics来暴露组件内部的一些指标,这样我们可以更好地了解kubernetes系统中各个组件内部发生的情况。我们可以通过 HTTP 访问组件的 /metrics 端点来获取组件的指标。有些组件默认情况下绑定在--bind-address=127.0.0.1,可以使用 --bind-address=0.0.0.0 标志启用。
这些组件的示例:(以下表格是v1.22.4版本)

组件 metrics端口 协议
kube-controller-manager 10257 https
kube-proxy 10249 http
kkube-apiserver 6443 https
kube-scheduler 10259 https
kubelet 10250 https

在生产环境中,你可能需要配置 Prometheus 服务器 或 某些其他指标搜集器以定期收集这些指标,并使它们在某种时间序列数据库中可用。

请注意,kubelet 还会在 /metrics/cadvisor/metrics/resource/metrics/probes 端点中公开度量值。这些度量值的生命周期各不相同。

组件指标

kube-controller-manager 指标

控制器管理器指标可提供有关控制器管理器性能和运行状况的重要洞察。 这些指标包括通用的 Go 语言运行时指标(例如 go_routine 数量)和控制器特定的度量指标, 例如可用于评估集群运行状况的 etcd 请求延迟或云提供商(AWS、GCE、OpenStack)的 API 延迟等。

从 Kubernetes 1.7 版本开始,详细的云提供商指标可用于 GCE、AWS、Vsphere 和 OpenStack 的存储操作。 这些指标可用于监控持久卷操作的运行状况。

比如,对于 GCE,这些指标称为:

1
2
3
4
5
6
cloudprovider_gce_api_request_duration_seconds { request = "instance_list"}
cloudprovider_gce_api_request_duration_seconds { request = "disk_insert"}
cloudprovider_gce_api_request_duration_seconds { request = "disk_delete"}
cloudprovider_gce_api_request_duration_seconds { request = "attach_disk"}
cloudprovider_gce_api_request_duration_seconds { request = "detach_disk"}
cloudprovider_gce_api_request_duration_seconds { request = "list_disk"}

kube-scheduler 指标

调度器会暴露一些可选的指标,报告所有运行中 Pods 所请求的资源和期望的约束值。 这些指标可用来构造容量规划监控面板、访问调度约束的当前或历史数据、 快速发现因为缺少资源而无法被调度的负载,或者将 Pod 的实际资源用量 与其请求值进行比较。

kube-scheduler 组件能够辩识各个 Pod 所配置的资源 请求和约束。 在 Pod 的资源请求值或者约束值非零时,kube-scheduler 会以度量值时间序列的形式 生成报告。该时间序列值包含以下标签:

  • 名字空间
  • Pod 名称
  • Pod 调度所处节点,或者当 Pod 未被调度时用空字符串表示
  • 优先级
  • 为 Pod 所指派的调度器
  • 资源的名称(例如,cpu)
  • 资源的单位,如果知道的话(例如,cores)

一旦 Pod 进入完成状态(其 restartPolicyNeverOnFailure,且 其处于 SucceededFailed Pod 阶段,或者已经被删除且所有容器都具有 终止状态),该时间序列停止报告,因为调度器现在可以调度其它 Pod 来执行。 这两个指标称作 kube_pod_resource_requestkube_pod_resource_limit。

指标暴露在 HTTP 端点 /metrics/resources,与调度器上的 /metrics 端点 一样要求相同的访问授权。你必须使用 --show-hidden-metrics-for-version=1.20 标志才能暴露那些稳定性为 Alpha 的指标。


Prometheus监控Kubernetes
https://system51.github.io/2021/12/14/prometheus-and-kubernetes/
作者
Mr.Ye
发布于
2021年12月14日
许可协议