监控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
posted @ 2021-11-20 18:54  小家电维修  阅读(1140)  评论(0编辑  收藏  举报