導航:這里主要是列出一個prometheus一些系統的學習過程,最后按照章節順序查看,由於寫作該文檔經歷了不同時期,所以在文中有時出現 的雲環境不統一,但是學習具體使用方法即可,在最后的篇章,有一個完整的騰訊雲的實戰案例。 8.kube-state-metrics 和 metrics-server 13.Grafana簡單用法 參考: https://prometheus.io/docs/prometheus/latest/configuration/configuration/#kubernetes_sd_config https://www.bookstack.cn/read/prometheus_practice/introduction-README.md |
1.Kubernetes中部署prometheus
由於下面的演示需要用到prometheus,為了方便,首先在k8s集群中部署一個prometheus。
1.1 使用ConfigMaps管理應用配置
這里將使用ConfigMaps管理Prometheus的配置文件,創建prometheus-config.yml文件,並寫入以下內容:

cat prometheus-configmap.yml apiVersion: v1 kind: ConfigMap metadata: name: prometheus-config namespace: monitoring data: prometheus.yml: | global: scrape_interval: 15s evaluation_interval: 15s scrape_configs: - job_name: 'prometheus' static_configs: - targets: ['localhost:9090'] - job_name: 'kubernetes-kubelet' scheme: https tls_config: ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token kubernetes_sd_configs: - role: node 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 - job_name: 'kubernetes-cadvisor' scheme: https tls_config: ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token kubernetes_sd_configs: - role: node relabel_configs: - 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 - action: labelmap regex: __meta_kubernetes_node_label_(.+) - job_name: 'kubernetes-pods' kubernetes_sd_configs: - role: pod relabel_configs: - source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_scrape] action: keep regex: true - source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_path] action: replace target_label: __metrics_path__ regex: (.+) - source_labels: [__address__, __meta_kubernetes_pod_annotation_prometheus_io_port] action: replace regex: ([^:]+)(?::\d+)?;(\d+) replacement: $1:$2 target_label: __address__ - action: labelmap regex: __meta_kubernetes_pod_label_(.+) - source_labels: [__meta_kubernetes_namespace] action: replace target_label: kubernetes_namespace - source_labels: [__meta_kubernetes_pod_name] action: replace target_label: kubernetes_pod_name - job_name: 'kubernetes-apiservers' 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 - target_label: __address__ replacement: kubernetes.default.svc:443
1.2 使用Deployment部署Prometheus

apiVersion: v1 kind: "Service" metadata: name: prometheus namespace: monitoring labels: name: prometheus spec: ports: - name: prometheus protocol: TCP port: 9090 targetPort: 9090 selector: app: prometheus type: NodePort --- apiVersion: apps/v1 kind: Deployment metadata: labels: name: prometheus name: prometheus namespace: monitoring spec: replicas: 1 selector: matchLabels: app: prometheus template: metadata: labels: app: prometheus spec: serviceAccountName: prometheus containers: - name: prometheus image: prom/prometheus:v2.3.0 env: - name: ver value: "8" command: - "/bin/prometheus" args: - "--config.file=/etc/prometheus/prometheus.yml" ports: - containerPort: 9090 protocol: TCP volumeMounts: - mountPath: "/etc/prometheus" name: prometheus-config volumes: - name: prometheus-config configMap: name: prometheus-config
安裝完成后使用nodeport來訪問測試是否安裝成功,這里就不做演示
2.Kubernetes的訪問授權
這篇授權文件已更新增強了通過node的訪問發現模式的授權.
2.1 Kubernetes的訪問授權
為了能夠讓Prometheus能夠訪問收到認證保護的Kubernetes API,我們首先需要做的是,對Prometheus進行訪問授權。在Kubernetes中主要使用基於角色的訪問控制模型(Role-Based Access Control),用於管理Kubernetes下資源訪問權限。首先我們需要在Kubernetes下定義角色(ClusterRole),並且為該角色賦予相應的訪問權限。同時創建Prometheus所使用的賬號(ServiceAccount),最后則是將該賬號與角色進行綁定(ClusterRoleBinding)。這些所有的操作在Kubernetes同樣被視為是一系列的資源,可以通過YAML文件進行描述並創建,這里創建prometheus-rbac-setup.yml文件,並寫入以下內容:

apiVersion: rbac.authorization.k8s.io/v1beta1 kind: ClusterRole metadata: name: prometheus rules: - apiGroups: [""] resources: - nodes #node發現模式的授權資源,不然通過kubelet自帶的發現模式不授權這個資源,會在prometheus爆出403錯誤 - nodes/metrics - nodes/proxy - services - endpoints - pods - namespaces verbs: ["get", "list", "watch"] - apiGroups: - extensions resources: - ingresses verbs: ["get", "list", "watch"] - nonResourceURLs: ["/metrics","/api/*"] verbs: ["get"] --- apiVersion: v1 kind: ServiceAccount metadata: name: prometheus namespace: monitoring --- apiVersion: rbac.authorization.k8s.io/v1beta1 kind: ClusterRoleBinding metadata: name: prometheus roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: prometheus subjects: - kind: ServiceAccount name: prometheus namespace: monitoring
其中需要注意的是ClusterRole是全局的,不需要指定命名空間。而ServiceAccount是屬於特定命名空間的資源。通過kubectl命令創建RBAC對應的各個資源:
$ kubectl create -f prometheus-rbac-setup.yml clusterrole "prometheus" created serviceaccount "prometheus" created clusterrolebinding "prometheus" created
在完成角色權限以及用戶的綁定之后,就可以指定Prometheus使用特定的ServiceAccount創建Pod實例。修改prometheus-deployment.yml文件,並添加serviceAccountName和serviceAccount定義:
spec: replicas: 1 template: metadata: labels: app: prometheus spec: serviceAccountName: prometheus serviceAccount: prometheus
通過kubectl apply對Deployment進行變更升級:
$ kubectl apply -f prometheus-deployment.yml service "prometheus" configured deployment "prometheus" configured $ kubectl get pods NAME READY STATUS RESTARTS AGE prometheus-55f655696d-wjqcl 0/1 Terminating 0 38m prometheus-69f9ddb588-czn2c 1/1 Running 0 6s
指定ServiceAccount創建的Pod實例中,會自動將用於訪問Kubernetes API的CA證書以及當前賬戶對應的訪問令牌文件掛載到Pod實例的/var/run/secrets/kubernetes.io/serviceaccount/目錄下,可以通過以下命令進行查看:
kubectl exec -it prometheus-69f9ddb588-czn2c ls /var/run/secrets/kubernetes.io/serviceaccount/ ca.crt namespace token
2.2 Kubernetes下的服務發現
之前介紹了Prometheus的服務發現能力,它能夠與通過與“中間代理人“的交互,從而動態的獲取需要監控的目標實例。而在Kubernetes下Prometheus就是需要與Kubernetes的API進行交互,從而能夠動態的發現Kubernetes中部署的所有可監控的目標資源。
在Kubernetes下,Promethues通過與Kubernetes API集成目前主要支持5種服務發現模式,分別是:Node、Service、Pod、Endpoints、Ingress。
通過kubectl命令行,可以方便的獲取到當前集群中的所有節點信息:
以下使用minikube做一個簡單的示例
$ kubectl get nodes -o wide NAME STATUS ROLES AGE VERSION EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIME minikube Ready <none> 164d v1.8.0 <none> Buildroot 2017.02 4.9.13 docker://Unknown
為了能夠讓Prometheus能夠獲取到當前集群中所有節點的信息,在Promtheus的配置文件中,我們添加如下Job配置:
- job_name: 'kubernetes-nodes' tls_config: ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token kubernetes_sd_configs: - role: node
通過指定kubernetes_sd_config的模式為node,Prometheus會自動從Kubernetes中發現到所有的node節點並作為當前Job監控的Target實例。如下所示,這里需要指定用於訪問Kubernetes API的ca以及token文件路徑。
對於Ingress,Service,Endpoints, Pod的使用方式也是類似的,下面給出了一個完整Prometheus配置的示例:

apiVersion: v1 data: prometheus.yml: |- global: scrape_interval: 15s evaluation_interval: 15s scrape_configs: - job_name: 'kubernetes-nodes' tls_config: ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token kubernetes_sd_configs: - role: node - job_name: 'kubernetes-service' tls_config: ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token kubernetes_sd_configs: - role: service - job_name: 'kubernetes-endpoints' tls_config: ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token kubernetes_sd_configs: - role: endpoints - job_name: 'kubernetes-ingress' tls_config: ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token kubernetes_sd_configs: - role: ingress - job_name: 'kubernetes-pods' tls_config: ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token kubernetes_sd_configs: - role: pod kind: ConfigMap metadata: name: prometheus-config
更新Prometheus配置文件,並重建Prometheus實例:
$ kubectl apply -f prometheus-config.yml configmap "prometheus-config" configured $ kubectl get pods prometheus-69f9ddb588-rbrs2 1/1 Running 0 4m $ kubectl delete pods prometheus-69f9ddb588-rbrs2 pod "prometheus-69f9ddb588-rbrs2" deleted $ kubectl get pods prometheus-69f9ddb588-rbrs2 0/1 Terminating 0 4m prometheus-69f9ddb588-wtlsn 1/1 Running 0 14s
Prometheus使用新的配置文件重建之后,打開Prometheus UI,通過Service Discovery頁面可以查看到當前Prometheus通過Kubernetes發現的所有資源對象了:
Service Discovery發現的實例
同時Prometheus會自動將該資源的所有信息,並通過標簽的形式體現在Target對象上。如下所示,是Promthues獲取到的Node節點的標簽信息:
__address__="192.168.99.100:10250" __meta_kubernetes_node_address_Hostname="minikube" __meta_kubernetes_node_address_InternalIP="192.168.99.100" __meta_kubernetes_node_annotation_alpha_kubernetes_io_provided_node_ip="192.168.99.100" __meta_kubernetes_node_annotation_node_alpha_kubernetes_io_ttl="0" __meta_kubernetes_node_annotation_volumes_kubernetes_io_controller_managed_attach_detach="true" __meta_kubernetes_node_label_beta_kubernetes_io_arch="amd64" __meta_kubernetes_node_label_beta_kubernetes_io_os="linux" __meta_kubernetes_node_label_kubernetes_io_hostname="minikube" __meta_kubernetes_node_name="minikube" __metrics_path__="/metrics" __scheme__="https" instance="minikube" job="kubernetes-nodes"
目前為止,我們已經能夠通過Prometheus自動發現Kubernetes集群中的各類資源以及其基本信息。不過,如果現在查看Promtheus的Target狀態頁面,結果可能會讓人不太滿意:
Target頁面狀態
雖然Prometheus能夠自動發現所有的資源對象,並且將其作為Target對象進行數據采集。 但並不是所有的資源對象都是支持Promethues的,並且不同類型資源對象的采集方式可能是不同的。因此,在實際的操作中,我們需要有明確的監控目標,並且針對不同類型的監控目標設置不同的數據采集方式。
接下來,將利用Promtheus的服務發現能力,實現對Kubernetes集群的全面監控。
3.監控Kubernetes集群
上一小節中,介紹了Promtheus在Kubernetes下的服務發現能力,並且通過kubernetes_sd_config實現了對Kubernetes下各類資源的自動發現。在本小節中,我們將利用Promethues提供的服務發現能力,實現對Kubernetes集群以及其中部署的各類資源的自動化監控。
3.1 維度策略表
下表中,梳理了監控Kubernetes集群監控的各個維度以及策略:
目標 | 服務發現模式 | 監控方法 | 數據源 |
從集群各節點kubelet組件中獲取節點kubelet的基本運行狀態的監控指標 | node | 白盒 | Kubelet |
從集群各節點kubelet內置的cAdvisor中獲取,節點中運行的容器的監控指標 | node | 白盒 | Kubelet |
從部署到各個節點的Node Exporter中采集主機資源相關的運行資源 | node | 白盒 | Node exporter |
對於內置了Promthues支持的應用,需要從Pod實例中采集其自定義監控指標 | pod | 白盒 | Clustom pod |
獲取API Server組件的訪問地址,並從中獲取Kubernetes集群相關的運行監控指標 | endpoints | 白盒 | api server |
獲取集群中Service的訪問地址,並通過Blackbox Exporter獲取網絡探測指標 | service | 黑盒 | blackbox exporter |
獲取集群中Ingress的訪問信息,並通過Blackbox Exporter獲取網絡探測指標 | ingress | 黑盒 | blackbox exporter |
apiserver實際上是一種特殊的Service,配置一個專門發現普通類型的Service | endpoints | 白盒 | 帶有監控接口的service |
3.2 Kubernetes 集群內監控配置
3.2.1 報錯處理
這里的報錯在下面可能會能用到,所以先貼出來。
該報錯一般在node發現模式出現,就是在通過10250讀取metrics時出現。報錯見以下
Get https://x.x.x.x.:10250/metrics: x509: cannot validate certificate for 192.168.99.100 because it doesn't contain any IP SANs
這是由於當前使用的ca證書中,並不包含192.168.99.100的地址信息。為了解決該問題,第一種方法是直接跳過ca證書校驗過程,通過在tls_config中設置 insecure_skip_verify為true即可。 這樣Promthues在采集樣本數據時,將會自動跳過ca證書的校驗過程,從而從kubelet采集到監控數據:
- job_name: 'kubernetes-kubelet' scheme: https tls_config: ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt insecure_skip_verify: true bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token kubernetes_sd_configs: - role: node relabel_configs: - action: labelmap regex: __meta_kubernetes_node_label_(.+)
3.2.2 從Kubelet獲取節點運行狀態
以下獲取kubelet 節點運行狀態有2種方式來獲取,在維度策略表里面有具體體現。
簡單來說有一種通過node 的 metric的方式,一種使用使用k8s api的方式獲取,2種方式都可以,但是為了統一,建議使用K8s api的獲取方式.
使用node發現模式和api發現模式,主要在於訪問的api不一樣,其余的都一樣。
k8s api發現模式 merics地址(地址原文檔未找到,根據實驗結果反推的以下地址)
cAdvisor的metrics地址: /api/v1/nodes/[節點名稱]/proxy/metrics/cadvisor
kubelnet的metrics地址:/api/v1/nodes/[節點名稱]/proxy/metrics
Node模式自動發現集群中所有Kubelet作為監控的數據采集目標 地址
cAdvisor的metrics地址: /metrics/cadvisor
kubelnet的metrics地址:/metrics
3.2.2.1 K8S API
1.代碼總覽
- job_name: 'kubernetes-kubelet' scheme: https tls_config: ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token kubernetes_sd_configs: - role: node relabel_configs: - action: labelmap - 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
這里使用api-server提供的代理API訪問各個節點中kubelet的metrics服務,所以這里只能監控kubelet的一些狀態和數據
這里配置從relabel_configs分為3步:
第一步: 使用 -action:labelmap, 把k8s node的標簽給匹配出來,方便我們分組,即使沒有標簽也能是node的狀態為up
第二步: 使用 -target_label: __address__,由於在集群內部,這里用集群默認的api server的地址 替換掉__address,這樣,就可以訪問到集群,並且將node節點的狀態為up,但是 訪問api是錯誤的,無法獲取數據
第三步: 使用 -source_labels: [__meta_kubernetes_node_name] 以及 replacement 將 拼接的正常的api替換掉 __metrics_path__,這樣就可以獲取 kubelet的 mertics的數據了.
2.target狀態
3.步驟拆解
每個監控模塊只從重點開始講解。
第一步:
kubernetes_sd_configs:
- role: node
這里首先什么動作都不增加,看看target界面效果,沒有標簽,但是主機是通的,但是這里是因為如果什么都不增加,那么就是 node的發現模式,為了使用api的發現模式,所以接下來還有很多步驟.
第二步:
- action: labelmap regex: __meta_kubernetes_node_label_(.+)
__meta_kubernetes_node_label_(.+) 為kubernetes_sd_config的默認可用元標簽,
__meta_kubernetes_node_label_(.+) 官方文檔是讓用戶匹配node的標簽,這里使用.+匹配到了所有的node標簽,默認可用元標簽,可查閱文檔https://prometheus.io/docs/prometheus/latest/configuration/configuration/#kubernetes_sd_config;把標簽匹配出來可以方便我們分組
第三步:
- target_label: __address__ replacement: kubernetes.default.svc:443
由於第2步里面將地址替換成為了kubernetes.default.svc,這時url地址變成了 "域名/merics",這是k8s api訪問模式的地址,(如果是api的發現模式,如果替換了地址,但是這時候監控key就沒有了)雖然節點狀態正常,但是無法通過api查詢數,所以下一步就是將這個地址變成默認的kubelet的metrics地址。kubelnet的metrics地址:/api/v1/nodes/[節點名稱]/proxy/metrics,下面的source_labels 是node的默認標簽.
第四步:
- source_labels: [__meta_kubernetes_node_name] #語法不加 [] 程序就會報錯 regex: (.+) target_label: __metrics_path__ replacement: /api/v1/nodes/${1}/proxy/metrics
匹配原標簽的所有值(也就是node的名稱),replacement中的值將會覆蓋target_label中指定的label name的值,即__metrics_path__的值會被替換為/api/v1/nodes/${1}/proxy/metrics,其中${1}的值會被替換為__meta_kubernetes_node_name的值這樣完成的可以請求數據的api就拼接出來了
以上就完成了api自動發現的方式
4.監控key總覽
3.2.2.2 Node 發現模式
Kubelet組件運行在Kubernetes集群的各個節點中,其負責維護和管理節點上Pod的運行狀態。kubelet組件的正常運行直接關系到該節點是否能夠正常的被Kubernetes集群正常使用。
基於Node模式,Prometheus會自動發現Kubernetes中所有Node節點的信息並作為監控的目標Target。 而這些Target的訪問地址實際上就是Kubelet的訪問地址,並且Kubelet實際上直接內置了對Promtheus的支持。
簡單來說,node和api發現模式在於訪問的api不同,沒有api發現模式的后面三個步驟,就是node發現模式(node發現模式的授權sa已更新到最新)
1.代碼總覽
- job_name: 'kubernetes-kubelet' scheme: https tls_config: ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token kubernetes_sd_configs: - role: node relabel_configs: - action: labelmap regex: __meta_kubernetes_node_label_(.+)
默認使用role:node,那么就是node發現模式,區別在於訪問的api不同,見下一步的正常target狀態。
2.正常target狀態
3.步驟拆解
Node發現模式和 api發現模式只是api的不同,事實上,node的發現模式更為簡潔。
所以這里不做重復的描述
4.監控key總覽
在k8s API章節一樣,這里不做過多講解
3.2.3 從Kubelet獲取節點容器資源使用情況
從集群各節點kubelet內置的cAdvisor中獲取,節點中運行的容器的監控指標 | node | 白盒 | kubelet |
各節點的kubelet組件中除了包含自身的監控指標信息以外,kubelet組件還內置了對cAdvisor的支持。cAdvisor能夠獲取當前節點上運行的所有容器的資源使用情況,通過訪問kubelet的/metrics/cadvisor地址可以獲取到cadvisor的監控指標,因此和獲取kubelet監控指標類似,這里同樣通過node模式自動發現所有的kubelet信息,並通過適當的relabel過程,修改監控采集任務的配置。 與采集kubelet自身監控指標相似,這里也有兩種方式采集cadvisor中的監控指標。
使用node發現模式和api發現模式,主要在於訪問的api不一樣,其余的都一樣。.
k8s api發現模式 merics地址
cAdvisor的metrics地址: /api/v1/nodes/[節點名稱]/proxy/metrics/cadvisor
kubelet的metrics地址:/api/v1/nodes/[節點名稱]/proxy/metrics
Node模式自動發現集群中所有Kubelet作為監控的數據采集目標地址
cAdvisor的metrics地址: /metrics/cadvisor
kubelnet的metrics地址:/metrics
3.2.3.1 K8S API
1.代碼總覽
- job_name: 'kubernetes-cadvisor' scheme: https tls_config: ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token kubernetes_sd_configs: - role: node #cadvisor的方式和job kubelet的方式基本相同,差距只是api后面多了一個 cadvisor relabel_configs: - 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 - action: labelmap regex: __meta_kubernetes_node_label_(.+)
cadvisor的方式和job kubelet的方式基本相同,差距只是api后面多了一個cadvisor
因為這里需要增加一個cadvisor的目錄上去,所以在代碼的16-18,替換的api url是不同的
2.正常target狀態
3.步驟拆解
由於和獲取節點運行狀態的方式一樣,這里就不做具體拆解,只是api后面多了一個cadvisor
4.監控key總覽
3.2.3.2 Node發現模式
1.代碼總覽
- job_name: 'kubernetes-cadvisor' scheme: https tls_config: ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt insecure_skip_verify: true bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token kubernetes_sd_configs: - role: node relabel_configs: - source_labels: [__meta_kubernetes_node_name] regex: (.+) target_label: __metrics_path__ replacement: metrics/cadvisor - action: labelmap regex: __meta_kubernetes_node_label_(.+)
因為在從 kubelet獲取節點運行狀態默認就是api 就是metric,所以在這個node發現模式章節,把默認的metrics值替換成為metrics/cadvisor ,就這里的代碼不相同
2.正常target狀態
3.步驟拆解
由於和獲取節點運行狀態的方式一樣,這里就不做具體拆解,只是api后面多了一個cadvisor
4.監控key總覽
在k8s API章節一樣,這里不做過多講解
3.2.4 使用NodeExporter監控集群資源使用情況
從部署到各個節點的Node Exporter中采集主機資源相關的運行資源 | node | 白盒 | Node exporter |
對於內置了Promthues支持的應用,需要從Pod實例中采集其自定義監控指標 | pod | 白盒 | Clustom pod |
3.2.4.1 安裝NodeExporter
為了能夠采集集群中各個節點的資源使用情況,我們需要在各節點中部署一個Node Exporter實例。在本章的“部署Prometheus”小節,我們使用了Kubernetes內置的控制器之一Deployment。Deployment能夠確保Prometheus的Pod能夠按照預期的狀態在集群中運行,而Pod實例可能隨機運行在任意節點上。而與Prometheus的部署不同的是,對於Node Exporter而言每個節點只需要運行一個唯一的實例,此時,就需要使用Kubernetes的另外一種控制器Daemonset。顧名思義,Daemonset的管理方式類似於操作系統中的守護進程。Daemonset會確保在集群中所有(也可以指定)節點上運行一個唯一的Pod實例。
apiVersion: extensions/v1beta1 kind: DaemonSet metadata: name: node-exporter namespace: monitoring spec: template: metadata: annotations: prometheus.io/scrape: 'true' prometheus.io/port: '9100' prometheus.io/path: '/metrics' labels: app: node-exporter name: node-exporter spec: containers: - image: prom/node-exporter imagePullPolicy: IfNotPresent name: node-exporter ports: - containerPort: 9100 hostPort: 9100 name: scrape hostNetwork: true hostPID: true
由於Node Exporter需要能夠訪問宿主機,因此這里指定了hostNetwork和hostPID,讓Pod實例能夠以主機網絡以及系統進程的形式運行。同時YAML文件中也創建了NodeExporter相應的Service。這樣通過Service就可以訪問到對應的NodeExporter實例。
應用后查看狀態
$ kubectl get daemonsets NAME DESIRED CURRENT READY UP-TO-DATE AVAILABLE NODE SELECTOR AGE node-exporter 1 1 1 1 1 <none> 15s $ kubectl get pods NAME READY STATUS RESTARTS AGE ... node-exporter-9h56z 1/1 Running 0 51s
由於Node Exporter是以主機網絡的形式運行,因此直接訪問MiniKube的虛擬機IP加上Pod的端口即可訪問當前節點上運行的Node Exporter實例:
curl http://ip:9100/metrics
目前為止,通過Daemonset的形式將Node Exporter部署到了集群中的各個節點中。接下來,我們只需要通過Prometheus的pod服務發現模式,找到當前集群中部署的Node Exporter實例即可。 需要注意的是,由於Kubernetes中並非所有的Pod都提供了對Prometheus的支持,有些可能只是一些簡單的用戶應用,為了區分哪些Pod實例是可以供Prometheus進行采集的,這里我們為Node Exporter添加了注解:
prometheus.io/scrape: 'true' (很多時候,包括在這里,可以通過這個注釋過濾出要監控的容器)
由於Kubernetes中Pod可能會包含多個容器,還需要用戶通過注解指定用戶提供監控指標的采集端口:
prometheus.io/port: '9100'
而有些情況下,Pod中的容器可能並沒有使用默認的/metrics作為監控采集路徑,因此還需要支持用戶指定采集路徑:
prometheus.io/path: 'metrics'
3.2.4.2 配置
1.代碼總覽
- job_name: 'kubernetes-pods' kubernetes_sd_configs: - role: pod relabel_configs: - source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_scrape] action: keep regex: true - source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_path] action: replace target_label: __metrics_path__ regex: (.+) - source_labels: [__address__, __meta_kubernetes_pod_annotation_prometheus_io_port] action: replace regex: ([^:]+)(?::\d+)?;(\d+) replacement: $1:$2 target_label: __address__ - action: labelmap regex: __meta_kubernetes_pod_label_(.+) - source_labels: [__meta_kubernetes_namespace] action: replace target_label: kubernetes_namespace - source_labels: [__meta_kubernetes_pod_name] action: replace target_label: kubernetes_pod_name
這里使用 node_exporter來獲取pod的信息,所以這里主要可以獲取一些pod container的一些信息;
這里從relabel_config開始,總共分為5步
第一步: 使用source_labels和action:keep,過濾出用戶標記過的pod,regex=true才會去匹配,否則會匹配出所有pod
第二步: 使用source_labels和action:replace,過路出用戶標記過的pod,並獲取標記的prometheus_io_path的值,然后替換掉__address__
第三步: 使用source_labels過濾出ip和端口號,替換到target_label里面
第四步: 使用labelmap 取出pod的 namespace,方便我們查看和分類
第五步: 使用labelmap 取出pod的名稱,方便我們查看和分類
2.正常target狀態
3.步驟拆解
第一步:
- job_name: 'kubernetes-pods' kubernetes_sd_configs: - role: pod
這里使用role:pod的發現模式
由於沒有過濾出要監控的pod和更改監控訪問的api,這里為止,獲取了所有的deploy信息
第二步:
relabel_configs: - source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_scrape] action: keep regex: true
__meta_kubernetes_pod_annotation_prometheus_io_scrape是根據 deploy的注釋來采集的,只有annotation=prometheus_io_scrape(當然,這是自定義的)才能收集到
這里通過annotation 過濾除了pod,但是監控的api url不對。
第三步:
- source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_path] action: replace target_label: __metrics_path__ regex: (.+)
過濾出源標簽__meta_kubernetes_pod_annotation_prometheus_io_path 的值,然后替換到默認標簽 __metrics_path__的值
prometheus_io_path也是用戶最定義的值
這里是改變二級目錄的路徑值,所以這里默認就是metric,顯示沒有沒有多大改動
第四步:
- source_labels: [__address__, __meta_kubernetes_pod_annotation_prometheus_io_port] action: replace regex: ([^:]+)(?::\d+)?;(\d+) replacement: $1:$2 target_label: __address__
過濾出 source_labels 的標簽的值,也就是取出IP地址和端口號
regex:只取出默認標簽里面需要的參數,這條正則取出的就是ip地址
replacement: 把上面過濾出來的IP地址和端口號反向引用然后替換到 target_label 標簽里面去
由於node默認就是 9100和metics的二級目錄,所以這里改變了其實是為了保險一點,到這一步,基本可以獲取監控key了
第五步:
- action: labelmap regex: __meta_kubernetes_pod_label_(.+)
取出pod的標簽,方便我們分類和查看
雖然上一步已經有了監控key了,但是為了分組和方便查看,這里再把pod的標簽過濾出來
第六步:
- source_labels: [__meta_kubernetes_namespace] action: replace target_label: kubernetes_namespace
取出 namespace,替換到kubernetes_namespace標簽里
第七步:
- source_labels: [__meta_kubernetes_pod_name] action: replace target_label: kubernetes_pod_name
取出 pod名,以同樣的方式替換至展示的目標標簽
4.監控key總覽
3.2.5 從kube-apiserver獲取集群運行監控指標
獲取API Server組件的訪問地址,並從中獲取Kubernetes集群相關的運行監控指標 | endpoints | 白盒 | api server |
在開始正式內容之前,我們需要先了解一下Kubernetes中Service是如何實現負載均衡的,如下圖所示,一般來說Service有兩個主要的使用場景:
代理對集群內部應用Pod實例的請求:當創建Service時如果指定了標簽選擇器,Kubernetes會監聽集群中所有的Pod變化情況,通過Endpoints自動維護滿足標簽選擇器的Pod實例的訪問信息;
代理對集群外部服務的請求:當創建Service時如果不指定任何的標簽選擇器,此時需要用戶手動創建Service對應的Endpoint資源。例如,一般來說,為了確保數據的安全,我們通常講數據庫服務部署到集群外。 這是為了避免集群內的應用硬編碼數據庫的訪問信息,這是就可以通過在集群內創建Service,並指向外部的數據庫服務實例。
kube-apiserver扮演了整個Kubernetes集群管理的入口的角色,負責對外暴露Kubernetes API。kube-apiserver組件一般是獨立部署在集群外的,為了能夠讓部署在集群內的應用(kubernetes插件或者用戶應用)能夠與kube-apiserver交互,Kubernetes會默認在命名空間下創建一個名為kubernetes的服務,如下所示:
$ kubectl get svc kubernetes -o wide NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 166d <none>
而該kubernetes服務代理的后端實際地址通過endpoints進行維護,如下所示:
$ kubectl get endpoints kubernetes
NAME ENDPOINTS AGE
kubernetes 10.0.2.15:8443 166d
通過這種方式集群內的應用或者系統主機就可以通過集群內部的DNS域名kubernetes.default.svc訪問到部署外部的kube-apiserver實例。
因此,如果我們想要監控kube-apiserver相關的指標,只需要通過endpoints資源找到kubernetes對應的所有后端地址即可。
如下所示,創建監控任務kubernetes-apiservers,這里指定了服務發現模式為endpoints。Promtheus會查找當前集群中所有的endpoints配置,並通過relabel進行判斷是否為apiserver對應的訪問地址:
1.代碼總覽
- job_name: 'kubernetes-apiservers' 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 - target_label: __address__ replacement: kubernetes.default.svc:443
過濾出k8s api集群的訪問svc ,然后將 kubernetes.default.svc:443替換到默認標簽上面,讓prometheus可以訪問
這里從relabel_config開始,總共分為2步
第一步:過濾出默認的k8s api的svc.
第二步:把kubernetes.default.svc:443替換到默認__address__
2.正常target狀態
3.步驟拆解
第一步:
- job_name: 'kubernetes-apiservers' kubernetes_sd_configs: - role: endpoints scheme: https
這里使用role: endpoints的發現模式
如果不配置relabel_configs,,因為訪問不到正常的api,所以target是空白的
第二步:
- source_labels: [__meta_kubernetes_namespace, __meta_kubernetes_service_name, __meta_kubernetes_endpoint_port_name] action: keep regex: default;kubernetes;https
使用source_labels過濾出, defautl空間下的kubernetes服務,這是一個k8s的對外接口服務,服務調用k8sapi都是經過這個svc
由於沒有替換掉 api url,所以顯示出的是node的ip和默認端口
第三步:
- target_label: __address__ replacement: kubernetes.default.svc:443
然后通過target_label替換掉默認的__address__,這樣prometheus就可以訪問 k8s的api服務
4.監控key總覽
3.2.6 對Ingress和Service進行網絡探測
獲取集群中Service的訪問地址,並通過Blackbox Exporter獲取網絡探測指標 | service | 黑盒 | blackbox exporter |
獲取集群中Ingress的訪問信息,並通過Blackbox Exporter獲取網絡探測指標 | ingress | 黑盒 | blackbox exporter |
3.2.6.1 Blackbox exporter
Blackbox_exporter 主動監測主機與服務狀態,是官方提供的 exporter 之一,可以提供 http、dns、tcp、icmp 的監控數據采集
- HTTP 測試
定義 Request Header 信息
判斷 Http status / Http Respones Header / Http Body 內容
- TCP 測試
業務組件端口狀態監聽
應用層協議定義與監聽
- ICMP 測試
主機探活機制
- POST 測試
接口聯通性
- SSL 證書過期時間
安裝
apiVersion: v1 kind: Service metadata: namespace: monitoring labels: app: blackbox-exporter name: blackbox-exporter spec: ports: - name: blackbox port: 9115 protocol: TCP selector: app: blackbox-exporter type: ClusterIP --- apiVersion: extensions/v1beta1 kind: Deployment metadata: labels: app: blackbox-exporter name: blackbox-exporter namespace: monitoring spec: replicas: 1 selector: matchLabels: app: blackbox-exporter template: metadata: labels: app: blackbox-exporter spec: containers: - image: prom/blackbox-exporter imagePullPolicy: IfNotPresent name: blackbox-exporter
通過kubectl命令部署Blackbox Exporter實例,這里將部署一個Blackbox Exporter的Pod實例,同時通過服務blackbox-exporter在集群內暴露訪問地址blackbox-exporter.default.svc.cluster.local,對於集群內的任意服務都可以通過該內部DNS域名訪問Blackbox Exporter實例
3.2.6.2 Service
1.代碼總覽
- job_name: 'kubernetes-services' metrics_path: /probe params: module: [http_2xx] kubernetes_sd_configs: - role: service relabel_configs: - source_labels: [__meta_kubernetes_service_annotation_prometheus_io_probe] action: keep regex: true - source_labels: [__address__] target_label: __param_target - source_labels: [__param_target] target_label: instance - target_label: __address__ replacement: blackbox-exporter.monitoring.svc.cluster.local:9115 - action: labelmap regex: __meta_kubernetes_service_label_(.+) - source_labels: [__meta_kubernetes_namespace] target_label: kubernetes_namespace - source_labels: [__meta_kubernetes_service_name] target_label: kubernetes_name
獲取打了prometheus_io_probe標記的svc,因為是需要blocker-exporter來獲取監控的svc的信息,所以這里做了2大步:
1.讓prometheus 知道 blackbox-exporter的地址,這樣統計信息
2.知道具體的要監控svc的訪問api地址
這里從relabel_config開始,總共分為8小步
第一步:過濾出用戶標記過的svc.(在service的deploy文件里面標明)
第二步: 這里就是替換掉要監控的svc的訪問api地址
第三步: 第二步和第三步做的是一個連續的事情
第四步:替換掉默認instance信息,默認的是獲取監控數據的地址,不太准確,為了標識清楚,還是要替換,不替換也不太會影響監控結果,只是可能在其它地方需要這些信息的時候不太友好。
第五步:替換掉訪問blackbox-exporter的api url,讓prometheus可以正確訪問
第六七八步: 都是獲取被監控的svc的一些信息
2.正常target狀態
3.步驟拆解
第一步:
- job_name: 'kubernetes-services' metrics_path: /probe params: module: [http_2xx] kubernetes_sd_configs: - role: service
metrics_path: /probe這里是blockbox-exporter的訪問api,可以通過這種方式把路徑加入到prometheus的endpoint的ip地址和端口號后面;
module: [http_2xx]: 一個返回的字符串,一般來檢測接口返回,可以不填,不能亂填
沒有annotation 的注釋,會獲取所有service的信息,但是都不正常
第二步:
- source_labels: [__meta_kubernetes_service_annotation_prometheus_io_probe] action: keep regex: true
__meta_kubernetes_pod_annotation_prometheus_io_probe是 根據 svc的注釋來采集的,只有svc的annotation=prometheus_io_probe(當然,這是自定義的)才能收集到
過濾出帶有annotation的svc
第三步:
- source_labels: [__address__] target_label: __param_target
這里開始就是要替換要監控的svc的地址了,因為source_labels過濾出了要監控的svc,把要監控的svc的地址覆蓋到__param_target標簽,__param_target的標簽就是左邊的target,只是沒有顯式的顯示出來。
還沒替換完成, 但是可以很明顯的看出,多了一個target的信息
第四步:
- source_labels: [__param_target] target_label: instance
把這個默認__param_target的參數的值賦值給 instance,這個值是label里面的一個參數,為了標識清楚,因為默認是獲取監控信息的地址。不替換也不太會影響監控結果,只是可能在其它地方需要信息的時候不太友好。
第五步:
- target_label: __address__ replacement: blackbox-exporter.monitoring.svc.cluster.local:9115
替換掉訪問blackbox-exporter的api url,讓prometheus可以正確訪問
正確地址替換完成
第六步:
- action: labelmap regex: __meta_kubernetes_service_label_(.+) - source_labels: [__meta_kubernetes_namespace] target_label: kubernetes_namespace - source_labels: [__meta_kubernetes_service_name] target_label: kubernetes_name
這里把六、七、八合在一起了,最后3步都是獲取service的標簽
4.監控key總覽
3.2.6.3 Ingress
和service差不多,就做了在匹配路徑等信息的時候有一點小小的改變
1.代碼總覽
- job_name: 'kubernetes-ingresses' metrics_path: /probe params: module: [http_2xx] kubernetes_sd_configs: - role: ingress relabel_configs: - source_labels: [__meta_kubernetes_ingress_annotation_prometheus_io_probe] action: keep regex: true - source_labels: [__meta_kubernetes_ingress_scheme,__address__,__meta_kubernetes_ingress_path] regex: (.+);(.+);(.+) replacement: ${1}://${2}${3} target_label: __param_target - target_label: __address__ replacement: blackbox-exporter.monitoring.svc.cluster.local:9115 - source_labels: [__param_target] target_label: instance - action: labelmap regex: __meta_kubernetes_ingress_label_(.+) - source_labels: [__meta_kubernetes_namespace] target_label: kubernetes_namespace - source_labels: [__meta_kubernetes_ingress_name] target_label: kubernetes_name
獲取打了prometheus_io_probe標記的ingress,因為是需要blocker-exporter來獲取監控的svc的信息,所以這里做了2大步:
1.讓prometheus 知道 blackbox-exporter的地址,這樣統計信息
2.知道具體的要監控ingress的訪問api地址
這里從relabel_config開始,總共分為8小步
第一步:過濾出用戶標記過的ingress.(在ingress的deploy文件里面標明)
第二步: 這里就是替換掉要監控的ingress的訪問api地址
第三步: 第二步和第三步做的是一個連續的事情
第四步: 替換掉訪問blackbox-exporter的api url,讓prometheus可以正確訪問
第五步: 替換掉默認instance信息,默認的是獲取監控數據的地址,不太准確,為了標識清楚,還是要替換,不替換也不太會影響監控結果,只是可能在其它地方需要信息的時候不太友好。
第六七八步: 都是獲取被監控的ingress的一些信息
2.正常target狀態
3.步驟拆解
第一步:
- job_name: 'kubernetes-ingresses' metrics_path: /probe params: module: [http_2xx] kubernetes_sd_configs: - role: ingress
metrics_path: /probe這里是blockbox-exporter的訪問api路徑,可以通過這種方式把路徑加入到prometheus的endpoint的ip地址和端口號后面;
module: [http_2xx]: 一個返回的字符串,一般來檢測接口返回,可以不填,不能亂填
沒有annotation 的注釋,會獲取所有ingress的信息,但是都不正常。(這里只創建了一個ingress所以只有一個ingress實例)
第二步:
- source_labels: [__meta_kubernetes_ingress_annotation_prometheus_io_probe] action: keep regex: true
__meta_kubernetes_pod_annotation_prometheus_io_probe是根據 ingress的注釋來采集的,只有ingress的annotation=prometheus_io_probe(當然,這是自定義的)才能收集到
過濾出帶有annotation的ingress(因為只有一個ingress,所以和上面的結果沒有什么改變)
第三步:
- source_labels: [__meta_kubernetes_ingress_scheme,__address__,__meta_kubernetes_ingress_path] regex: (.+);(.+);(.+) replacement: ${1}://${2}${3} target_label: __param_target
這里開始就是要替換要監控的ingress的地址了,使用source_labels過濾出了要監控的協議(http/https)以及地址還有訪問路徑,把拼接好的要監控ingress的地址 覆蓋到__param_target標簽,__param_target的標簽就是左邊的target,只是沒有顯式的顯示出來。
可以很明顯的看出,多了一個target的信息
第四步:
- target_label: __address__ replacement: blackbox-exporter.monitoring.svc.cluster.local:9115
替換掉訪問blackbox-exporter的api url,讓prometheus可以正確訪問
正確地址替換完成
第五步:
- source_labels: [__param_target] target_label: instance
把這個默認__param_target的參數的值賦值給 instance,這個值是label里面的一個參數,為了標識清楚,因為默認是獲取監控信息的地址。不替換也不太會影響監控結果,只是可能在其它地方需要信息的時候不太友好。
第六步:
- action: labelmap regex: __meta_kubernetes_ingress_label_(.+) - source_labels: [__meta_kubernetes_namespace] target_label: kubernetes_namespace - source_labels: [__meta_kubernetes_ingress_name] target_label: kubernetes_name
這里把六、七、八合在一起了,最后3步都是獲取ingress的標簽
4.監控key總覽
3.2.7 使用endpoints監控service(番外)
apiserver實際上是一種特殊的Service,現在配置一個專門發現普通類型的Service,這里的service必須要有自定義的監控接口,否則無法使用這種方式
由於方式太多相同,且這種方式不會作為主要用途,所以不詳細講解代碼每一步的使用方式
主體配置
- 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
因為默認的prometheus.io/scrape: true,如果用戶沒有自定義做些操作,只有core DNS默認自帶了
所以匹配出來的時候只有core dns
有了上面的例子,發現如果服務沒有自定義的監控度量metric,那么就無法監控,但是有些服務還是可以通過這種方式監控的,比如Redis:
cat >>prometheus-redis-exporter.yaml <<EOF apiVersion: extensions/v1beta1 kind: Deployment metadata: name: redis namespace: abcdocker annotations: prometheus.io/scrape: "true" prometheus.io/port: "9121" spec: template: metadata: labels: app: redis spec: containers: - name: redis image: redis:4 resources: requests: cpu: 100m memory: 100Mi ports: - containerPort: 6379 - name: redis-exporter image: oliver006/redis_exporter:latest resources: requests: cpu: 100m memory: 100Mi ports: - containerPort: 9121 --- kind: Service apiVersion: v1 metadata: name: redis namespace: abcdocker spec: selector: app: redis ports: - name: redis port: 6379 targetPort: 6379 - name: prom port: 9121 targetPort: 9121 EOF
由於Redis服務的metrics接口在redis-exporter 9121上,我們還需要添加prometheus.io/port=9121這樣的annotation
如果redis有metric的監控項,接下來就可以獲取redis的監控值了。
3.3 Kubernetes 集群外監控配置
在集群內和集群外區別不是很大,首先在架構方案,一個prometheus監控多個k8s集群不太合理.但是還是可以實現,只是有些特定監控模塊差需要特定的條件開啟才能監控到,所以在集群外只是列出了一些示例,一般不到萬不得已,不會使用這種模式。
這里僅列出了使用 node模式監控node以及cadvisor,比如pod是pod發現模式,使用了node-exporte,這里獲取的target地址是私網地址,這時,prometheus就無法直接訪問私網地址,本章只是用一些事例來演示和集群內的配置有哪些區別,會配置一個就會配置多個.

- job_name: 'kubernetes-kubelet' #我們這里會跳過https的認證,講道理這里是不需要開始這個配置的,但是在relabel_configs里面, replacement替換的時候不用這個選項 #是無法加上https://的前綴的,其實已經取消了https驗證,但是沒有辦法,在eks上雖然不使用https驗證,但是不用https://api-address #就是無法正常獲取狀態 scheme: https kubernetes_sd_configs: - role: node #因為在集群外,這里就要指定要監控的集群的地址 api_server: "https://1E73E810A71671022BC2EB1A4F79C434.sk1.ap-northeast-1.eks.amazonaws.com:443" tls_config: #雙行注釋代表一般不會用這個文件 ##ca_file: /data/prometheus/test.crt #跳過https認證 insecure_skip_verify: true ##bearer_token: "eyJhbGciOiJSUzI1NiIsImtpZCI6IiJ9.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJtb25pdG9yaW5nIiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZWNyZXQubmFtZSI6InByb21ldGhldXMtdG9rZW4tajg4OG4iLCJrdWJlcm5ldGVzLmlvL3NlcnZpY2VhY2NvdW50L3NlcnZpY2UtYWNjb3VudC5uYW1lIjoicHJvbWV0aGV1cyIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VydmljZS1hY2NvdW50LnVpZCI6IjU3M2ZkNjlhLWIyMGQtMTFlOS05ZmJmLTA2MTU3MjE4YWFjYSIsInN1YiI6InN5c3RlbTpzZXJ2aWNlYWNjb3VudDptb25pdG9yaW5nOnByb21ldGhldXMifQ.fyv8Io7opPXqXv30ZBdnRdAr00XhjEPk8jMldPLbbqx4JUAO5h5_qCG9z8ljnzveIbMWPPspq9YtGzoFtdQbg4EkL7G2w-CYPECHyufEna8UkIHkugBEzb7KLHaKbNzbv5v5Lqv_X7gmY_iJUCO3NTHdnkvBSGOawZwSJ0fVS7F6z79d8ec4sf03tPuER4z77-ItzBa9gwEt7Q-V5oqI_evQ4x4XkwbFVNJ1xZUzUbQaGLOQ4gcRQRXmAJYPDL_lzTyHANR7g5AP1r7-HuynM7LoDgpstdyCcp3pF_RwHrpKBUQMwbzoPELBllrAuiXx9niV3yUbQNyjzWOHdIjkRA" #這里的tls_config方式要寫2遍,原因不明,可能是因為prometheus去監控時需要去做2次驗證 tls_config: insecure_skip_verify: true #獲取RBAC用戶的token,獲取方式jenkins文檔里面有 bearer_token: "eyJhbGciOiJSUzI1NiIsImtpZCI6IiJ9.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJtb25pdG9yaW5nIiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZWNyZXQubmFtZSI6InByb21ldGhldXMtdG9rZW4tajg4OG4iLCJrdWJlcm5ldGVzLmlvL3NlcnZpY2VhY2NvdW50L3NlcnZpY2UtYWNjb3VudC5uYW1lIjoicHJvbWV0aGV1cyIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VydmljZS1hY2NvdW50LnVpZCI6IjU3M2ZkNjlhLWIyMGQtMTFlOS05ZmJmLTA2MTU3MjE4YWFjYSIsInN1YiI6InN5c3RlbTpzZXJ2aWNlYWNjb3VudDptb25pdG9yaW5nOnByb21ldGhldXMifQ.fyv8Io7opPXqXv30ZBdnRdAr00XhjEPk8jMldPLbbqx4JUAO5h5_qCG9z8ljnzveIbMWPPspq9YtGzoFtdQbg4EkL7G2w-CYPECHyufEna8UkIHkugBEzb7KLHaKbNzbv5v5Lqv_X7gmY_iJUCO3NTHdnkvBSGOawZwSJ0fVS7F6z79d8ec4sf03tPuER4z77-ItzBa9gwEt7Q-V5oqI_evQ4x4XkwbFVNJ1xZUzUbQaGLOQ4gcRQRXmAJYPDL_lzTyHANR7g5AP1r7-HuynM7LoDgpstdyCcp3pF_RwHrpKBUQMwbzoPELBllrAuiXx9niV3yUbQNyjzWOHdIjkRA" relabel_configs: - action: labelmap regex: __meta_kubernetes_node_label_(.+) - target_label: __address__ #這里就不需要加一些http或者https了,加了會報錯,只有在scheme配置這里添加 replacement: 1E73E810A71671022BC2EB1A4F79C434.sk1.ap-northeast-1.eks.amazonaws.com:443 - source_labels: [__meta_kubernetes_node_name] target_label: __metrics_path__ replacement: /api/v1/nodes/${1}/proxy/metrics #cadvisor和上面是一樣的 - job_name: 'kubernetes-cadvisor' scheme: https kubernetes_sd_configs: - role: node api_server: "https://1E73E810A71671022BC2EB1A4F79C434.sk1.ap-northeast-1.eks.amazonaws.com:443" tls_config: insecure_skip_verify: true tls_config: insecure_skip_verify: true bearer_token: "eyJhbGciOiJSUzI1NiIsImtpZCI6IiJ9.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJtb25pdG9yaW5nIiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZWNyZXQubmFtZSI6InByb21ldGhldXMtdG9rZW4tajg4OG4iLCJrdWJlcm5ldGVzLmlvL3NlcnZpY2VhY2NvdW50L3NlcnZpY2UtYWNjb3VudC5uYW1lIjoicHJvbWV0aGV1cyIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VydmljZS1hY2NvdW50LnVpZCI6IjU3M2ZkNjlhLWIyMGQtMTFlOS05ZmJmLTA2MTU3MjE4YWFjYSIsInN1YiI6InN5c3RlbTpzZXJ2aWNlYWNjb3VudDptb25pdG9yaW5nOnByb21ldGhldXMifQ.fyv8Io7opPXqXv30ZBdnRdAr00XhjEPk8jMldPLbbqx4JUAO5h5_qCG9z8ljnzveIbMWPPspq9YtGzoFtdQbg4EkL7G2w-CYPECHyufEna8UkIHkugBEzb7KLHaKbNzbv5v5Lqv_X7gmY_iJUCO3NTHdnkvBSGOawZwSJ0fVS7F6z79d8ec4sf03tPuER4z77-ItzBa9gwEt7Q-V5oqI_evQ4x4XkwbFVNJ1xZUzUbQaGLOQ4gcRQRXmAJYPDL_lzTyHANR7g5AP1r7-HuynM7LoDgpstdyCcp3pF_RwHrpKBUQMwbzoPELBllrAuiXx9niV3yUbQNyjzWOHdIjkRA" relabel_configs: - target_label: __address__ replacement: 1E73E810A71671022BC2EB1A4F79C434.sk1.ap-northeast-1.eks.amazonaws.com:443 - source_labels: [__meta_kubernetes_node_name] regex: (.+) target_label: __metrics_path__ replacement: /api/v1/nodes/${1}/proxy/metrics/cadvisor - action: labelmap regex: __meta_kubernetes_node_label_(.+)
集群內集群外更改的就是要指明 k8s的api地址以及 認證方式,這兩點都特別妖孽。甚至有時候不知道為什么要這么樣配置。
接下來講解一些無法使用集群內監控的方式的監控項;比如pod

- job_name: 'kubernetes-pods' kubernetes_sd_configs: - role: pod api_server: "https://1E73E810A71671022BC2EB1A4F79C434.sk1.ap-northeast-1.eks.amazonaws.com:443" tls_config: insecure_skip_verify: true tls_config: insecure_skip_verify: true bearer_token: "eyJhbGciOiJSUzI1NiIsImtpZCI6IiJ9.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJtb25pdG9yaW5nIiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZWNyZXQubmFtZSI6InByb21ldGhldXMtdG9rZW4tajg4OG4iLCJrdWJlcm5ldGVzLmlvL3NlcnZpY2VhY2NvdW50L3NlcnZpY2UtYWNjb3VudC5uYW1lIjoicHJvbWV0aGV1cyIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VydmljZS1hY2NvdW50LnVpZCI6IjU3M2ZkNjlhLWIyMGQtMTFlOS05ZmJmLTA2MTU3MjE4YWFjYSIsInN1YiI6InN5c3RlbTpzZXJ2aWNlYWNjb3VudDptb25pdG9yaW5nOnByb21ldGhldXMifQ.fyv8Io7opPXqXv30ZBdnRdAr00XhjEPk8jMldPLbbqx4JUAO5h5_qCG9z8ljnzveIbMWPPspq9YtGzoFtdQbg4EkL7G2w-CYPECHyufEna8UkIHkugBEzb7KLHaKbNzbv5v5Lqv_X7gmY_iJUCO3NTHdnkvBSGOawZwSJ0fVS7F6z79d8ec4sf03tPuER4z77-ItzBa9gwEt7Q-V5oqI_evQ4x4XkwbFVNJ1xZUzUbQaGLOQ4gcRQRXmAJYPDL_lzTyHANR7g5AP1r7-HuynM7LoDgpstdyCcp3pF_RwHrpKBUQMwbzoPELBllrAuiXx9niV3yUbQNyjzWOHdIjkRA" relabel_configs: - source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_scrape] action: keep regex: true - source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_path] action: replace target_label: __metrics_path__ regex: (.+) - source_labels: [__address__, __meta_kubernetes_pod_annotation_prometheus_io_port] action: replace regex: ([^:]+)(?::\d+)?;(\d+) replacement: $1:$2 target_label: __address__ - action: labelmap regex: __meta_kubernetes_pod_label_(.+) - source_labels: [__meta_kubernetes_namespace] action: replace target_label: kubernetes_namespace - source_labels: [__meta_kubernetes_pod_name] action: replace target_label: kubernetes_pod_name
看看監控pod的結果
獲取的是私網地址,如果prometheus不在一個集群內,無法訪問到
總結:
上述配置已經很復雜了,更變態的是prometheus竟然只支持一個配置文件,因此每加入一個k8s集群的監控,就得往prometheus的配置文件里加入一段上述配置,所以這一章只是演示了一些示例,如果后期真的有這種需求,只能按照示例花時間去摸索.
(push-gateway還未深入使用到監控k8s,本章節預留)
4.標簽問題
經過上面的示例,可以看出就是對標簽的替換和查找,但是就有疑問,不知道標簽的值怎么辦?
所以用以下辦法知道當前實例的所有標簽值。
- job_name: 'kubernetes-kubelet' scheme: https tls_config: ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token kubernetes_sd_configs: - role: node relabel_configs: - action: labelmap regex: .(.+)
以上方式配置之后就可以獲取所有標簽值,標簽可以在prometheus程序的debug模式看。但是會缺少一些標簽。
比較全的標簽在prometheus的后台可以看到
或者在使用pod的發現模式時候,只有安裝對應注解的pod才會出現標簽,這里node-exporter有了相應的注解,並且已經安裝成功
更多標簽問題可以參考以下官方文檔: https://prometheus.io/docs/prometheus/latest/configuration/configuration/#kubernetes_sd_config
5.官方示例
以下最先文檔中的示例,如果在上述文章中講解的有缺失,可以查看以下文章(以下使用的環境是minikube)
5.1 從Kubelet獲取節點運行狀態
Kubelet組件運行在Kubernetes集群的各個節點中,其負責維護和管理節點上Pod的運行狀態。kubelet組件的正常運行直接關系到該節點是否能夠正常的被Kubernetes集群正常使用。
基於Node模式,Prometheus會自動發現Kubernetes中所有Node節點的信息並作為監控的目標Target。 而這些Target的訪問地址實際上就是Kubelet的訪問地址,並且Kubelet實際上直接內置了對Promtheus的支持。
修改prometheus.yml配置文件,並添加以下采集任務配置:
- job_name: 'kubernetes-kubelet' scheme: https tls_config: ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token kubernetes_sd_configs: - role: node relabel_configs: - action: labelmap regex: __meta_kubernetes_node_label_(.+)
這里使用Node模式自動發現集群中所有Kubelet作為監控的數據采集目標,同時通過labelmap步驟,將Node節點上的標簽,作為樣本的標簽保存到時間序列當中。
重新加載promethues配置文件,並重建Promthues的Pod實例后,查看kubernetes-kubelet任務采集狀態,我們會看到以下錯誤提示信息:
Get https://192.168.99.100:10250/metrics: x509: cannot validate certificate for 192.168.99.100 because it doesn't contain any IP SANs
這是由於當前使用的ca證書中,並不包含192.168.99.100的地址信息。為了解決該問題,第一種方法是直接跳過ca證書校驗過程,通過在tls_config中設置 insecure_skip_verify為true即可。 這樣Promthues在采集樣本數據時,將會自動跳過ca證書的校驗過程,從而從kubelet采集到監控數據:
- job_name: 'kubernetes-kubelet' scheme: https tls_config: ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt insecure_skip_verify: true bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token kubernetes_sd_configs: - role: node relabel_configs: - action: labelmap regex: __meta_kubernetes_node_label_(.+)
直接采集kubelet監控指標
第二種方式,不直接通過kubelet的metrics服務采集監控數據,而通過Kubernetes的api-server提供的代理API訪問各個節點中kubelet的metrics服務,如下所示:
- job_name: 'kubernetes-kubelet' scheme: https tls_config: ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token kubernetes_sd_configs: - role: node 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
通過relabeling,將從Kubernetes獲取到的默認地址__address__替換為kubernetes.default.svc:443。同時將__metrics_path__替換為api-server的代理地址/api/v1/nodes/${1}/proxy/metrics。
通過api-server代理獲取kubelet監控指標
通過獲取各個節點中kubelet的監控指標,用戶可以評估集群中各節點的性能表現。例如,通過指標kubelet_pod_start_latency_microseconds可以獲得當前節點中Pod啟動時間相關的統計數據。
kubelet_pod_start_latency_microseconds{quantile="0.99"}
99%的Pod啟動時間
Pod平均啟動時間大致為42s左右(包含鏡像下載時間):
kubelet_pod_start_latency_microseconds_sum / kubelet_pod_start_latency_microseconds_count
Pod平均啟動時間
除此以外,監控指標kubeletdocker*還可以體現出kubelet與當前節點的docker服務的調用情況,從而可以反映出docker本身是否會影響kubelet的性能表現等問題。
5.2 從Kubelet獲取節點容器資源使用情況
各節點的kubelet組件中除了包含自身的監控指標信息以外,kubelet組件還內置了對cAdvisor的支持。cAdvisor能夠獲取當前節點上運行的所有容器的資源使用情況,通過訪問kubelet的/metrics/cadvisor地址可以獲取到cadvisor的監控指標,因此和獲取kubelet監控指標類似,這里同樣通過node模式自動發現所有的kubelet信息,並通過適當的relabel過程,修改監控采集任務的配置。 與采集kubelet自身監控指標相似,這里也有兩種方式采集cadvisor中的監控指標:
方式一:直接訪問kubelet的/metrics/cadvisor地址,需要跳過ca證書認證:
- job_name: 'kubernetes-cadvisor' scheme: https tls_config: ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt insecure_skip_verify: true bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token kubernetes_sd_configs: - role: node relabel_configs: - source_labels: [__meta_kubernetes_node_name] regex: (.+) target_label: __metrics_path__ replacement: metrics/cadvisor - action: labelmap regex: __meta_kubernetes_node_label_(.+)
直接訪問kubelet
方式二:通過api-server提供的代理地址訪問kubelet的/metrics/cadvisor地址:
使用api-server代理
5.3 使用NodeExporter監控集群資源使用情況
為了能夠采集集群中各個節點的資源使用情況,我們需要在各節點中部署一個Node Exporter實例。在本章的“部署Prometheus”小節,我們使用了Kubernetes內置的控制器之一Deployment。Deployment能夠確保Prometheus的Pod能夠按照預期的狀態在集群中運行,而Pod實例可能隨機運行在任意節點上。而與Prometheus的部署不同的是,對於Node Exporter而言每個節點只需要運行一個唯一的實例,此時,就需要使用Kubernetes的另外一種控制器Daemonset。顧名思義,Daemonset的管理方式類似於操作系統中的守護進程。Daemonset會確保在集群中所有(也可以指定)節點上運行一個唯一的Pod實例。
創建node-exporter-daemonset.yml文件,並寫入以下內容:
apiVersion: extensions/v1beta1 kind: DaemonSet metadata: name: node-exporter spec: template: metadata: annotations: prometheus.io/scrape: 'true' prometheus.io/port: '9100' prometheus.io/path: 'metrics' labels: app: node-exporter name: node-exporter spec: containers: - image: prom/node-exporter imagePullPolicy: IfNotPresent name: node-exporter ports: - containerPort: 9100 hostPort: 9100 name: scrape hostNetwork: true hostPID: true
由於Node Exporter需要能夠訪問宿主機,因此這里指定了hostNetwork和hostPID,讓Pod實例能夠以主機網絡以及系統進程的形式運行。同時YAML文件中也創建了NodeExporter相應的Service。這樣通過Service就可以訪問到對應的NodeExporter實例。
$ kubectl create -f node-exporter-daemonset.yml service "node-exporter" created daemonset "node-exporter" created
查看Daemonset以及Pod的運行狀態
$ kubectl get daemonsets NAME DESIRED CURRENT READY UP-TO-DATE AVAILABLE NODE SELECTOR AGE node-exporter 1 1 1 1 1 <none> 15s $ kubectl get pods NAME READY STATUS RESTARTS AGE ... node-exporter-9h56z 1/1 Running 0 51s
由於Node Exporter是以主機網絡的形式運行,因此直接訪問MiniKube的虛擬機IP加上Pod的端口即可訪問當前節點上運行的Node Exporter實例:
$ minikube ip 192.168.99.100 $ curl http://192.168.99.100:9100/metrics ... process_start_time_seconds 1.5251401593e+09 # HELP process_virtual_memory_bytes Virtual memory size in bytes. # TYPE process_virtual_memory_bytes gauge process_virtual_memory_bytes 1.1984896e+08
目前為止,通過Daemonset的形式將Node Exporter部署到了集群中的各個節點中。接下來,我們只需要通過Prometheus的pod服務發現模式,找到當前集群中部署的Node Exporter實例即可。 需要注意的是,由於Kubernetes中並非所有的Pod都提供了對Prometheus的支持,有些可能只是一些簡單的用戶應用,為了區分哪些Pod實例是可以供Prometheus進行采集的,這里我們為Node Exporter添加了注解:
prometheus.io/scrape: 'true'
由於Kubernetes中Pod可能會包含多個容器,還需要用戶通過注解指定用戶提供監控指標的采集端口:
prometheus.io/port: '9100'
而有些情況下,Pod中的容器可能並沒有使用默認的/metrics作為監控采集路徑,因此還需要支持用戶指定采集路徑:
prometheus.io/path: 'metrics'
為Prometheus創建監控采集任務kubernetes-pods,如下所示:
- job_name: 'kubernetes-pods' kubernetes_sd_configs: - role: pod relabel_configs: - source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_scrape] action: keep regex: true - source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_path] action: replace target_label: __metrics_path__ regex: (.+) - source_labels: [__address__, __meta_kubernetes_pod_annotation_prometheus_io_port] action: replace regex: ([^:]+)(?::\d+)?;(\d+) replacement: $1:$2 target_label: __address__ - action: labelmap regex: __meta_kubernetes_pod_label_(.+) - source_labels: [__meta_kubernetes_namespace] action: replace target_label: kubernetes_namespace - source_labels: [__meta_kubernetes_pod_name] action: replace target_label: kubernetes_pod_name
通過Pod模式自動發現Node Exporter實例
通過以上relabel過程實現對Pod實例的過濾,以及采集任務地址替換,從而實現對特定Pod實例監控指標的采集。需要說明的是kubernetes-pods並不是只針對Node Exporter而言,對於用戶任意部署的Pod實例,只要其提供了對Prometheus的支持,用戶都可以通過為Pod添加注解的形式為其添加監控指標采集的支持。
5.4 從kube-apiserver獲取集群運行監控指標
在開始正式內容之前,我們需要先了解一下Kubernetes中Service是如何實現負載均衡的,如下圖所示,一般來說Service有兩個主要的使用場景:
Service負載均衡
- 代理對集群內部應用Pod實例的請求:當創建Service時如果指定了標簽選擇器,Kubernetes會監聽集群中所有的Pod變化情況,通過Endpoints自動維護滿足標簽選擇器的Pod實例的訪問信息;
- 代理對集群外部服務的請求:當創建Service時如果不指定任何的標簽選擇器,此時需要用戶手動創建Service對應的Endpoint資源。例如,一般來說,為了確保數據的安全,我們通常講數據庫服務部署到集群外。 這是為了避免集群內的應用硬編碼數據庫的訪問信息,這是就可以通過在集群內創建Service,並指向外部的數據庫服務實例。
kube-apiserver扮演了整個Kubernetes集群管理的入口的角色,負責對外暴露Kubernetes API。kube-apiserver組件一般是獨立部署在集群外的,為了能夠讓部署在集群內的應用(kubernetes插件或者用戶應用)能夠與kube-apiserver交互,Kubernetes會默認在命名空間下創建一個名為kubernetes的服務,如下所示:
$ kubectl get svc kubernetes -o wide NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 166d <none>
而該kubernetes服務代理的后端實際地址通過endpoints進行維護,如下所示:
$ kubectl get endpoints kubernetes
NAME ENDPOINTS AGE
kubernetes 10.0.2.15:8443 166d
通過這種方式集群內的應用或者系統主機就可以通過集群內部的DNS域名kubernetes.default.svc訪問到部署外部的kube-apiserver實例。
因此,如果我們想要監控kube-apiserver相關的指標,只需要通過endpoints資源找到kubernetes對應的所有后端地址即可。
如下所示,創建監控任務kubernetes-apiservers,這里指定了服務發現模式為endpoints。Promtheus會查找當前集群中所有的endpoints配置,並通過relabel進行判斷是否為apiserver對應的訪問地址:
- job_name: 'kubernetes-apiservers' 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 - target_label: __address__ replacement: kubernetes.default.svc:443
在relabel_configs配置中第一步用於判斷當前endpoints是否為kube-apiserver對用的地址。第二步,替換監控采集地址到kubernetes.default.svc:443即可。重新加載配置文件,重建Promthues實例,得到以下結果。
apiserver任務狀態
5.5 對Ingress和Service進行網絡探測
為了能夠對Ingress和Service進行探測,我們需要在集群部署Blackbox Exporter實例。如下所示,創建blackbox-exporter.yaml用於描述部署相關的內容:
apiVersion: v1 kind: Service metadata: labels: app: blackbox-exporter name: blackbox-exporter spec: ports: - name: blackbox port: 9115 protocol: TCP selector: app: blackbox-exporter type: ClusterIP --- apiVersion: extensions/v1beta1 kind: Deployment metadata: labels: app: blackbox-exporter name: blackbox-exporter spec: replicas: 1 selector: matchLabels: app: blackbox-exporter template: metadata: labels: app: blackbox-exporter spec: containers: - image: prom/blackbox-exporter imagePullPolicy: IfNotPresent name: blackbox-exporter
通過kubectl命令部署Blackbox Exporter實例,這里將部署一個Blackbox Exporter的Pod實例,同時通過服務blackbox-exporter在集群內暴露訪問地址blackbox-exporter.default.svc.cluster.local,對於集群內的任意服務都可以通過該內部DNS域名訪問Blackbox Exporter實例:
$ kubectl get pods NAME READY STATUS RESTARTS AGE blackbox-exporter-f77fc78b6-72bl5 1/1 Running 0 4s $ kubectl get svc NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE blackbox-exporter ClusterIP 10.109.144.192 <none> 9115/TCP 3m
為了能夠讓Prometheus能夠自動的對Service進行探測,我們需要通過服務發現自動找到所有的Service信息。 如下所示,在Prometheus的配置文件中添加名為kubernetes-services的監控采集任務:
- job_name: 'kubernetes-services' metrics_path: /probe params: module: [http_2xx] kubernetes_sd_configs: - role: service relabel_configs: - source_labels: [__meta_kubernetes_service_annotation_prometheus_io_probe] action: keep regex: true - source_labels: [__address__] target_label: __param_target - target_label: __address__ replacement: blackbox-exporter.default.svc.cluster.local:9115 - source_labels: [__param_target] target_label: instance - action: labelmap regex: __meta_kubernetes_service_label_(.+) - source_labels: [__meta_kubernetes_namespace] target_label: kubernetes_namespace - source_labels: [__meta_kubernetes_service_name] target_label: kubernetes_name
在該任務配置中,通過指定kubernetes_sd_config的role為service指定服務發現模式:
kubernetes_sd_configs:
- role: service
為了區分集群中需要進行探測的Service實例,我們通過標簽‘prometheus.io/probe: true’進行判斷,從而過濾出需要探測的所有Service實例:
- source_labels: [__meta_kubernetes_service_annotation_prometheus_io_probe] action: keep regex: true
並且將通過服務發現獲取到的Service實例地址__address__轉換為獲取監控數據的請求參數。同時將__address執行Blackbox Exporter實例的訪問地址,並且重寫了標簽instance的內容:
- source_labels: [__address__] target_label: __param_target - target_label: __address__ replacement: blackbox-exporter.default.svc.cluster.local:9115 - source_labels: [__param_target] target_label: instance
最后,為監控樣本添加了額外的標簽信息:
- action: labelmap regex: __meta_kubernetes_service_label_(.+) - source_labels: [__meta_kubernetes_namespace] target_label: kubernetes_namespace - source_labels: [__meta_kubernetes_service_name] target_label: kubernetes_name
對於Ingress而言,也是一個相對類似的過程,這里給出對Ingress探測的Promthues任務配置作為參考:
- job_name: 'kubernetes-ingresses' metrics_path: /probe params: module: [http_2xx] kubernetes_sd_configs: - role: ingress relabel_configs: - source_labels: [__meta_kubernetes_ingress_annotation_prometheus_io_probe] action: keep regex: true - source_labels: [__meta_kubernetes_ingress_scheme,__address__,__meta_kubernetes_ingress_path] regex: (.+);(.+);(.+) replacement: ${1}://${2}${3} target_label: __param_target - target_label: __address__ replacement: blackbox-exporter.default.svc.cluster.local:9115 - source_labels: [__param_target] target_label: instance - action: labelmap regex: __meta_kubernetes_ingress_label_(.+) - source_labels: [__meta_kubernetes_namespace] target_label: kubernetes_namespace - source_labels: [__meta_kubernetes_ingress_name] target_label: kubernetes_name