• 监控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
  • 相关阅读:
    Vector3函数理解-计算两向量之间的角度
    Android报错Type Error executing aapt: Return code -1
    android中 onResume()方法什么时候执行 ??(转)
    自行实现Kinect 手势Demo踩的坑
    Kinect 2.0 默认姿势的中文意思
    C#限制float有两位小数
    Android View 从左边滑出动画 ,以及从左上,左下,右上,右下放大动画。
    注册谷歌账户时最后一步验证账户输入手机号说此电话号码无法用于进行验证,如何解决?
    Mac使用sonarqube进行代码检测
    Unable to find method 'org.gradle.api.tasks.TaskInputs.file
  • 原文地址:https://www.cnblogs.com/lizexiong/p/15582280.html
Copyright © 2020-2023  润新知