title: 部署Prometheus监控k8s集群 #标题tags: prometheus #标签
date: 2020-09-21
categories: 监控 # 分类
记录下k8s部署Prometheus、aletermanager、node-exports、grafana及访问cAdvisor的数据。最后监控k8s集群中的各个组件,如manager、scheduler、etcd。
部署node_export
$ kubectl create ns prom # 创建名称空间
# 编写yaml文件
$ cat > node-export.yaml << EOF
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: node-exporter
namespace: prom
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: prom/node-exporter:v1.0.1
imagePullPolicy: IfNotPresent
ports:
- containerPort: 9100
resources:
requests:
cpu: 0.15
securityContext:
privileged: true
args:
- --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/master"
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
$ kubectl apply -f node-export.yaml # 执行yaml文件
$ kubectl get pods -n prom -o wide # 确认node_export运行在集群所有节点,包括master节点
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
node-exporter-nrjrr 1/1 Running 0 30h 192.168.20.3 node01 <none> <none>
node-exporter-tmlnz 1/1 Running 0 30h 192.168.20.4 node02 <none> <none>
node-exporter-v89dk 1/1 Running 0 30h 192.168.20.2 master <none> <none>
浏览器访问(任意节点IP+9100端口):
能看到以下数据,则表示正常:
配置用户获取cAvisor数据
cAdvisor是Google开源的容器资源监控和性能分析工具,它是专门为容器而生,在K8s中,我们不需要单独去安装,cAdvisor作为kubelet内置的一部分程序可以直接使用,也就是我们可以直接使用cadvisor采集数据,可以采集到和容器运行相关的所有指标。
$ kubectl create serviceaccount monitor -n prom # 创建用户
# 进行role绑定
$ kubectl create clusterrolebinding monitor-clusterrolebinding -n prom --clusterrole=cluster-admin --serviceaccount=prom:monitor
$ kubectl get secret -n prom # 查看secret
NAME TYPE DATA AGE
default-token-smhrm kubernetes.io/service-account-token 3 30h
monitor-token-lvzt9 kubernetes.io/service-account-token 3 19s
$ kubectl describe secret monitor-token-lvzt9 -n prom # 查看token
.......... # 将tocken信息复制下来
token: eyJhbGciOiJSUzI1NiIsImtpZCI6ImplanRmbkswLXFmZ1J5QXlweXR3Y0RTengwR3c5S2x6R3pPVTJVR0llWGcifQ.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJwcm9tIiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZWNyZXQubmFtZSI6Im1vbml0b3ItdG9rZW4tbHZ6dDkiLCJrdWJlcm5ldGVzLmlvL3NlcnZpY2VhY2NvdW50L3NlcnZpY2UtYWNjb3VudC5uYW1lIjoibW9uaXRvciIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VydmljZS1hY2NvdW50LnVpZCI6IjFlYjdiYjg1LTA5N2EtNGNiZS04NTg3LWJkMjRlZjEzYmI3MCIsInN1YiI6InN5c3RlbTpzZXJ2aWNlYWNjb3VudDpwcm9tOm1vbml0b3IifQ.L4AtiCKbApzYQ_tyXLfr-dZcbYMnDCWZil0hihzsl9t1EVbhywp0XaVS3ju6UTOuJ00M_JJ2U5pwcuDagReLrGexHJZ23BkDNm3vU99ruovMxRLvOHWz3491T_Rdl7TNc9s47RxD0S-JFp9-orB0NbYjKIrzCLVG0MW0W9-okTzCiN4OvF4rPssk8kbF8-ux4NU22hgf4hu_pQ5EYnzGsuEmHYBBExiWHiqBKgzX02pa3qn00L-UGJTf4TDtN1zRSQ54GO-MoiyxYBLZGpy9kCycwrwQ_SoS6ongqzoZsCO6jDPnR5KBPe283wcAahqASHgvgZSbBj7gw1a65pRSDA
# 将性能指标数据保存至文件(将token替换为你自己查看到的token)
$ curl https://127.0.0.1:10250/metrics/cadvisor -k -H "Authorization: Bearer eyJhbGciOiJSUzI1NiIsImtpZCI6ImplanRmbkswLXFmZ1J5QXlweXR3Y0RTengwR3c5S2x6R3pPVTJVR0llWGcifQ.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJwcm9tIiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZWNyZXQubmFtZSI6Im1vbml0b3ItdG9rZW4tbHZ6dDkiLCJrdWJlcm5ldGVzLmlvL3NlcnZpY2VhY2NvdW50L3NlcnZpY2UtYWNjb3VudC5uYW1lIjoibW9uaXRvciIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VydmljZS1hY2NvdW50LnVpZCI6IjFlYjdiYjg1LTA5N2EtNGNiZS04NTg3LWJkMjRlZjEzYmI3MCIsInN1YiI6InN5c3RlbTpzZXJ2aWNlYWNjb3VudDpwcm9tOm1vbml0b3IifQ.L4AtiCKbApzYQ_tyXLfr-dZcbYMnDCWZil0hihzsl9t1EVbhywp0XaVS3ju6UTOuJ00M_JJ2U5pwcuDagReLrGexHJZ23BkDNm3vU99ruovMxRLvOHWz3491T_Rdl7TNc9s47RxD0S-JFp9-orB0NbYjKIrzCLVG0MW0W9-okTzCiN4OvF4rPssk8kbF8-ux4NU22hgf4hu_pQ5EYnzGsuEmHYBBExiWHiqBKgzX02pa3qn00L-UGJTf4TDtN1zRSQ54GO-MoiyxYBLZGpy9kCycwrwQ_SoS6ongqzoZsCO6jDPnR5KBPe283wcAahqASHgvgZSbBj7gw1a65pRSDA" > metrics.txt
cadvisor性能指标数据如下:
cadvisor中获取到的典型监控指标
指标名称 | 类型 | 含义 |
---|---|---|
container_cpu_load_average_10s | gauge | 过去10秒容器CPU的平均负载 |
container_cpu_usage_seconds_total | counter | 容器在每个CPU内核上的累积占用时间 (单位:秒) |
container_cpu_system_seconds_total | counter | System CPU累积占用时间(单位:秒) |
container_cpu_user_seconds_total | counter | User CPU累积占用时间(单位:秒) |
container_fs_usage_bytes | gauge | 容器中文件系统的使用量(单位:字节) |
container_fs_limit_bytes | gauge | 容器可以使用的文件系统总量(单位:字节) |
container_fs_reads_bytes_total | counter | 容器累积读取数据的总量(单位:字节) |
container_fs_writes_bytes_total | counter | 容器累积写入数据的总量(单位:字节) |
container_memory_max_usage_bytes | gauge | 容器的最大内存使用量(单位:字节) |
container_memory_usage_bytes | gauge | 容器当前的内存使用量(单位:字节 |
container_spec_memory_limit_bytes | gauge | 容器的内存使用量限制 |
machine_memory_bytes | gauge | 当前主机的内存总量 |
container_network_receive_bytes_total | counter | 容器网络累积接收数据总量(单位:字节) |
container_network_transmit_bytes_total | counter | 容器网络累积传输数据总量(单位:字节) |
监控指标的metrices类型
监控指标有四种metrics类型,分别是 Counter, Gauge, Summary,Histogram,各个metrices类型含义如下:
- Counter计数器: 计数器统计的数据是递增的,不能使用计数器来统计可能减小的指标,计数器统计的指标是累计增加的,如http请求的总数,出现的错误总数,总的处理时间(如cpu累计使用时间),api请求总数,已完成的任务数等。
- Gauge量规: 量规是一种度量标准,代表可以任意上下波动的单个数值,
用于统计cpu使用率,内存使用率,磁盘使用率,温度等指标,还可统计上升和下降的计数,如并发请求数等。 - Histogram直方图:统计在一定的时间范围内数据的分布情况,如请求的持续/延迟时间,请求的响应大小等,还提供度量指标的总和,数据以直方图显示。
Histogram由_bucket{le=””},_bucket{le=”+Inf”}, _sum,_count 组成
如:
apiserver_request_latencies_sum
apiserver_request_latencies_count
apiserver_request_latencies_bucket - Summary摘要:和Histogram直方图类似,主要用于表示一段时间内数据采样结果(通常是请求持续时间或响应大小之类的东西),还可计算度量值的总和和度量值的分位数以及在一定时间范围内的分位数,由 {quantile=”<φ>”},_sum,_count 组成。
在上述4中metrices类型中,最常见的还是gauge和conter这两种。
部署Prometheus及altermanager
生成Prometheus配置文件
$ cat prometheus-cfg.yaml # 将Prometheus配置文件写入至configmap
# 下面的job用到了k8s的服务发现,故比较复杂,但后期维护方便
---
kind: ConfigMap
apiVersion: v1
metadata:
labels:
app: prometheus
name: prometheus-config
namespace: prom
data:
prometheus.yml: |
rule_files:
- /etc/prometheus/rules.yml
alerting:
alertmanagers:
- static_configs:
- targets: ["localhost:9093"]
global:
scrape_interval: 15s
scrape_timeout: 10s
evaluation_interval: 1m
scrape_configs:
- job_name: kubernetes-pods
kubernetes_sd_configs:
- role: pod
relabel_configs:
- action: keep
regex: true
source_labels:
- __meta_kubernetes_pod_annotation_prometheus_io_scrape
- action: replace
regex: (.+)
source_labels:
- __meta_kubernetes_pod_annotation_prometheus_io_path
target_label: __metrics_path__
- action: replace
regex: ([^:]+)(?::\d+)?;(\d+)
replacement: $1:$2
source_labels:
- __address__
- __meta_kubernetes_pod_annotation_prometheus_io_port
target_label: __address__
- action: labelmap
regex: __meta_kubernetes_pod_label_(.+)
- action: replace
source_labels:
- __meta_kubernetes_namespace
target_label: kubernetes_namespace
- action: replace
source_labels:
- __meta_kubernetes_pod_name
target_label: kubernetes_pod_name
- job_name: 'kubernetes-node'
kubernetes_sd_configs:
- role: node
relabel_configs:
- source_labels: [__address__]
regex: '(.*):10250'
replacement: '${1}:9100'
target_label: __address__
action: replace
- action: labelmap
regex: __meta_kubernetes_node_label_(.+)
- job_name: 'kubernetes-node-cadvisor'
kubernetes_sd_configs:
- role: node
scheme: https
tls_config:
ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt
bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token
relabel_configs:
- action: labelmap
regex: __meta_kubernetes_node_label_(.+)
- target_label: __address__
replacement: kubernetes.default.svc:443
- source_labels: [__meta_kubernetes_node_name]
regex: (.+)
target_label: __metrics_path__
replacement: /api/v1/nodes/${1}/proxy/metrics/cadvisor
- job_name: 'kubernetes-apiserver'
kubernetes_sd_configs:
- role: endpoints
scheme: https
tls_config:
ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt
bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token
relabel_configs:
- source_labels: [__meta_kubernetes_namespace, __meta_kubernetes_service_name, __meta_kubernetes_endpoint_port_name]
action: keep
regex: default;kubernetes;https
- job_name: 'kubernetes-service-endpoints'
kubernetes_sd_configs:
- role: endpoints
relabel_configs:
- source_labels: [__meta_kubernetes_service_annotation_prometheus_io_scrape]
action: keep
regex: true
- source_labels: [__meta_kubernetes_service_annotation_prometheus_io_scheme]
action: replace
target_label: __scheme__
regex: (https?)
- source_labels: [__meta_kubernetes_service_annotation_prometheus_io_path]
action: replace
target_label: __metrics_path__
regex: (.+)
- source_labels: [__address__, __meta_kubernetes_service_annotation_prometheus_io_port]
action: replace
target_label: __address__
regex: ([^:]+)(?::\d+)?;(\d+)
replacement: $1:$2
- action: labelmap
regex: __meta_kubernetes_service_label_(.+)
- source_labels: [__meta_kubernetes_namespace]
action: replace
target_label: kubernetes_namespace
- source_labels: [__meta_kubernetes_service_name]
action: replace
target_label: kubernetes_name
rules.yml: |
groups:
- name: example
rules:
- alert: kube-proxy的cpu使用率大于80%
expr: rate(process_cpu_seconds_total{job=~"kubernetes-kube-proxy"}[1m]) * 100 > 80
for: 2s
labels:
severity: warnning
annotations:
description: "{{$labels.instance}}的{{$labels.job}}组件的cpu使用率超过80%"
- alert: kube-proxy的cpu使用率大于90%
expr: rate(process_cpu_seconds_total{job=~"kubernetes-kube-proxy"}[1m]) * 100 > 90
for: 2s
labels:
severity: critical
annotations:
description: "{{$labels.instance}}的{{$labels.job}}组件的cpu使用率超过90%"
- alert: scheduler的cpu使用率大于80%
expr: rate(process_cpu_seconds_total{job=~"kubernetes-schedule"}[1m]) * 100 > 80
for: 2s
labels:
severity: warnning
annotations:
description: "{{$labels.instance}}的{{$labels.job}}组件的cpu使用率超过80%"
- alert: scheduler的cpu使用率大于90%
expr: rate(process_cpu_seconds_total{job=~"kubernetes-schedule"}[1m]) * 100 > 90
for: 2s
labels:
severity: critical
annotations:
description: "{{$labels.instance}}的{{$labels.job}}组件的cpu使用率超过90%"
- alert: controller-manager的cpu使用率大于80%
expr: rate(process_cpu_seconds_total{job=~"kubernetes-controller-manager"}[1m]) * 100 > 80
for: 2s
labels:
severity: warnning
annotations:
description: "{{$labels.instance}}的{{$labels.job}}组件的cpu使用率超过80%"
- alert: controller-manager的cpu使用率大于90%
expr: rate(process_cpu_seconds_total{job=~"kubernetes-controller-manager"}[1m]) * 100 > 0
for: 2s
labels:
severity: critical
annotations:
description: "{{$labels.instance}}的{{$labels.job}}组件的cpu使用率超过90%"
- alert: apiserver的cpu使用率大于80%
expr: rate(process_cpu_seconds_total{job=~"kubernetes-apiserver"}[1m]) * 100 > 80
for: 2s
labels:
severity: warnning
annotations:
description: "{{$labels.instance}}的{{$labels.job}}组件的cpu使用率超过80%"
- alert: apiserver的cpu使用率大于90%
expr: rate(process_cpu_seconds_total{job=~"kubernetes-apiserver"}[1m]) * 100 > 90
for: 2s
labels:
severity: critical
annotations:
description: "{{$labels.instance}}的{{$labels.job}}组件的cpu使用率超过90%"
- alert: etcd的cpu使用率大于80%
expr: rate(process_cpu_seconds_total{job=~"kubernetes-etcd"}[1m]) * 100 > 80
for: 2s
labels:
severity: warnning
annotations:
description: "{{$labels.instance}}的{{$labels.job}}组件的cpu使用率超过80%"
- alert: etcd的cpu使用率大于90%
expr: rate(process_cpu_seconds_total{job=~"kubernetes-etcd"}[1m]) * 100 > 90
for: 2s
labels:
severity: critical
annotations:
description: "{{$labels.instance}}的{{$labels.job}}组件的cpu使用率超过90%"
- alert: kube-state-metrics的cpu使用率大于80%
expr: rate(process_cpu_seconds_total{k8s_app=~"kube-state-metrics"}[1m]) * 100 > 80
for: 2s
labels:
severity: warnning
annotations:
description: "{{$labels.instance}}的{{$labels.k8s_app}}组件的cpu使用率超过80%"
value: "{{ $value }}%"
threshold: "80%"
- alert: kube-state-metrics的cpu使用率大于90%
expr: rate(process_cpu_seconds_total{k8s_app=~"kube-state-metrics"}[1m]) * 100 > 0
for: 2s
labels:
severity: critical
annotations:
description: "{{$labels.instance}}的{{$labels.k8s_app}}组件的cpu使用率超过90%"
value: "{{ $value }}%"
threshold: "90%"
- alert: coredns的cpu使用率大于80%
expr: rate(process_cpu_seconds_total{k8s_app=~"kube-dns"}[1m]) * 100 > 80
for: 2s
labels:
severity: warnning
annotations:
description: "{{$labels.instance}}的{{$labels.k8s_app}}组件的cpu使用率超过80%"
value: "{{ $value }}%"
threshold: "80%"
- alert: coredns的cpu使用率大于90%
expr: rate(process_cpu_seconds_total{k8s_app=~"kube-dns"}[1m]) * 100 > 90
for: 2s
labels:
severity: critical
annotations:
description: "{{$labels.instance}}的{{$labels.k8s_app}}组件的cpu使用率超过90%"
value: "{{ $value }}%"
threshold: "90%"
- alert: kube-proxy打开句柄数>600
expr: process_open_fds{job=~"kubernetes-kube-proxy"} > 600
for: 2s
labels:
severity: warnning
annotations:
description: "{{$labels.instance}}的{{$labels.job}}打开句柄数>600"
value: "{{ $value }}"
- alert: kube-proxy打开句柄数>1000
expr: process_open_fds{job=~"kubernetes-kube-proxy"} > 1000
for: 2s
labels:
severity: critical
annotations:
description: "{{$labels.instance}}的{{$labels.job}}打开句柄数>1000"
value: "{{ $value }}"
- alert: kubernetes-schedule打开句柄数>600
expr: process_open_fds{job=~"kubernetes-schedule"} > 600
for: 2s
labels:
severity: warnning
annotations:
description: "{{$labels.instance}}的{{$labels.job}}打开句柄数>600"
value: "{{ $value }}"
- alert: kubernetes-schedule打开句柄数>1000
expr: process_open_fds{job=~"kubernetes-schedule"} > 1000
for: 2s
labels:
severity: critical
annotations:
description: "{{$labels.instance}}的{{$labels.job}}打开句柄数>1000"
value: "{{ $value }}"
- alert: kubernetes-controller-manager打开句柄数>600
expr: process_open_fds{job=~"kubernetes-controller-manager"} > 600
for: 2s
labels:
severity: warnning
annotations:
description: "{{$labels.instance}}的{{$labels.job}}打开句柄数>600"
value: "{{ $value }}"
- alert: kubernetes-controller-manager打开句柄数>1000
expr: process_open_fds{job=~"kubernetes-controller-manager"} > 1000
for: 2s
labels:
severity: critical
annotations:
description: "{{$labels.instance}}的{{$labels.job}}打开句柄数>1000"
value: "{{ $value }}"
- alert: kubernetes-apiserver打开句柄数>600
expr: process_open_fds{job=~"kubernetes-apiserver"} > 600
for: 2s
labels:
severity: warnning
annotations:
description: "{{$labels.instance}}的{{$labels.job}}打开句柄数>600"
value: "{{ $value }}"
- alert: kubernetes-apiserver打开句柄数>1000
expr: process_open_fds{job=~"kubernetes-apiserver"} > 1000
for: 2s
labels:
severity: critical
annotations:
description: "{{$labels.instance}}的{{$labels.job}}打开句柄数>1000"
value: "{{ $value }}"
- alert: kubernetes-etcd打开句柄数>600
expr: process_open_fds{job=~"kubernetes-etcd"} > 600
for: 2s
labels:
severity: warnning
annotations:
description: "{{$labels.instance}}的{{$labels.job}}打开句柄数>600"
value: "{{ $value }}"
- alert: kubernetes-etcd打开句柄数>1000
expr: process_open_fds{job=~"kubernetes-etcd"} > 1000
for: 2s
labels:
severity: critical
annotations:
description: "{{$labels.instance}}的{{$labels.job}}打开句柄数>1000"
value: "{{ $value }}"
- alert: coredns
expr: process_open_fds{k8s_app=~"kube-dns"} > 600
for: 2s
labels:
severity: warnning
annotations:
description: "插件{{$labels.k8s_app}}({{$labels.instance}}): 打开句柄数超过600"
value: "{{ $value }}"
- alert: coredns
expr: process_open_fds{k8s_app=~"kube-dns"} > 1000
for: 2s
labels:
severity: critical
annotations:
description: "插件{{$labels.k8s_app}}({{$labels.instance}}): 打开句柄数超过1000"
value: "{{ $value }}"
- alert: kube-proxy
expr: process_virtual_memory_bytes{job=~"kubernetes-kube-proxy"} > 2000000000
for: 2s
labels:
severity: warnning
annotations:
description: "组件{{$labels.job}}({{$labels.instance}}): 使用虚拟内存超过2G"
value: "{{ $value }}"
- alert: scheduler
expr: process_virtual_memory_bytes{job=~"kubernetes-schedule"} > 2000000000
for: 2s
labels:
severity: warnning
annotations:
description: "组件{{$labels.job}}({{$labels.instance}}): 使用虚拟内存超过2G"
value: "{{ $value }}"
- alert: kubernetes-controller-manager
expr: process_virtual_memory_bytes{job=~"kubernetes-controller-manager"} > 2000000000
for: 2s
labels:
severity: warnning
annotations:
description: "组件{{$labels.job}}({{$labels.instance}}): 使用虚拟内存超过2G"
value: "{{ $value }}"
- alert: kubernetes-apiserver
expr: process_virtual_memory_bytes{job=~"kubernetes-apiserver"} > 2000000000
for: 2s
labels:
severity: warnning
annotations:
description: "组件{{$labels.job}}({{$labels.instance}}): 使用虚拟内存超过2G"
value: "{{ $value }}"
- alert: kubernetes-etcd
expr: process_virtual_memory_bytes{job=~"kubernetes-etcd"} > 2000000000
for: 2s
labels:
severity: warnning
annotations:
description: "组件{{$labels.job}}({{$labels.instance}}): 使用虚拟内存超过2G"
value: "{{ $value }}"
- alert: kube-dns
expr: process_virtual_memory_bytes{k8s_app=~"kube-dns"} > 2000000000
for: 2s
labels:
severity: warnning
annotations:
description: "插件{{$labels.k8s_app}}({{$labels.instance}}): 使用虚拟内存超过2G"
value: "{{ $value }}"
- alert: HttpRequestsAvg
expr: sum(rate(rest_client_requests_total{job=~"kubernetes-kube-proxy|kubernetes-kubelet|kubernetes-schedule|kubernetes-control-manager|kubernetes-apiservers"}[1m])) > 1000
for: 2s
labels:
severity: critical
annotations:
description: "组件{{$labels.job}}({{$labels.instance}}): TPS超过1000"
value: "{{ $value }}"
threshold: "1000"
- alert: Pod_waiting
expr: kube_pod_container_status_waiting_reason{namespace=~"kube-system|default"} == 1
for: 2s
labels:
severity: critical
annotations:
description: "空间{{$labels.namespace}}({{$labels.instance}}): 发现{{$labels.pod}}下的{{$labels.container}}启动异常等待中"
value: "{{ $value }}"
threshold: "1"
- alert: Pod_terminated
expr: kube_pod_container_status_terminated_reason{namespace=~"kube-system|default|prom"} == 1
for: 2s
labels:
severity: critical
annotations:
description: "空间{{$labels.namespace}}({{$labels.instance}}): 发现{{$labels.pod}}下的{{$labels.container}}被删除"
value: "{{ $value }}"
threshold: "1"
- alert: Etcd_leader
expr: etcd_server_has_leader{job="kubernetes-etcd"} == 0
for: 2s
labels:
severity: critical
annotations:
description: "组件{{$labels.job}}({{$labels.instance}}): 当前没有leader"
value: "{{ $value }}"
threshold: "0"
- alert: Etcd_leader_changes
expr: rate(etcd_server_leader_changes_seen_total{job="kubernetes-etcd"}[1m]) > 0
for: 2s
labels:
severity: critical
annotations:
description: "组件{{$labels.job}}({{$labels.instance}}): 当前leader已发生改变"
value: "{{ $value }}"
threshold: "0"
- alert: Etcd_failed
expr: rate(etcd_server_proposals_failed_total{job="kubernetes-etcd"}[1m]) > 0
for: 2s
labels:
severity: critical
annotations:
description: "组件{{$labels.job}}({{$labels.instance}}): 服务失败"
value: "{{ $value }}"
threshold: "0"
- alert: Etcd_db_total_size
expr: etcd_debugging_mvcc_db_total_size_in_bytes{job="kubernetes-etcd"} > 10000000000
for: 2s
labels:
severity: critical
annotations:
description: "组件{{$labels.job}}({{$labels.instance}}):db空间超过10G"
value: "{{ $value }}"
threshold: "10G"
- alert: Endpoint_ready
expr: kube_endpoint_address_not_ready{namespace=~"kube-system|default"} == 1
for: 2s
labels:
severity: critical
annotations:
description: "空间{{$labels.namespace}}({{$labels.instance}}): 发现{{$labels.endpoint}}不可用"
value: "{{ $value }}"
threshold: "1"
- name: 物理节点状态-监控告警
rules:
- alert: 物理节点cpu使用率
expr: 100-avg(irate(node_cpu_seconds_total{mode="idle"}[5m])) by(instance)*100 > 90
for: 2s
labels:
severity: critical
annotations:
summary: "{{ $labels.instance }}cpu使用率过高"
description: "{{ $labels.instance }}的cpu使用率超过90%,当前使用率[{{ $value }}],需要排查处理"
- alert: 物理节点内存使用率
expr: (node_memory_MemTotal_bytes - (node_memory_MemFree_bytes + node_memory_Buffers_bytes + node_memory_Cached_bytes)) / node_memory_MemTotal_bytes * 100 > 90
for: 2s
labels:
severity: critical
annotations:
summary: "{{ $labels.instance }}内存使用率过高"
description: "{{ $labels.instance }}的内存使用率超过90%,当前使用率[{{ $value }}],需要排查处理"
- alert: InstanceDown
expr: up == 0
for: 2s
labels:
severity: critical
annotations:
summary: "{{ $labels.instance }}: 服务器宕机"
description: "{{ $labels.instance }}: 服务器延时超过2分钟"
- alert: 物理节点磁盘的IO性能
expr: 100-(avg(irate(node_disk_io_time_seconds_total[1m])) by(instance)* 100) < 60
for: 2s
labels:
severity: critical
annotations:
summary: "{{$labels.mountpoint}} 流入磁盘IO使用率过高!"
description: "{{$labels.mountpoint }} 流入磁盘IO大于60%(目前使用:{{$value}})"
- alert: 入网流量带宽
expr: ((sum(rate (node_network_receive_bytes_total{device!~'tap.*|veth.*|br.*|docker.*|virbr*|lo*'}[5m])) by (instance)) / 100) > 102400
for: 2s
labels:
severity: critical
annotations:
summary: "{{$labels.mountpoint}} 流入网络带宽过高!"
description: "{{$labels.mountpoint }}流入网络带宽持续5分钟高于100M. RX带宽使用率{{$value}}"
- alert: 出网流量带宽
expr: ((sum(rate (node_network_transmit_bytes_total{device!~'tap.*|veth.*|br.*|docker.*|virbr*|lo*'}[5m])) by (instance)) / 100) > 102400
for: 2s
labels:
severity: critical
annotations:
summary: "{{$labels.mountpoint}} 流出网络带宽过高!"
description: "{{$labels.mountpoint }}流出网络带宽持续5分钟高于100M. RX带宽使用率{{$value}}"
- alert: TCP会话
expr: node_netstat_Tcp_CurrEstab > 1000
for: 2s
labels:
severity: critical
annotations:
summary: "{{$labels.mountpoint}} TCP_ESTABLISHED过高!"
description: "{{$labels.mountpoint }} TCP_ESTABLISHED大于1000%(目前使用:{{$value}}%)"
- alert: 磁盘容量
expr: 100-(node_filesystem_free_bytes{fstype=~"ext4|xfs"}/node_filesystem_size_bytes {fstype=~"ext4|xfs"}*100) > 80
for: 2s
labels:
severity: critical
annotations:
summary: "{{$labels.mountpoint}} 磁盘分区使用率过高!"
description: "{{$labels.mountpoint }} 磁盘分区使用大于80%(目前使用:{{$value}}%)"
生成alertmanager配置文件
$ cat >alertmanager-cm.yaml <<EOF
kind: ConfigMap
apiVersion: v1
metadata:
name: alertmanager
namespace: prom
data:
alertmanager.yml: |-
global:
resolve_timeout: 1m
smtp_smarthost: 'smtp.163.com:25'
smtp_from: 'lv916551516@163.com'
smtp_auth_username: 'lv916551516@163.com'
smtp_auth_password: 'QKRIUAMMLHGGYEGB'
smtp_require_tls: false
route:
group_by: [alertname]
group_wait: 10s
group_interval: 10s
repeat_interval: 10m
receiver: default-receiver
receivers:
- name: 'default-receiver'
email_configs:
- to: '916551516@qq.com' # 发送至哪个邮箱
send_resolved: true # 当告警恢复后,发送一份告警恢复的邮件
EOF
准备部署文件
$ cat prometheus-deploy.yaml # 准备Prometheus部署的yaml文件
# Prometheus的数据存储方式我这里为了方便,采用了hostpath,并且指定了主机节点名称
# 如果是用来生产环境,此方式不太合适,建议采用nfs或ceph
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: prometheus-server
namespace: prom
labels:
app: prometheus
spec:
replicas: 1
selector:
matchLabels:
app: prometheus
component: server
#matchExpressions:
#- {key: app, operator: In, values: [prometheus]}
#- {key: component, operator: In, values: [server]}
template:
metadata:
labels:
app: prometheus
component: server
annotations:
prometheus.io/scrape: 'false'
spec:
nodeName: node02 # 将此处的node02改为你集群的任意node节点(不建议是master节点)
serviceAccountName: monitor # 此处指定的是上面访问cAvisor时创建的用户
containers:
- name: prometheus
image: prom/prometheus:v2.20.1
imagePullPolicy: IfNotPresent
command:
- prometheus
- --config.file=/etc/prometheus/prometheus.yml
- --storage.tsdb.path=/prometheus
- --storage.tsdb.retention=30d
- --web.enable-lifecycle
ports:
- containerPort: 9090
protocol: TCP
volumeMounts:
- mountPath: /etc/prometheus
name: prometheus-config
- mountPath: /prometheus/
name: prometheus-storage-volume
- name: localtime
mountPath: /etc/localtime
- name: alertmanager
image: prom/alertmanager:v0.21.0
imagePullPolicy: IfNotPresent
args:
- "--config.file=/etc/alertmanager/alertmanager.yml"
- "--log.level=info"
ports:
- containerPort: 9093
protocol: TCP
name: alertmanager
volumeMounts:
- name: alertmanager-config
mountPath: /etc/alertmanager
- name: alertmanager-storage
mountPath: /alertmanager
- name: localtime
mountPath: /etc/localtime
volumes:
- name: prometheus-config
configMap:
name: prometheus-config
- name: prometheus-storage-volume
hostPath:
path: /data
type: Directory
- name: alertmanager-config
configMap:
name: alertmanager
- name: alertmanager-storage
hostPath:
path: /data/alertmanager
type: DirectoryOrCreate
- name: localtime
hostPath:
path: /usr/share/zoneinfo/Asia/Shanghai
---
apiVersion: v1
kind: Service
metadata:
name: prometheus
namespace: prom
labels:
app: prometheus
spec:
type: NodePort
ports:
- port: 9090
targetPort: 9090
nodePort: 30090
protocol: TCP
selector:
app: prometheus
component: server
---
apiVersion: v1
kind: Service
metadata:
labels:
name: prometheus
kubernetes.io/cluster-service: 'true'
name: alertmanager
namespace: prom
spec:
ports:
- name: alertmanager
nodePort: 30066
port: 9093
protocol: TCP
targetPort: 9093
selector:
app: prometheus
sessionAffinity: None
type: NodePort
# 在node02机器上创建pod将要挂载的目录并赋予权限
$ mkdir /data
$ chown 65534.65534 /data # prometheus默认以id为 65534的用户运行,需要调整这个目录的属主,否则容器无法启动
# 执行yaml文件(回到master节点)
$ kubectl apply -f prometheus-cfg.yaml
kubectl apply -f alertmanager-cm.yaml
kubectl apply -f prometheus-deploy.yaml
访问Prometheus
访问地址; k8s集群中任意节点IP+30090
根据上面提示点击后,看到如下,都为“UP”则表示部署完成:
访问altermanager
访问任意节点IP+30066端口,看到如下页面即可:
部署grafana
参考博文: k8s之安装配置grafana。
监控kube-schedule组件
此处将写下动态和静态发现两种配置。自行选择即可。
基于endpoints的动态发现
因为在配置Prometheus时,已经配置了基于endpoint的服务发现,所以我们只需要给kube-scheduler创建一个service,那么Prometheus自然就可以将其监控到。
$ cat > kube-scheduler-service.yaml << EOF
apiVersion: v1
kind: Service
metadata:
annotations: # 想要Prometheus监控到此service,下面两个注解是不可或缺的。
prometheus.io/port: "32107"
prometheus.io/scrape: "true"
labels:
component: kube-scheduler
tier: control-plane
name: kube-scheduler
namespace: kube-system
spec:
clusterIP:
ports:
- name: metrics
port: 10251
protocol: TCP
targetPort: 10251
nodePort: 32107
selector:
component: kube-scheduler
tier: control-plane
type: NodePort
EOF
# 创建service
$ kubectl apply -f kube-scheduler-service.yaml
经过上述配置后,稍等两三秒,刷新Prometheus的target页面,即可看到类似下面的页面,已经将kube-scheduler添加到了监控列表中。
基于静态配置监控kube-scheduler
如果做了动态发现kube-scheduler的步骤,请自行删除kube-cheduler的service,否则会获取到重复数据。
$ cat prometheus-cfg.yaml # 配置文件中追加以下配置
# 请将targets中的IP换成你自己的kube-scheduler所在节点的IP
............ # 省略部分配置
- job_name: 'kubernetes-schedule'
scrape_interval: 5s
static_configs:
- targets: ['192.168.20.2:10251']
# 重新生成Prometheus配置文件
$ kubectl apply -f prometheus-cfg.yaml
# 重新创建容器
$ kubectl delete -f prometheus.yaml
$ kubectl apply -f prometheus.yaml
然后查看Prometheus的target列表,看到以下配置,就说明配置无误。
监控kube-controller-manager组件
同样写下动态和静态两种配置方式。
基于endpoints的动态发现
# 编写service配置文件
$ cat > kube-controller-manager.yaml << EOF
apiVersion: v1
kind: Service
metadata:
annotations: # 同样,以下两个注解是必不可少的
prometheus.io/port: "32108"
prometheus.io/scrape: "true"
labels:
component: kube-controller-manager
tier: control-plane
name: kube-controller
namespace: kube-system
spec:
clusterIP:
ports:
- name: metrics
port: 10252
protocol: TCP
targetPort: 10252
nodePort: 32108
selector:
component: kube-controller-manager
tier: control-plane
type: NodePort
EOF
# 上述中的targetPort指定的端口,就是kube-controller-manager监听的端口
# 你可以在master上执行以下命令,确认下
$ ss -lnput | grep kube-controller
tcp LISTEN 0 128 127.0.0.1:10257 *:* users:(("kube-controller",pid=7906,fd=6))
tcp LISTEN 0 128 [::]:10252 [::]:* users:(("kube-controller",pid=7906,fd=5))
# 创建service
$ kubectl apply -f kube-controller-manager.yaml
稍等几秒钟,Prometheus看到如下,即表示监控到了kube-controller-manager。
基于静态配置监控kube-controller-manager
如果做了动态发现kube-controller-manager的步骤,请自行删除kube-controller-manager的service,否则会获取到重复数据。
$ cat prometheus-cfg.yaml # 配置文件中追加以下配置
# 请将targets中的IP换成你自己的kube-scheduler所在节点的IP
............ # 省略部分配置
- job_name: 'kubernetes-controller-manager'
scrape_interval: 5s
static_configs:
- targets: ['192.168.20.2:10252']
# 重新生成Prometheus配置文件
$ kubectl apply -f prometheus-cfg.yaml
# 重新创建容器
$ kubectl delete -f prometheus.yaml
$ kubectl apply -f prometheus.yaml
查看target列表如下:
监控kube-proxy组件
kube-proxy默认监听的地址是127.0.0.1:10249,想要修改监听的端口,需进行以下操作:
$ kubectl edit configmap kube-proxy -n kube-system
# 修改如下
metricsBindAddress: "0.0.0.0:10249"
# 重启pod
$ kubectl get pods -n kube-system | grep kube-proxy |awk '{print $1}' | xargs kubectl delete pods -n kube-system
# 确定本机10249端口在监听
$ ss -antulp |grep :10249
tcp LISTEN 0 128 [::]:10249 [::]:* users:(("kube-proxy",pid=32899,fd=17))
配置Prometheus
$ vim prometheus-cfg.yaml # 新增以下配置
# targets列表中指定的是k8s集群中每个节点上proxy监听的地址
- job_name: 'kubernetes-kube-proxy'
scrape_interval: 5s
static_configs:
- targets: ['192.168.20.2:10249','192.168.20.3:10249','192.168.20.4:10249']
$ kubectl apply -f prometheus-cfg.yaml
至此,自行重启Prometheus后,即可在target列表看到kube-pory已经被监控到了,如下:
监控etcd组件
# 在k8s-master节点建secret,将需要的etcd证书保存到secret对象etcd-certs中:
$ kubectl -n prom create secret generic etcd-certs \
--from-file=/etc/kubernetes/pki/etcd/server.key \
--from-file=/etc/kubernetes/pki/etcd/server.crt \
--from-file=/etc/kubernetes/pki/etcd/ca.crt
# 查看创建的secret
$ kubectl get secret -n prom|grep etcd-certs
etcd-certs Opaque 3 60s
# 修改Prometheus-deploy.yaml文件
# 主要是将创建的secret通过volume挂载到Prometheus容器中,如下:
$ vim prometheus-deploy.yaml
# 在volumeMounts字段下新增如下:
- name: k8s-certs
mountPath: /var/run/secrets/kubernetes.io/k8s-certs/etcd/
# 在volumes字段新增如下:
- name: k8s-certs
secret:
secretName: etcd-certs
# 修改prometheus-cfg.yaml文件,增加如下job:
$ vim prometheus-cfg.yaml
........... # 省略部分内容
- job_name: 'kubernetes-etcd'
scheme: https
tls_config:
ca_file: /var/run/secrets/kubernetes.io/k8s-certs/etcd/ca.crt
cert_file: /var/run/secrets/kubernetes.io/k8s-certs/etcd/server.crt
key_file: /var/run/secrets/kubernetes.io/k8s-certs/etcd/server.key
scrape_interval: 5s
static_configs:
- targets: ['192.168.20.2:2379']
# 重启Prometheus
$ kubectl delete -f prometheus-deploy.yaml
$ kubectl apply -f prometheus-deploy.yaml
注意,可能会遇到如下错误:
# 启动问题:
level=info ts=2020-09-21T15:39:18.938Z caller=main.go:755 msg="Notifier manager stopped"
level=error ts=2020-09-21T15:39:18.938Z caller=main.go:764 err="opening storage failed: lock DB directory: resource temporarily unavailable"
# 解决:删除 lock 文件
$ rm -f /opt/prometheus/data/lock
最后,访问target列表,看到etcd的job列表,即表示成功,如下:
部署kube-state-metrics
Kube-state-metrics通过监听API Server生成有关资源对象的状态指标,比如Deployment、Node、Pod,需要注意的是kube-state-metrics只是简单的提供一个metrics数据,并不会存储这些指标数据,所以我们可以使用Prometheus来抓取这些数据然后存储,主要关注的是业务相关的一些元数据,比如Deployment、Pod、副本状态等,调度了多少个replicas?现在可用的有几个?多少个Pod是running/stopped/terminated状态?Pod重启了多少次?多少job在运行中等等。
参考: 官方文档
# 创建deployment文件
$ cat > kube-state-metrics-deploy.yaml <<EOF
apiVersion: apps/v1
kind: Deployment
metadata:
name: kube-state-metrics
namespace: kube-system
spec:
replicas: 1
selector:
matchLabels:
app: kube-state-metrics
template:
metadata:
labels:
app: kube-state-metrics
spec:
serviceAccountName: kube-state-metrics
containers:
- name: kube-state-metrics
# image: gcr.io/google_containers/kube-state-metrics-amd64:v1.3.1
image: quay.io/coreos/kube-state-metrics:v1.9.0
ports:
- containerPort: 8080
EOF
$ 创建授权账户
$ cat > kube-state-metrics-rbac.yaml <<EOF
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: kube-state-metrics
namespace: kube-system
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: kube-state-metrics
rules:
- apiGroups: [""]
resources: ["nodes", "pods", "services", "resourcequotas", "replicationcontrollers", "limitranges", "persistentvolumeclaims", "persistentvolumes", "namespaces", "endpoints"]
verbs: ["list", "watch"]
- apiGroups: ["extensions"]
resources: ["daemonsets", "deployments", "replicasets"]
verbs: ["list", "watch"]
- apiGroups: ["apps"]
resources: ["statefulsets"]
verbs: ["list", "watch"]
- apiGroups: ["batch"]
resources: ["cronjobs", "jobs"]
verbs: ["list", "watch"]
- apiGroups: ["autoscaling"]
resources: ["horizontalpodautoscalers"]
verbs: ["list", "watch"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: kube-state-metrics
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: kube-state-metrics
subjects:
- kind: ServiceAccount
name: kube-state-metrics
namespace: kube-system
EOF
# 创建service
$ cat > kube-state-metrics-svc.yaml <<EOF
apiVersion: v1
kind: Service
metadata:
annotations:
prometheus.io/scrape: 'true'
name: kube-state-metrics
namespace: kube-system
labels:
app: kube-state-metrics
spec:
ports:
- name: kube-state-metrics
port: 8080
protocol: TCP
selector:
app: kube-state-metrics
EOF
# 创建资源对象
$ kubectl apply -f kube-state-metrics-rbac.yaml
$ kubectl apply -f kube-state-metrics-deploy.yaml
$ kubectl apply -f kube-state-metrics-svc.yaml
在Prometheus的target列表中可以看到如下,则表明数据采集正常:
其中,以kube_
开头的,都是此容器采集到的。如下:
基于pod的k8s服务发现
在上面部署Prometheus时,我们定义了如下字段:
上述配置是用于自动发现pod的,现在我们编辑Prometheus这个pods,使其可以自己发现自己,编辑如下:
$ kubectl edit pod prometheus-server-fc59797f6-296ld -n prom
apiVersion: v1
kind: Pod
metadata:
annotations:
cni.projectcalico.org/podIP: 10.100.140.88/32
cni.projectcalico.org/podIPs: 10.100.140.88/32
prometheus.io/scrape: "true" # 将此处的false改为true即可
........ # 省略部分内容
然后查看Prometheus的target列表,看到如下即表示成功发现pod: