k8s 監控(二)監控集羣組件和 pod

本文屬於 k8s 監控系列,其他文章爲:node

  1. k8s 監控(一)安裝 Prometheus
  2. k8s 監控(三)prometheus-adapter
  3. k8s 監控(四)監控宿主機

在上一篇文章中,咱們已經在 k8s 中安裝了 Prometheus,而且收集了它自身的監控指標。而在這篇文章,咱們將收集 k8s 全部組件和 pod 的監控指標。linux

在這以前須要先修改下以前監控 Prometheus 自身使用的一個配置,由於它來源於 prometheus-operator,更多的是我對它使用這個配置的理解。而咱們本身直接使用的話,沒有必要搞這麼麻煩,下面是修改後的內容。web

- job_name: prometheus
 honor_labels: false
 kubernetes_sd_configs:
 - role: endpoints
 namespaces:
 names:
 - monitoring
 scrape_interval: 30s
 relabel_configs:
 - action: keep
 source_labels:
 - __meta_kubernetes_service_label_prometheus
 regex: k8s
 - source_labels:
 - __meta_kubernetes_namespace
 target_label: namespace
 - source_labels:
 - __meta_kubernetes_service_name
 target_label: service
 - source_labels:
 - __meta_kubernetes_pod_name
 target_label: pod
 - target_label: endpoint
 replacement: web
複製代碼

這一看就懂,我也就很少作解釋了。下面咱們開始進入正題,首先監控 etcd。正則表達式

監控 etcd

以前咱們經過 curl 命令訪問到了 etcd 監控指標所在的 URL,知道了它的監控指標有哪些,如今咱們要配置 Prometheus,讓其收集這些監控數據。docker

以前也提到過,k8s 中 Prometheus 的監控是經過發現 endpoint 的方式進行,而 endpoint 又是 service 建立的,因此咱們須要先建立一個 etcd 的 service。centos

咱們新建一個名爲 kube-etcd-service.yml 的文件,內容以下:api

apiVersion: v1
kind: Service
metadata:
 name: kube-etcd
 labels:
 k8s-app: kube-etcd
 namespace: kube-system
spec:
 clusterIP: None
 ports:
 - name: http-metrics
 port: 2379
 protocol: TCP
 targetPort: 2379
 selector:
 component: etcd
 type: ClusterIP
複製代碼

說明:bash

  • 因爲 etcd 處於 kube-system 名稱空間,因此這裏的 namespace 也應該是 kube-system;
  • 由於 etcd pod 自己會存在 component=etcd 這個標籤,因此這裏的選擇器使用的就是這個。
kubectl apply -f kube-etcd-service.yml
複製代碼

建立成功後,能夠經過以下命令查看它建立的 endpoint:markdown

kubectl -n kube-system get endpoints kube-etcd
複製代碼

如今經過這個 endpoint 就可以訪問到後面三臺 etcd,如今只須要在 Prometheus 中添加對應的配置便可,配置內容以下。app

- job_name: kube-etcd
 honor_labels: false
 kubernetes_sd_configs:
 - role: endpoints
 namespaces:
 names:
 - kube-system
 scheme: https
 tls_config:
 insecure_skip_verify: false
 ca_file: /etc/prometheus/secrets/etcd-client-cert/ca.crt
 cert_file: /etc/prometheus/secrets/etcd-client-cert/healthcheck-client.crt
 key_file: /etc/prometheus/secrets/etcd-client-cert/healthcheck-client.key
 relabel_configs:
 - action: keep
 source_labels:
 - __meta_kubernetes_service_label_k8s_app
 regex: kube-etcd
 - source_labels:
 - __meta_kubernetes_namespace
 target_label: namespace
 - source_labels:
 - __meta_kubernetes_service_name
 target_label: service
 - source_labels:
 - __meta_kubernetes_pod_name
 target_label: pod
 - target_label: endpoint
 replacement: http-metrics
 metric_relabel_configs:
 - action: drop
 regex: (etcd_debugging|etcd_disk|etcd_request|etcd_server|grpc_server).*
 source_labels:
 - __name__
複製代碼

由於訪問 etcd 須要驗證客戶端證書,因此這裏須要提供證書和私鑰文件。這三個文件以前都已掛載到 Prometheus 容器中,直接拿來用就行。

下面的 relabel_configs 就很少提了,和前面監控 Prometheus 自身的配置差很少,最主要的仍是 metric_relabel_configs,它是用來刪除咱們不須要的監控指標的。

這裏將以 etcd_debugging|etcd_disk|etcd_request|etcd_server|grpc_server 這些開頭的監控指標都刪掉了,大家不要學我,最好搞清楚它的做用來決定是否是將其刪掉,我純粹是看不懂因此才刪的。

最後將上面的內容粘貼進 prometheus-config.yml。當你 apply 配置文件後,不要急着 reload,由於 Prometheus 中可能沒有當即更新,你能夠經過 kubectl exec -it 鏈接到 Prometheus 的 pod 中驗證下配置文件是否已經更新。

若是更新了,就直接經過下面命令讓其 reload:

curl -XPOST PROMETHEUS_IP:9090/-/reload
複製代碼

而後訪問 Prometheus 的 web 頁面,就能夠在 targets 中看到 etcd 了。

監控 apiserver

apiserver 的監控方式更簡單,由於它的 service 已經自動建立了。但你須要注意的是,它的 service 建立在 default 名稱空間,名爲 kubernetes

沒什麼好說的,直接放出 Prometheus 監控 apiserver 的配置。

- job_name: kube-apiserver
 honor_labels: false
 kubernetes_sd_configs:
 - role: endpoints
 namespaces:
 names:
 - default
 scrape_interval: 30s
 scheme: https
 tls_config:
 insecure_skip_verify: false
 ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt
 server_name: kubernetes
 bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token
 relabel_configs:
 - action: keep
 source_labels:
 - __meta_kubernetes_service_label_component
 regex: apiserver
 metric_relabel_configs:
 - source_labels:
 - __name__
 action: drop
 regex: (apiserver_storage_data_key_generation_latencies_microseconds_bucket|apiserver_admission_controller_admission_latencies_milliseconds_bucket|apiserver_admission_step_admission_latencies_milliseconds_bucket|apiserver_admission_step_admission_latencies_milliseconds_summary|apiserver_request_latencies_bucket|apiserver_request_latencies_summary|apiserver_storage_data_key_generation_latencies_microseconds_bucket|rest_client_request_latency_seconds_bucket)
複製代碼

這裏由於 insecure_skip_verify 設爲了 false,也就是校驗服務端證書,因此這裏提供了 ca 文件和 server_name。一樣,這個證書事先已經掛載到了容器中,因此直接指定就行。

由於我不想關注的指標太多,因此刪了一批。先聲明,我是瞎刪的,並不懂它們的確切意義,只是以爲沒啥用,因此就刪了,大家別學我!

最後你看着 reload 吧。

監控 pod

pod 的監控指標是 kubelet 提供的,前面也已經使用 curl 命令看到了,所以這裏也是直接幹。

prometheus-operator 使用的一樣是 endpoints 發現的方式,可是 kubelet 是操做系統的進程,並非 pod,所以經過建立 service 的方式是不可能建立對應的 endpoint 的,也不知道它爲啥能夠作到。

爲了更通用,咱們這裏是經過 node 發現的方式進行的。使用 node 發現,你沒法指定端口,prometheus 會自動訪問發現 node 的 10250 端口。

prometheus 的配置以下:

 - job_name: pods
 honor_labels: true
 kubernetes_sd_configs:
 - role: node
 scrape_interval: 30s
 metrics_path: /metrics/cadvisor
 scheme: https
 tls_config:
 insecure_skip_verify: true
 bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token
 metric_relabel_configs:
 - source_labels:
 - __name__
 regex: container_(cpu_cfs_periods_total|fs_inodes_total|fs_sector_reads_total|fs_sector_writes_total|last_seen|memory_mapped_file|spec_memory_reservation_limit_bytes|spec_memory_swap_limit_bytes|tasks_state)
 action: drop
 - source_labels:
 - container
 regex: ""
 action: drop
 - action: labeldrop
 regex: (id|name|pod_name|image)
複製代碼

後面的 metric_relabel_configs 中,除了刪除了一些我認爲沒用的監控指標外,還刪除了全部 container 標籤爲空的監控指標,就像這些:

container_memory_cache{container="",container_name="",id="/",image="",name="",namespace="",pod="",pod_name=""} 2.144395264e+09 1565777155746
container_memory_cache{container="",container_name="",id="/kubepods.slice",image="",name="",namespace="",pod="",pod_name=""} 7.14027008e+08 1565777155757
container_memory_cache{container="",container_name="",id="/kubepods.slice/kubepods-besteffort.slice",image="",name="",namespace="",pod="",pod_name=""} 3.5053568e+08 1565777145294
container_memory_cache{container="",container_name="",id="/kubepods.slice/kubepods-besteffort.slice/kubepods-besteffort-poda213e57700fd1325c59a70dd70f1a07d.slice",image="",name="",namespace="kube-system",pod="etcd-ops.k8s.master.01.sit",pod_name="etcd-ops.k8s.master.01.sit"} 3.09784576e+08 1565777149076
container_memory_cache{container="",container_name="",id="/kubepods.slice/kubepods-besteffort.slice/kubepods-besteffort-podcfdbebf5_8211_11e9_8699_005056a7c0c5.slice",image="",name="",namespace="kube-system",pod="kube-proxy-xw8sw",pod_name="kube-proxy-xw8sw"} 4.0767488e+07 1565777147425
複製代碼

實在不知道這些是幹啥的,並且數量很是多,乾脆直接刪掉。同時還刪除了一些標籤,好比下面這種的:

container_fs_io_current{container="coredns",container_name="coredns",device="/dev/mapper/centos-root",endpoint="https-metrics",id="/kubepods.slice/kubepods-burstable.slice/kubepods-burstable-poda9693624_85e3_11e9_80cb_005056a7c0c5.slice/docker-9b95ca870a0e7a8fde7ce116b07fc696bd91bea75f6bc61478f3ecc98f36f131.scope",image="sha256:eb516548c180f8a6e0235034ccee2428027896af16a509786da13022fe95fe8c",instance="10.99.100.2:10250",job="pods",name="k8s_coredns_coredns-fb8b8dccf-9dvh7_kube-system_a9693624-85e3-11e9-80cb-005056a7c0c5_2",namespace="kube-system",pod="coredns-fb8b8dccf-9dvh7",pod_name="coredns-fb8b8dccf-9dvh7",service="kubelet"}
複製代碼

能夠看到 id、name 和 image 這些標籤的值很是長,很差看不說,還浪費內存和存儲資源,我就都刪了。它貌似會形成一個 pod 中若是有多個容器,你可能沒法知道這個容器是監控指標中是哪個,由於 image 這個標籤被刪了。

反正我刪了,你看着辦。刪除以後就是這樣:

container_fs_io_current{container="coredns",container_name="coredns",device="/dev/mapper/centos-root",endpoint="https-metrics",instance="10.99.100.2:10250",job="pods",namespace="kube-system",pod="coredns-fb8b8dccf-9dvh7",service="kubelet"}
複製代碼

固然不少標籤是咱們本身建立,若是你不須要,能夠在上面的 relabel_configs 中刪除對應標籤的配置。或許你還想刪其餘的標籤,那你往上面的配置中加就行。

最後記得 reload。

安裝 kube-state-metrics

k8s 的其餘組件我就不繼續監控了,包括 kubelet、controller manager、coredns 等,它們監控的手段和以前的幾個組件都差很少,相信大家本身弄起來也是輕輕鬆鬆。

下面咱們會安裝 kube-state-metrics,這個東西會鏈接 apiserver,而後將集羣裏的各類資源的指標都暴露出來,好比 configMap、ingress、secret、pod、deployment、statefulset 等,這是對 pod 指標的一大補充,很是有用。

RBAC 權限

由於它要訪問集羣內的全部資源,才能將它們的信息提供出去,所以部署它以前,先爲它建立一些權限。這些權限都會綁定到一個 serviceAccount 上,而後咱們用這個 sa 運行 kube-state-metrics 就行。

kube-state-metrics-clusterRole.yml:

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
 name: kube-state-metrics
rules:
 - apiGroups:
 - ""
 resources:
 - configmaps
 - secrets
 - nodes
 - pods
 - services
 - resourcequotas
 - replicationcontrollers
 - limitranges
 - persistentvolumeclaims
 - persistentvolumes
 - namespaces
 - endpoints
 verbs:
 - list
 - watch
 - apiGroups:
 - extensions
 resources:
 - daemonsets
 - deployments
 - replicasets
 - ingresses
 verbs:
 - list
 - watch
 - apiGroups:
 - apps
 resources:
 - statefulsets
 - daemonsets
 - deployments
 - replicasets
 verbs:
 - list
 - watch
 - apiGroups:
 - batch
 resources:
 - cronjobs
 - jobs
 verbs:
 - list
 - watch
 - apiGroups:
 - autoscaling
 resources:
 - horizontalpodautoscalers
 verbs:
 - list
 - watch
 - apiGroups:
 - authentication.k8s.io
 resources:
 - tokenreviews
 verbs:
 - create
 - apiGroups:
 - authorization.k8s.io
 resources:
 - subjectaccessreviews
 verbs:
 - create
 - apiGroups:
 - policy
 resources:
 - poddisruptionbudgets
 verbs:
 - list
 - watch
 - apiGroups:
 - certificates.k8s.io
 resources:
 - certificatesigningrequests
 verbs:
 - list
 - watch
複製代碼

kube-state-metrics-clusterRoleBinding.yml:

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: monitoring
複製代碼

kube-state-metrics-role.yml:

apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
 name: kube-state-metrics
 namespace: monitoring
rules:
 - apiGroups:
 - ""
 resources:
 - pods
 verbs:
 - get
 - apiGroups:
 - extensions
 resourceNames:
 - kube-state-metrics
 resources:
 - deployments
 verbs:
 - get
 - update
 - apiGroups:
 - apps
 resourceNames:
 - kube-state-metrics
 resources:
 - deployments
 verbs:
 - get
 - update
複製代碼

kube-state-metrics-roleBinding.yml:

apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
 name: kube-state-metrics
 namespace: monitoring
roleRef:
 apiGroup: rbac.authorization.k8s.io
 kind: Role
 name: kube-state-metrics
subjects:
 - kind: ServiceAccount
 name: kube-state-metrics
複製代碼

kube-state-metrics-serviceAccount.yml:

apiVersion: v1
kind: ServiceAccount
metadata:
 name: kube-state-metrics
 namespace: monitoring
複製代碼

deployment 和 service

kube-state-metrics 會提供兩個指標頁面,一個是暴露集羣內資源的,另外一個是它自身的,它自身的能夠選擇性的關注。

先建立 kube-state-metrics-deployment.yml:

apiVersion: apps/v1
kind: Deployment
metadata:
 labels:
 app: kube-state-metrics
 name: kube-state-metrics
 namespace: monitoring
spec:
 replicas: 1
 selector:
 matchLabels:
 app: kube-state-metrics
 template:
 metadata:
 labels:
 app: kube-state-metrics
 spec:
 containers:
 - args:
 - --port=10000
 - --telemetry-port=10001
 image: quay.io/coreos/kube-state-metrics:v1.6.0
 name: kube-state-metrics
 resources:
 limits:
 cpu: 100m
 memory: 150Mi
 requests:
 cpu: 100m
 memory: 150Mi
 - command:
 - /pod_nanny
 - --container=kube-state-metrics
 - --cpu=100m
 - --extra-cpu=2m
 - --memory=150Mi
 - --extra-memory=30Mi
 - --threshold=5
 - --deployment=kube-state-metrics
 env:
 - name: MY_POD_NAME
 valueFrom:
 fieldRef:
 apiVersion: v1
 fieldPath: metadata.name
 - name: MY_POD_NAMESPACE
 valueFrom:
 fieldRef:
 apiVersion: v1
 fieldPath: metadata.namespace
 image: k8s.gcr.io/addon-resizer:1.8.4
 name: addon-resizer
 resources:
 limits:
 cpu: 50m
 memory: 30Mi
 requests:
 cpu: 10m
 memory: 30Mi
 nodeSelector:
        kubernetes.io/os: linux
 securityContext:
 runAsNonRoot: true
 runAsUser: 65534
 serviceAccountName: kube-state-metrics
複製代碼

指定了兩個啓動參數,也就是兩個端口,其中 10000 是暴露集羣資源指標的端口,10001 就是它自身了。除了 kube-state-metrics 以外,還啓動了 addon-resizer 這個容器,我不知道它是幹啥的,反正官方怎麼搞咱們怎麼弄就是了。

最後是 service 文件 kube-state-metrics-service.yml:

apiVersion: v1
kind: Service
metadata:
 labels:
 k8s-app: kube-state-metrics
 name: kube-state-metrics
 namespace: monitoring
spec:
 clusterIP: None
 ports:
 - name: http-main
 port: 10000
 targetPort: 10000
 - name: http-self
 port: 10001
 targetPort: 10001
 selector:
 app: kube-state-metrics
複製代碼

兩個端口都暴露出來,你能夠都收集或者只收集 10000 端口。若是隻收集 10000,你能夠只暴露一個端口,也能夠兩個都暴露,而後在 Prometheus 配置中過濾掉一個端口便可。

收集監控數據

將上面全部的文件都 apply 以後,就能夠直接配置 Prometheus 進行收集了。在此以前,你可使用 curl 命令訪問它的指標頁面,看看裏面都有啥:

curl IP:10000/metrics
curl IP:10001/metrics
複製代碼

這個 ip 地址不用我說怎麼拿吧,而後你就能夠看到集羣資源的指標很是很是很是的多,我以爲你最好對其進行過濾,將不須要的通通拒絕掉,否則對 Prometheus 形成的壓力很大。

而後下面就是 Prometheus 的配置:

- job_name: kube-state-metrics
 honor_labels: true
 kubernetes_sd_configs:
 - role: endpoints
 namespaces:
 names:
 - monitoring
 scrape_interval: 30s
 scrape_timeout: 30s
 tls_config:
 insecure_skip_verify: true
 bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token
 relabel_configs:
 - action: keep
 source_labels:
 - __meta_kubernetes_service_label_k8s_app
 regex: kube-state-metrics
 - action: keep
 source_labels:
 - __meta_kubernetes_endpoint_port_name
 regex: http-main
 metric_relabel_configs:
 - source_labels:
 - __name__
 regex: (kube_daemonset_status_number_ready|kube_daemonset_status_number_unavailable|kube_deployment_status_replicas_unavailable|kube_deployment_spec_paused|kube_deployment_spec_strategy_rollingupdate_max_surge|kube_deployment_spec_strategy_rollingupdate_max_unavailable|kube_endpoint_address_available|kube_endpoint_address_not_ready|kube_node_info|kube_node_spec_unschedulable|kube_node_status_condition|kube_node_status_capacity|kube_node_status_capacity|kube_node_status_allocatable|kube_persistentvolumeclaim_info|kube_persistentvolumeclaim_status_phase|kube_persistentvolumeclaim_resource_requests_storage_bytes|kube_persistentvolume_status_phase|kube_persistentvolume_info|kube_persistentvolume_capacity_bytes|kube_pod_info|kube_pod_status_phase|kube_pod_status_ready|kube_pod_container_info|kube_pod_container_status_waiting|kube_pod_container_status_waiting_reason|kube_pod_container_status_running|kube_pod_container_status_terminated_reason|kube_pod_container_status_last_terminated_reason|kube_pod_container_status_restarts_total|kube_pod_container_resource_limits|kube_service_info|kube_statefulset_status_replicas_current|kube_statefulset_status_replicas_ready)
 action: keep
複製代碼

配置的內容就無需我多提了,和前面監控的配置都差很少。

主要是這裏刪除了一大批我不關注的指標,注意我這裏作的是白名單,只收集我指定的,由於不須要的實在太多,寫不過來。雖然正則表達式這麼長,可是因爲指標名稱短,且 regex 默認錨定了行首和行尾,因此匹配效率仍是很高的。

最後記得 reload。

ok,本文到此爲止,下一篇會提到如何使用 grafana 和 alertmanager,謝謝!