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 << EOFapiVersion: apps/v1kind: DaemonSetmetadata:name: node-exporternamespace: promlabels:name: node-exporterspec:selector:matchLabels:name: node-exportertemplate:metadata:labels:name: node-exporterspec:hostPID: truehostIPC: truehostNetwork: truecontainers:- name: node-exporterimage: prom/node-exporter:v1.0.1imagePullPolicy: IfNotPresentports:- containerPort: 9100resources:requests:cpu: 0.15securityContext:privileged: trueargs:- --path.procfs- /host/proc- --path.sysfs- /host/sys- --collector.filesystem.ignored-mount-points- '"^/(sys|proc|dev|host|etc)($|/)"'volumeMounts:- name: devmountPath: /host/dev- name: procmountPath: /host/proc- name: sysmountPath: /host/sys- name: rootfsmountPath: /rootfstolerations:- key: "node-role.kubernetes.io/master"operator: "Exists"effect: "NoSchedule"volumes:- name: prochostPath:path: /proc- name: devhostPath:path: /dev- name: syshostPath:path: /sys- name: rootfshostPath: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 GATESnode-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 # 查看secretNAME TYPE DATA AGEdefault-token-smhrm kubernetes.io/service-account-token 3 30hmonitor-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: ConfigMapapiVersion: v1metadata:labels:app: prometheusname: prometheus-confignamespace: promdata:prometheus.yml: |rule_files:- /etc/prometheus/rules.ymlalerting:alertmanagers:- static_configs:- targets: ["localhost:9093"]global:scrape_interval: 15sscrape_timeout: 10sevaluation_interval: 1mscrape_configs:- job_name: kubernetes-podskubernetes_sd_configs:- role: podrelabel_configs:- action: keepregex: truesource_labels:- __meta_kubernetes_pod_annotation_prometheus_io_scrape- action: replaceregex: (.+)source_labels:- __meta_kubernetes_pod_annotation_prometheus_io_pathtarget_label: __metrics_path__- action: replaceregex: ([^:]+)(?::\d+)?;(\d+)replacement: $1:$2source_labels:- __address__- __meta_kubernetes_pod_annotation_prometheus_io_porttarget_label: __address__- action: labelmapregex: __meta_kubernetes_pod_label_(.+)- action: replacesource_labels:- __meta_kubernetes_namespacetarget_label: kubernetes_namespace- action: replacesource_labels:- __meta_kubernetes_pod_nametarget_label: kubernetes_pod_name- job_name: 'kubernetes-node'kubernetes_sd_configs:- role: noderelabel_configs:- source_labels: [__address__]regex: '(.*):10250'replacement: '${1}:9100'target_label: __address__action: replace- action: labelmapregex: __meta_kubernetes_node_label_(.+)- job_name: 'kubernetes-node-cadvisor'kubernetes_sd_configs:- role: nodescheme: httpstls_config:ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crtbearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/tokenrelabel_configs:- action: labelmapregex: __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: endpointsscheme: httpstls_config:ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crtbearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/tokenrelabel_configs:- source_labels: [__meta_kubernetes_namespace, __meta_kubernetes_service_name, __meta_kubernetes_endpoint_port_name]action: keepregex: default;kubernetes;https- job_name: 'kubernetes-service-endpoints'kubernetes_sd_configs:- role: endpointsrelabel_configs:- source_labels: [__meta_kubernetes_service_annotation_prometheus_io_scrape]action: keepregex: true- source_labels: [__meta_kubernetes_service_annotation_prometheus_io_scheme]action: replacetarget_label: __scheme__regex: (https?)- source_labels: [__meta_kubernetes_service_annotation_prometheus_io_path]action: replacetarget_label: __metrics_path__regex: (.+)- source_labels: [__address__, __meta_kubernetes_service_annotation_prometheus_io_port]action: replacetarget_label: __address__regex: ([^:]+)(?::\d+)?;(\d+)replacement: $1:$2- action: labelmapregex: __meta_kubernetes_service_label_(.+)- source_labels: [__meta_kubernetes_namespace]action: replacetarget_label: kubernetes_namespace- source_labels: [__meta_kubernetes_service_name]action: replacetarget_label: kubernetes_namerules.yml: |groups:- name: examplerules:- alert: kube-proxy的cpu使用率大于80%expr: rate(process_cpu_seconds_total{job=~"kubernetes-kube-proxy"}[1m]) * 100 > 80for: 2slabels:severity: warnningannotations:description: "{{$labels.instance}}的{{$labels.job}}组件的cpu使用率超过80%"- alert: kube-proxy的cpu使用率大于90%expr: rate(process_cpu_seconds_total{job=~"kubernetes-kube-proxy"}[1m]) * 100 > 90for: 2slabels:severity: criticalannotations:description: "{{$labels.instance}}的{{$labels.job}}组件的cpu使用率超过90%"- alert: scheduler的cpu使用率大于80%expr: rate(process_cpu_seconds_total{job=~"kubernetes-schedule"}[1m]) * 100 > 80for: 2slabels:severity: warnningannotations:description: "{{$labels.instance}}的{{$labels.job}}组件的cpu使用率超过80%"- alert: scheduler的cpu使用率大于90%expr: rate(process_cpu_seconds_total{job=~"kubernetes-schedule"}[1m]) * 100 > 90for: 2slabels:severity: criticalannotations:description: "{{$labels.instance}}的{{$labels.job}}组件的cpu使用率超过90%"- alert: controller-manager的cpu使用率大于80%expr: rate(process_cpu_seconds_total{job=~"kubernetes-controller-manager"}[1m]) * 100 > 80for: 2slabels:severity: warnningannotations:description: "{{$labels.instance}}的{{$labels.job}}组件的cpu使用率超过80%"- alert: controller-manager的cpu使用率大于90%expr: rate(process_cpu_seconds_total{job=~"kubernetes-controller-manager"}[1m]) * 100 > 0for: 2slabels:severity: criticalannotations:description: "{{$labels.instance}}的{{$labels.job}}组件的cpu使用率超过90%"- alert: apiserver的cpu使用率大于80%expr: rate(process_cpu_seconds_total{job=~"kubernetes-apiserver"}[1m]) * 100 > 80for: 2slabels:severity: warnningannotations:description: "{{$labels.instance}}的{{$labels.job}}组件的cpu使用率超过80%"- alert: apiserver的cpu使用率大于90%expr: rate(process_cpu_seconds_total{job=~"kubernetes-apiserver"}[1m]) * 100 > 90for: 2slabels:severity: criticalannotations:description: "{{$labels.instance}}的{{$labels.job}}组件的cpu使用率超过90%"- alert: etcd的cpu使用率大于80%expr: rate(process_cpu_seconds_total{job=~"kubernetes-etcd"}[1m]) * 100 > 80for: 2slabels:severity: warnningannotations:description: "{{$labels.instance}}的{{$labels.job}}组件的cpu使用率超过80%"- alert: etcd的cpu使用率大于90%expr: rate(process_cpu_seconds_total{job=~"kubernetes-etcd"}[1m]) * 100 > 90for: 2slabels:severity: criticalannotations: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 > 80for: 2slabels:severity: warnningannotations: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 > 0for: 2slabels:severity: criticalannotations: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 > 80for: 2slabels:severity: warnningannotations: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 > 90for: 2slabels:severity: criticalannotations:description: "{{$labels.instance}}的{{$labels.k8s_app}}组件的cpu使用率超过90%"value: "{{ $value }}%"threshold: "90%"- alert: kube-proxy打开句柄数>600expr: process_open_fds{job=~"kubernetes-kube-proxy"} > 600for: 2slabels:severity: warnningannotations:description: "{{$labels.instance}}的{{$labels.job}}打开句柄数>600"value: "{{ $value }}"- alert: kube-proxy打开句柄数>1000expr: process_open_fds{job=~"kubernetes-kube-proxy"} > 1000for: 2slabels:severity: criticalannotations:description: "{{$labels.instance}}的{{$labels.job}}打开句柄数>1000"value: "{{ $value }}"- alert: kubernetes-schedule打开句柄数>600expr: process_open_fds{job=~"kubernetes-schedule"} > 600for: 2slabels:severity: warnningannotations:description: "{{$labels.instance}}的{{$labels.job}}打开句柄数>600"value: "{{ $value }}"- alert: kubernetes-schedule打开句柄数>1000expr: process_open_fds{job=~"kubernetes-schedule"} > 1000for: 2slabels:severity: criticalannotations:description: "{{$labels.instance}}的{{$labels.job}}打开句柄数>1000"value: "{{ $value }}"- alert: kubernetes-controller-manager打开句柄数>600expr: process_open_fds{job=~"kubernetes-controller-manager"} > 600for: 2slabels:severity: warnningannotations:description: "{{$labels.instance}}的{{$labels.job}}打开句柄数>600"value: "{{ $value }}"- alert: kubernetes-controller-manager打开句柄数>1000expr: process_open_fds{job=~"kubernetes-controller-manager"} > 1000for: 2slabels:severity: criticalannotations:description: "{{$labels.instance}}的{{$labels.job}}打开句柄数>1000"value: "{{ $value }}"- alert: kubernetes-apiserver打开句柄数>600expr: process_open_fds{job=~"kubernetes-apiserver"} > 600for: 2slabels:severity: warnningannotations:description: "{{$labels.instance}}的{{$labels.job}}打开句柄数>600"value: "{{ $value }}"- alert: kubernetes-apiserver打开句柄数>1000expr: process_open_fds{job=~"kubernetes-apiserver"} > 1000for: 2slabels:severity: criticalannotations:description: "{{$labels.instance}}的{{$labels.job}}打开句柄数>1000"value: "{{ $value }}"- alert: kubernetes-etcd打开句柄数>600expr: process_open_fds{job=~"kubernetes-etcd"} > 600for: 2slabels:severity: warnningannotations:description: "{{$labels.instance}}的{{$labels.job}}打开句柄数>600"value: "{{ $value }}"- alert: kubernetes-etcd打开句柄数>1000expr: process_open_fds{job=~"kubernetes-etcd"} > 1000for: 2slabels:severity: criticalannotations:description: "{{$labels.instance}}的{{$labels.job}}打开句柄数>1000"value: "{{ $value }}"- alert: corednsexpr: process_open_fds{k8s_app=~"kube-dns"} > 600for: 2slabels:severity: warnningannotations:description: "插件{{$labels.k8s_app}}({{$labels.instance}}): 打开句柄数超过600"value: "{{ $value }}"- alert: corednsexpr: process_open_fds{k8s_app=~"kube-dns"} > 1000for: 2slabels:severity: criticalannotations:description: "插件{{$labels.k8s_app}}({{$labels.instance}}): 打开句柄数超过1000"value: "{{ $value }}"- alert: kube-proxyexpr: process_virtual_memory_bytes{job=~"kubernetes-kube-proxy"} > 2000000000for: 2slabels:severity: warnningannotations:description: "组件{{$labels.job}}({{$labels.instance}}): 使用虚拟内存超过2G"value: "{{ $value }}"- alert: schedulerexpr: process_virtual_memory_bytes{job=~"kubernetes-schedule"} > 2000000000for: 2slabels:severity: warnningannotations:description: "组件{{$labels.job}}({{$labels.instance}}): 使用虚拟内存超过2G"value: "{{ $value }}"- alert: kubernetes-controller-managerexpr: process_virtual_memory_bytes{job=~"kubernetes-controller-manager"} > 2000000000for: 2slabels:severity: warnningannotations:description: "组件{{$labels.job}}({{$labels.instance}}): 使用虚拟内存超过2G"value: "{{ $value }}"- alert: kubernetes-apiserverexpr: process_virtual_memory_bytes{job=~"kubernetes-apiserver"} > 2000000000for: 2slabels:severity: warnningannotations:description: "组件{{$labels.job}}({{$labels.instance}}): 使用虚拟内存超过2G"value: "{{ $value }}"- alert: kubernetes-etcdexpr: process_virtual_memory_bytes{job=~"kubernetes-etcd"} > 2000000000for: 2slabels:severity: warnningannotations:description: "组件{{$labels.job}}({{$labels.instance}}): 使用虚拟内存超过2G"value: "{{ $value }}"- alert: kube-dnsexpr: process_virtual_memory_bytes{k8s_app=~"kube-dns"} > 2000000000for: 2slabels:severity: warnningannotations:description: "插件{{$labels.k8s_app}}({{$labels.instance}}): 使用虚拟内存超过2G"value: "{{ $value }}"- alert: HttpRequestsAvgexpr: sum(rate(rest_client_requests_total{job=~"kubernetes-kube-proxy|kubernetes-kubelet|kubernetes-schedule|kubernetes-control-manager|kubernetes-apiservers"}[1m])) > 1000for: 2slabels:severity: criticalannotations:description: "组件{{$labels.job}}({{$labels.instance}}): TPS超过1000"value: "{{ $value }}"threshold: "1000"- alert: Pod_waitingexpr: kube_pod_container_status_waiting_reason{namespace=~"kube-system|default"} == 1for: 2slabels:severity: criticalannotations:description: "空间{{$labels.namespace}}({{$labels.instance}}): 发现{{$labels.pod}}下的{{$labels.container}}启动异常等待中"value: "{{ $value }}"threshold: "1"- alert: Pod_terminatedexpr: kube_pod_container_status_terminated_reason{namespace=~"kube-system|default|prom"} == 1for: 2slabels:severity: criticalannotations:description: "空间{{$labels.namespace}}({{$labels.instance}}): 发现{{$labels.pod}}下的{{$labels.container}}被删除"value: "{{ $value }}"threshold: "1"- alert: Etcd_leaderexpr: etcd_server_has_leader{job="kubernetes-etcd"} == 0for: 2slabels:severity: criticalannotations:description: "组件{{$labels.job}}({{$labels.instance}}): 当前没有leader"value: "{{ $value }}"threshold: "0"- alert: Etcd_leader_changesexpr: rate(etcd_server_leader_changes_seen_total{job="kubernetes-etcd"}[1m]) > 0for: 2slabels:severity: criticalannotations:description: "组件{{$labels.job}}({{$labels.instance}}): 当前leader已发生改变"value: "{{ $value }}"threshold: "0"- alert: Etcd_failedexpr: rate(etcd_server_proposals_failed_total{job="kubernetes-etcd"}[1m]) > 0for: 2slabels:severity: criticalannotations:description: "组件{{$labels.job}}({{$labels.instance}}): 服务失败"value: "{{ $value }}"threshold: "0"- alert: Etcd_db_total_sizeexpr: etcd_debugging_mvcc_db_total_size_in_bytes{job="kubernetes-etcd"} > 10000000000for: 2slabels:severity: criticalannotations:description: "组件{{$labels.job}}({{$labels.instance}}):db空间超过10G"value: "{{ $value }}"threshold: "10G"- alert: Endpoint_readyexpr: kube_endpoint_address_not_ready{namespace=~"kube-system|default"} == 1for: 2slabels:severity: criticalannotations: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 > 90for: 2slabels:severity: criticalannotations: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 > 90for: 2slabels:severity: criticalannotations:summary: "{{ $labels.instance }}内存使用率过高"description: "{{ $labels.instance }}的内存使用率超过90%,当前使用率[{{ $value }}],需要排查处理"- alert: InstanceDownexpr: up == 0for: 2slabels:severity: criticalannotations:summary: "{{ $labels.instance }}: 服务器宕机"description: "{{ $labels.instance }}: 服务器延时超过2分钟"- alert: 物理节点磁盘的IO性能expr: 100-(avg(irate(node_disk_io_time_seconds_total[1m])) by(instance)* 100) < 60for: 2slabels:severity: criticalannotations: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) > 102400for: 2slabels:severity: criticalannotations: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) > 102400for: 2slabels:severity: criticalannotations:summary: "{{$labels.mountpoint}} 流出网络带宽过高!"description: "{{$labels.mountpoint }}流出网络带宽持续5分钟高于100M. RX带宽使用率{{$value}}"- alert: TCP会话expr: node_netstat_Tcp_CurrEstab > 1000for: 2slabels:severity: criticalannotations: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) > 80for: 2slabels:severity: criticalannotations:summary: "{{$labels.mountpoint}} 磁盘分区使用率过高!"description: "{{$labels.mountpoint }} 磁盘分区使用大于80%(目前使用:{{$value}}%)"
生成alertmanager配置文件
$ cat >alertmanager-cm.yaml <<EOFkind: ConfigMapapiVersion: v1metadata:name: alertmanagernamespace: promdata:alertmanager.yml: |-global:resolve_timeout: 1msmtp_smarthost: 'smtp.163.com:25'smtp_from: 'lv916551516@163.com'smtp_auth_username: 'lv916551516@163.com'smtp_auth_password: 'QKRIUAMMLHGGYEGB'smtp_require_tls: falseroute:group_by: [alertname]group_wait: 10sgroup_interval: 10srepeat_interval: 10mreceiver: default-receiverreceivers:- 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/v1kind: Deploymentmetadata:name: prometheus-servernamespace: promlabels:app: prometheusspec:replicas: 1selector:matchLabels:app: prometheuscomponent: server#matchExpressions:#- {key: app, operator: In, values: [prometheus]}#- {key: component, operator: In, values: [server]}template:metadata:labels:app: prometheuscomponent: serverannotations:prometheus.io/scrape: 'false'spec:nodeName: node02 # 将此处的node02改为你集群的任意node节点(不建议是master节点)serviceAccountName: monitor # 此处指定的是上面访问cAvisor时创建的用户containers:- name: prometheusimage: prom/prometheus:v2.20.1imagePullPolicy: IfNotPresentcommand:- prometheus- --config.file=/etc/prometheus/prometheus.yml- --storage.tsdb.path=/prometheus- --storage.tsdb.retention=30d- --web.enable-lifecycleports:- containerPort: 9090protocol: TCPvolumeMounts:- mountPath: /etc/prometheusname: prometheus-config- mountPath: /prometheus/name: prometheus-storage-volume- name: localtimemountPath: /etc/localtime- name: alertmanagerimage: prom/alertmanager:v0.21.0imagePullPolicy: IfNotPresentargs:- "--config.file=/etc/alertmanager/alertmanager.yml"- "--log.level=info"ports:- containerPort: 9093protocol: TCPname: alertmanagervolumeMounts:- name: alertmanager-configmountPath: /etc/alertmanager- name: alertmanager-storagemountPath: /alertmanager- name: localtimemountPath: /etc/localtimevolumes:- name: prometheus-configconfigMap:name: prometheus-config- name: prometheus-storage-volumehostPath:path: /datatype: Directory- name: alertmanager-configconfigMap:name: alertmanager- name: alertmanager-storagehostPath:path: /data/alertmanagertype: DirectoryOrCreate- name: localtimehostPath:path: /usr/share/zoneinfo/Asia/Shanghai---apiVersion: v1kind: Servicemetadata:name: prometheusnamespace: promlabels:app: prometheusspec:type: NodePortports:- port: 9090targetPort: 9090nodePort: 30090protocol: TCPselector:app: prometheuscomponent: server---apiVersion: v1kind: Servicemetadata:labels:name: prometheuskubernetes.io/cluster-service: 'true'name: alertmanagernamespace: promspec:ports:- name: alertmanagernodePort: 30066port: 9093protocol: TCPtargetPort: 9093selector:app: prometheussessionAffinity: Nonetype: NodePort# 在node02机器上创建pod将要挂载的目录并赋予权限$ mkdir /data$ chown 65534.65534 /data # prometheus默认以id为 65534的用户运行,需要调整这个目录的属主,否则容器无法启动# 执行yaml文件(回到master节点)$ kubectl apply -f prometheus-cfg.yamlkubectl apply -f alertmanager-cm.yamlkubectl 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 << EOFapiVersion: v1kind: Servicemetadata:annotations: # 想要Prometheus监控到此service,下面两个注解是不可或缺的。prometheus.io/port: "32107"prometheus.io/scrape: "true"labels:component: kube-schedulertier: control-planename: kube-schedulernamespace: kube-systemspec:clusterIP:ports:- name: metricsport: 10251protocol: TCPtargetPort: 10251nodePort: 32107selector:component: kube-schedulertier: control-planetype: NodePortEOF# 创建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: 5sstatic_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 << EOFapiVersion: v1kind: Servicemetadata:annotations: # 同样,以下两个注解是必不可少的prometheus.io/port: "32108"prometheus.io/scrape: "true"labels:component: kube-controller-managertier: control-planename: kube-controllernamespace: kube-systemspec:clusterIP:ports:- name: metricsport: 10252protocol: TCPtargetPort: 10252nodePort: 32108selector:component: kube-controller-managertier: control-planetype: NodePortEOF# 上述中的targetPort指定的端口,就是kube-controller-manager监听的端口# 你可以在master上执行以下命令,确认下$ ss -lnput | grep kube-controllertcp 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: 5sstatic_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 :10249tcp 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: 5sstatic_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-certsetcd-certs Opaque 3 60s# 修改Prometheus-deploy.yaml文件# 主要是将创建的secret通过volume挂载到Prometheus容器中,如下:$ vim prometheus-deploy.yaml# 在volumeMounts字段下新增如下:- name: k8s-certsmountPath: /var/run/secrets/kubernetes.io/k8s-certs/etcd/# 在volumes字段新增如下:- name: k8s-certssecret:secretName: etcd-certs# 修改prometheus-cfg.yaml文件,增加如下job:$ vim prometheus-cfg.yaml........... # 省略部分内容- job_name: 'kubernetes-etcd'scheme: httpstls_config:ca_file: /var/run/secrets/kubernetes.io/k8s-certs/etcd/ca.crtcert_file: /var/run/secrets/kubernetes.io/k8s-certs/etcd/server.crtkey_file: /var/run/secrets/kubernetes.io/k8s-certs/etcd/server.keyscrape_interval: 5sstatic_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 <<EOFapiVersion: apps/v1kind: Deploymentmetadata:name: kube-state-metricsnamespace: kube-systemspec:replicas: 1selector:matchLabels:app: kube-state-metricstemplate:metadata:labels:app: kube-state-metricsspec:serviceAccountName: kube-state-metricscontainers:- name: kube-state-metrics# image: gcr.io/google_containers/kube-state-metrics-amd64:v1.3.1image: quay.io/coreos/kube-state-metrics:v1.9.0ports:- containerPort: 8080EOF$ 创建授权账户$ cat > kube-state-metrics-rbac.yaml <<EOF---apiVersion: v1kind: ServiceAccountmetadata:name: kube-state-metricsnamespace: kube-system---apiVersion: rbac.authorization.k8s.io/v1kind: ClusterRolemetadata:name: kube-state-metricsrules:- 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/v1kind: ClusterRoleBindingmetadata:name: kube-state-metricsroleRef:apiGroup: rbac.authorization.k8s.iokind: ClusterRolename: kube-state-metricssubjects:- kind: ServiceAccountname: kube-state-metricsnamespace: kube-systemEOF# 创建service$ cat > kube-state-metrics-svc.yaml <<EOFapiVersion: v1kind: Servicemetadata:annotations:prometheus.io/scrape: 'true'name: kube-state-metricsnamespace: kube-systemlabels:app: kube-state-metricsspec:ports:- name: kube-state-metricsport: 8080protocol: TCPselector:app: kube-state-metricsEOF# 创建资源对象$ 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 promapiVersion: v1kind: Podmetadata:annotations:cni.projectcalico.org/podIP: 10.100.140.88/32cni.projectcalico.org/podIPs: 10.100.140.88/32prometheus.io/scrape: "true" # 将此处的false改为true即可........ # 省略部分内容
然后查看Prometheus的target列表,看到如下即表示成功发现pod:

