監控kubernetes集群的方式


 

  導航:這里主要是列出一個prometheus一些系統的學習過程,最后按照章節順序查看,由於寫作該文檔經歷了不同時期,所以在文中有時出現

的雲環境不統一,但是學習具體使用方法即可,在最后的篇章,有一個完整的騰訊雲的實戰案例。

  1.什么是prometheus?

  2.Prometheus安裝

  3.Prometheus的Exporter詳解

  4.Prometheus的PromQL

  5.Prometheus告警處理

  6.Prometheus的集群與高可用

  7.Prometheus服務發現

  8.kube-state-metrics 和 metrics-server

  9.監控kubernetes集群的方式

  10.prometheus operator

  11.Prometheus實戰之聯邦+高可用+持久

  12.Prometheus實戰之配置匯總

  13.Grafana簡單用法

  14.Grafana SQL匯總

  15.prometheus SQL匯總

  參考:

  https://prometheus.io/docs/prometheus/latest/configuration/configuration/#kubernetes_sd_config

  https://yunlzheng.gitbook.io/prometheus-book/part-iii-prometheus-shi-zhan/readmd/use-prometheus-monitor-kubernetes

  https://www.bookstack.cn/read/prometheus_practice/introduction-README.md

  https://www.kancloud.cn/huyipow/prometheus/521184

  https://www.qikqiak.com/k8s-book/docs/

 

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
prometheus-configmap.yml

 

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
prometheus-deployment.yaml

  安裝完成后使用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  
prometheus-rbac-setup.yml

  其中需要注意的是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-configamp.yaml

  更新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監控配置

  看看監控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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM