Kubernetes集群监控-详解Prometheus高效监控

2023-11-11 10:53:04 浏览数 (3)

虚拟化运维KubernetesPrometheus

Kubernetes集群监控-详解Prometheus高效监控

王先森2023-11-102023-11-10

Prometheus简介

Prometheus 最初是 SoundCloud 构建的开源系统监控和报警工具,是一个独立的开源项目,于 2016 年加入了 CNCF 基金会,作为继 Kubernetes 之后的第二个托管项目。Prometheus 相比于其他传统监控工具主要有以下几个特点:

  • 具有由 metric 名称和键/值对标识的时间序列数据的多维数据模型
  • 有一个灵活的查询语言
  • 不依赖分布式存储,只和本地磁盘有关
  • 通过 HTTP 的服务拉取时间序列数据
  • 也支持推送的方式来添加时间序列数据
  • 还支持通过服务发现或静态配置发现目标
  • 多种图形和仪表板支持

Prometheus 由多个组件组成,但是其中有些组件是可选的:

  • Prometheus Server:用于抓取指标、存储时间序列数据
  • exporter:暴露指标让任务来抓
  • pushgateway:push 的方式将指标数据推送到该网关
  • alertmanager:处理报警的报警组件 adhoc:用于数据查询

大多数 Prometheus 组件都是用 Go 编写的,因此很容易构建和部署为静态的二进制文件。下图是 Prometheus 官方提供的架构及其一些相关的生态系统组件:

整体流程比较简单,Prometheus 直接接收或者通过中间的 Pushgateway 网关被动获取指标数据,在本地存储所有的获取的指标数据,并对这些数据进行一些规则整理,用来生成一些聚合数据或者报警信息,Grafana 或者其他工具用来可视化这些数据。

部署Prometheus

创建资源配置清单

ConfigMapDeploymentPV/PVCRBACServiceIngress

为了能够方便的管理配置文件,这里将 prometheus.yml 文件用 ConfigMap 的形式进行管理:

代码语言:javascript复制
# prometheus-cm.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: prometheus-config
  namespace: infra
data:
  prometheus.yml: |
    global:
      scrape_interval: 15s      # 每隔15秒抓取一次
      scrape_timeout: 15s       # 抓取数据超时时间
    scrape_configs:
    - job_name: 'prometheus'
      static_configs:
      - targets: ['localhost:9090']
代码语言:javascript复制
# prometheus-dp.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    name: prometheus
  name: prometheus
  namespace: infra
spec:
  progressDeadlineSeconds: 600
  replicas: 1
  revisionHistoryLimit: 7
  selector:
    matchLabels:
      app: prometheus
  strategy:
    rollingUpdate:
      maxSurge: 1
      maxUnavailable: 1
    type: RollingUpdate
  template:
    metadata:
      labels:
        app: prometheus
    spec:
      nodeName: k8s-master1                           # 固定到k8s-master1 节点上
      tolerations:                                    # 污点容忍
      - key: "node.kubernetes.io/unschedulable"       # 污点的key是node.kubernetes.io/unschedulable
        operator: "Exists"                            # 容忍所有含污点的node
        effect: "NoSchedule"
      initContainers:                                 # 初始化容器,修改data目录权限,也可以通过securityContext设置runAsUser=0指定运行的用户为root,避免权限不足。
      - name: fix-permissions
        image: busybox
        command: ["sh", "-c", "chown -R nobody:nobody /data"]
        volumeMounts:
        - name: data
          mountPath: /data
      containers:
      - name: prometheus
        image: prom/prometheus:v2.47.2
        imagePullPolicy: IfNotPresent
        command:
        - /bin/prometheus
        args:
        - '--config.file=/etc/prometheus/prometheus.yml'
        - '--storage.tsdb.path=/data/prom-db'
        - '--storage.tsdb.retention=24h'
        - '--storage.tsdb.min-block-duration=10m'
        - '--web.enable-admin-api' # 控制对admin HTTP API的访问,其中包括删除时间序列等功能
        - '--web.enable-lifecycle' # 支持热更新,直接执行localhost:9090/-/reload立即生效
        ports:
        - containerPort: 9090
          protocol: TCP
          name: http
        volumeMounts:
        - mountPath: /etc/prometheus/
          name: config-volume
        - mountPath: /data/
          name: data
        resources:
          requests:
            cpu: "100m"
            memory: "512Mi"
          limits:
            cpu: "500m"
            memory: "1Gi"
      serviceAccountName: prometheus
      volumes:
      - name: data
        persistentVolumeClaim:
          claimName: prometheus-data
      - name: config-volume
        configMap:
          name: prometheus-config

prometheus 的性能和数据持久化这里是直接将通过一个 LocalPV 来进行数据持久化的,通过 --storage.tsdb.path=/data/prom-db 指定数据目录,

代码语言:javascript复制
# prometheus-pvc.yaml
apiVersion: v1
kind: PersistentVolume
metadata:
  name: prometheus-local
  labels:
    app: prometheus
spec:
  accessModes:
    - ReadWriteOnce
  capacity:
    storage: 20Gi
  storageClassName: local-storage
  local:
    path: /data/k8s/prometheus               # 挂在本地目录
  nodeAffinity:
    required:
      nodeSelectorTerms:                     # 节点亲和性
        - matchExpressions:                  
            - key: kubernetes.io/hostname
              operator: In
              values:
                - k8s-master1                # 固定到k8s-master1节点上
  persistentVolumeReclaimPolicy: Retain
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: prometheus-data
  namespace: infra
spec:
  selector:
    matchLabels:
      app: prometheus
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 5Gi
  storageClassName: local-storage

prometheus 可以访问 Kubernetes 的一些资源对象,所以需要配置 rbac 相关认证,这里,使用了一个名为 prometheus 的 serviceAccount 对象

代码语言:javascript复制
# prometheus-rbac.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
  name: prometheus
  namespace: infra
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: prometheus
rules:
- apiGroups:
  - ""
  resources:
  - nodes
  - nodes/metrics
  - services
  - endpoints
  - pods
  verbs:
  - get
  - list
  - watch
- apiGroups:
  - ""
  resources:
  - configmaps
  verbs:
  - get
- nonResourceURLs:
  - /metrics
  verbs:
  - get
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: prometheus
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: prometheus
subjects:
- kind: ServiceAccount
  name: prometheus
  namespace: infra
代码语言:javascript复制
# prometheus-svc.yaml
apiVersion: v1
kind: Service
metadata:
  annotations:                            # 通过endpoints 自动发现时使用
    prometheus.io/port: "9090"            # 监听端口
    prometheus.io/scrape: "true"          # 是否开启监控
    prometheus.io/path: "/metrics"        # 监控路径
  name: prometheus
  namespace: infra
spec:
  ports:
  - port: 9090
    protocol: TCP
    targetPort: 9090
  selector:
    app: prometheus
代码语言:javascript复制
# prometheus-ing.yaml
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
  name: prometheus-web
  namespace: infra
spec:
  entryPoints:
    - web
  routes:
    - match: Host(`prometheus.od.com`)
      kind: Rule
      services:
        - name: prometheus
          port: 9090

应用资源配置清单

代码语言:javascript复制
# 创建挂载目录
mkdir /data/k8s/prometheus/ -p

# 创建NameSpaces
kubectl create namespace infra

# 应用资源配置清单
kubectl apply -f .

创建完成可以通过本地hosts文件绑定域名进行访问:http://prometheus.od.com

现在可以查看当前监控系统中的一些监控目标(Status -> Targets):

应用监控

Prometheus 的数据指标是通过一个公开的 HTTP(S) 数据接口获取到的,不需要单独安装监控的 agent,只需要暴露一个 metrics 接口,Prometheus 就会定期去拉取数据;对于一些普通的 HTTP 服务,完全可以直接重用这个服务,添加一个 /metrics 接口暴露给 Prometheus;而且获取到的指标数据格式是非常易懂的,不需要太高的学习成本。

现在很多服务从一开始就内置了一个 /metrics 接口,比如 Kubernetes 的各个组件、istio 服务网格都直接提供了数据指标接口。有一些服务即使没有原生集成该接口,也完全可以使用一些 exporter 来获取到指标数据,比如 mysqld_exporternode_exporter,这些 exporter 就有点类似于传统监控服务中的 agent,作为服务一直存在,用来收集目标服务的指标数据然后直接暴露给 Prometheus。

静态监控

官方抓取配置文档:https://prometheus.io/docs/prometheus/latest/configuration/configuration/#scrape_config

官方静态配置文档:https://prometheus.io/docs/prometheus/latest/configuration/configuration/#static_config

应用只需要能够提供一个满足 prometheus 格式要求的 /metrics 接口就可以让 Prometheus 来接管监控,比如 Kubernetes 集群中非常重要的 ETCD集群,一般默认情况下就开启了 /metrics 接口,将/metrics接口配置到prometheus.yml 中去,直接加到默认的 prometheus 这个 job 下面:

代码语言:javascript复制
apiVersion: v1
kind: ConfigMap
metadata:
  name: prometheus-config
  namespace: infra
data:
  prometheus.yml: |
    global:
      scrape_interval: 15s
      scrape_timeout: 15s
    scrape_configs:
    - job_name: 'etcd'
      tls_config:                                   # 配置抓取所有证书
        ca_file: /data/ssl/ca.pem
        cert_file: /data/ssl/server.pem
        key_file: /data/ssl/server-key.pem
      scheme: https                                 # 通过HTTPS协议抓取
      static_configs:
      - targets:
        - '10.1.1.100:2379'
        labels:
          instance: etcd-server-1                  # 创建instance标签
      - targets:
        - '10.1.1.120:2379'
        labels:
          instance: etcd-server-2
      - targets:
        - '10.1.1.130:2379'
        labels:
          instance: etcd-server-3

重新更新这个 ConfigMap 资源对象

代码语言:javascript复制
kubectl apply -f prometheus-cm.yaml

由于之前的 Prometheus 启动参数中添加了 --web.enable-lifecycle 参数,所以现在只需要执行一个 reload 命令即可让配置生效:

代码语言:javascript复制
curl -X POST "http://prometheus.od.com/-/reload"

由于 ConfigMap 通过 Volume 的形式挂载到 Pod 中去的热更新需要一定的间隔时间才会生效,所以需要稍微等一小会儿。

可以看到刚刚添加的 etcd 这个任务已经出现了,然后同样的可以切换到 Graph 下面去,可以找到一些 etcd 的指标数据,

使用 exporter 监控

上面也说过有一些应用可能没有自带 /metrics 接口供 Prometheus 使用,在这种情况下,就需要利用 exporter 服务来为 Prometheus 提供指标数据了。Prometheus 官方为许多应用就提供了对应的 exporter 应用,也有许多第三方的实现,可以前往官方网站进行查看:exporters,当然如果你的应用本身也没有 exporter 实现,那么就要自己想办法去实现一个 /metrics 接口了,只要你能提供一个合法的 /metrics 接口,Prometheus 就可以监控你的应用。

比如这里通过一个 redis-exporter 的服务来监控 redis 服务,对于这类应用,一般会以 sidecar 的形式和主应用部署在同一个 Pod 中,比如这里来部署一个 redis 应用,并用 redis-exporter 的方式来采集监控数据供 Prometheus 使用,如下资源清单文件:

代码语言:javascript复制
# prome-redis.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: redis
  namespace: monitor
spec:
  selector:
    matchLabels:
      app: redis
  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: monitor
spec:
  selector:
    app: redis
  ports:
    - name: redis
      port: 6379
      targetPort: 6379
    - name: prom
      port: 9121
      targetPort: 9121

可以看到上面在 redis 这个 Pod 中包含了两个容器,一个就是 redis 本身的主应用,另外一个容器就是 redis_exporter。现在直接创建上面的应用:

代码语言:javascript复制
$ kubectl apply -f prome-redis.yaml
deployment.apps/redis created
service/redis created

创建完成后,可以看到 redis 的 Pod 里面包含有两个容器:

代码语言:javascript复制
$ kubectl get pods -n monitor
NAME                          READY   STATUS    RESTARTS   AGE
redis-7c8bdd45cc-ssjbz        2/2     Running   0          2m1s
$ kubectl get svc -n monitor
NAME         TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)             AGE
redis        ClusterIP   192.168.11.251   <none>        6379/TCP,9121/TCP   2m14s

可以通过 9121 端口来校验是否能够采集到数据:

代码语言:javascript复制
$ curl 172.16.120.15:9121/metrics
# HELP go_gc_duration_seconds A summary of the GC invocation durations.
# TYPE go_gc_duration_seconds summary
go_gc_duration_seconds{quantile="0"} 0
go_gc_duration_seconds{quantile="0.25"} 0
go_gc_duration_seconds{quantile="0.5"} 0
go_gc_duration_seconds{quantile="0.75"} 0
go_gc_duration_seconds{quantile="1"} 0
go_gc_duration_seconds_sum 0
go_gc_duration_seconds_count 0
......
# HELP redis_up Information about the Redis instance
# TYPE redis_up gauge
redis_up 1
# HELP redis_uptime_in_seconds uptime_in_seconds metric
# TYPE redis_uptime_in_seconds gauge
redis_uptime_in_seconds 100

同样的,现在只需要更新 Prometheus 的配置文件:

代码语言:javascript复制
- job_name: 'redis'
  static_configs:
    - targets: ['redis.monitor:9121']

由于这里是通过 Service 去配置的 redis 服务,当然直接配置 Pod IP 也是可以的,因为和 Prometheus 处于同一个 namespace,所以直接使用 servicename 即可。配置文件更新后,重新加载:

代码语言:javascript复制
$ kubectl apply -f prometheus-cm.yaml
configmap/prometheus-config configured
# 隔一会儿执行reload操作
$ curl -X POST "http://prometheus.od.com/-/reload"

这个时候再去看 Prometheus 的 Dashboard 中查看采集的目标数据:

可以看到配置的 redis 这个 job 已经生效了。切换到 Graph 下面可以看到很多关于 redis 的指标数据,选择任意一个指标,比如 redis_exporter_scrapes_total,然后点击执行就可以看到对应的数据图表了:

集群节点

对于集群的监控一般需要考虑以下几个方面:

  • Kubernetes 节点的监控:比如节点的 cpu、load、disk、memory 等指标
  • 内部系统组件的状态:比如 kube-scheduler、kube-controller-manager、kubedns/coredns 等组件的详细运行状态
  • 编排级的 metrics:比如 Deployment 的状态、资源请求、调度和 API 延迟等数据指标

Kubernetes 集群的监控方案目前主要有以下几种方案:

  • Heapster:Heapster 是一个集群范围的监控和数据聚合工具,以 Pod 的形式运行在集群中。 heapster 除了 Kubelet/cAdvisor 之外,还可以向 Heapster 添加其他指标源数据,比如 kube-state-metrics,需要注意的是 Heapster 已经被废弃了,后续版本中会使用 metrics-server 代替。
  • cAdvisor:cAdvisor 是 Google 开源的容器资源监控和性能分析工具,它是专门为容器而生,本身也支持 Docker 容器。
  • kube-state-metrics:kube-state-metrics 通过监听 API Server 生成有关资源对象的状态指标,比如 Deployment、Node、Pod,需要注意的是 kube-state-metrics 只是简单提供一个 metrics 数据,并不会存储这些指标数据,所以可以使用 Prometheus 来抓取这些数据然后存储。
  • metrics-server:metrics-server 也是一个集群范围内的资源数据聚合工具,是 Heapster 的替代品,同样的,metrics-server 也只是显示数据,并不提供数据存储服务。

不过 kube-state-metrics 和 metrics-server 之间还是有很大不同的,二者的主要区别如下:

  • kube-state-metrics 主要关注的是业务相关的一些元数据,比如 Deployment、Pod、副本状态等
  • metrics-server 主要关注的是资源度量 API 的实现,比如 CPU、文件描述符、内存、请求延时等指标。

监控集群节点

Prometheus 采集节点的监控指标数据,可以通过 node_exporter 来获取,顾名思义,node_exporter 就是抓取用于采集服务器节点的各种运行指标,目前 node_exporter 支持几乎所有常见的监控点,比如 conntrack,cpu,diskstats,filesystem,loadavg,meminfo,netstat 等,详细的监控点列表可以参考其 Github 仓库。

可以通过 DaemonSet 控制器来部署该服务,这样每一个节点都会自动运行一个这样的 Pod,如果从集群中删除或者添加节点后,也会进行自动扩展。

在部署 node-exporter 的时候有一些细节需要注意,如下资源清单文件:

代码语言:javascript复制
apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: node-exporter
  namespace: kube-system
  labels:
    app: node-exporter
spec:
  selector:
    matchLabels:
      app: node-exporter
  template:
    metadata:
      labels:
        app: node-exporter
    spec:
      hostPID: true
      hostIPC: true
      hostNetwork: true
      nodeSelector:
        kubernetes.io/os: linux
      containers:
        - name: node-exporter
          image: prom/node-exporter:v1.6.1
          args:
            - --web.listen-address=$(HOSTIP):9100
            - --path.procfs=/host/proc
            - --path.sysfs=/host/sys
            - --path.rootfs=/host/root
            - --no-collector.hwmon # 禁用不需要的采集器
            - --no-collector.nfs
            - --no-collector.nfsd
            - --no-collector.nvme
            - --no-collector.dmi
            - --no-collector.arp
            - --collector.filesystem.ignored-mount-points=^/(dev|proc|sys|var/lib/containerd/. |/var/lib/docker/. |var/lib/kubelet/pods/. )($|/)
            - --collector.filesystem.ignored-fs-types=^(autofs|binfmt_misc|cgroup|configfs|debugfs|devpts|devtmpfs|fusectl|hugetlbfs|mqueue|overlay|proc|procfs|pstore|rpc_pipefs|securityfs|sysfs|tracefs)$
          ports:
            - containerPort: 9100
          env:
            - name: HOSTIP
              valueFrom:
                fieldRef:
                  fieldPath: status.hostIP
          resources:
            requests:
              cpu: 150m
              memory: 180Mi
            limits:
              cpu: 150m
              memory: 180Mi
          securityContext:
            runAsNonRoot: true
            runAsUser: 65534
          volumeMounts:
            - name: proc
              mountPath: /host/proc
            - name: sys
              mountPath: /host/sys
            - name: root
              mountPath: /host/root
              mountPropagation: HostToContainer
              readOnly: true
      tolerations:
        - operator: 'Exists'
      volumes:
        - name: proc
          hostPath:
            path: /proc
        - name: dev
          hostPath:
            path: /dev
        - name: sys
          hostPath:
            path: /sys
        - name: root
          hostPath:
            path: /

要获取到的数据是主机的监控指标数据,而 node-exporter 是运行在容器中的,所以在 Pod 中需要配置一些 Pod 的安全策略,这里就添加了 hostPID: truehostIPC: truehostNetwork: true 3 个策略,用来使用主机的 PID namespaceIPC namespace 以及主机网络,这些 namespace 就是用于容器隔离的关键技术,要注意这里的 namespace 和集群中的 namespace 是两个完全不相同的概念。

另外还将主机的 /dev/proc/sys这些目录挂载到容器中,这些因为采集的很多节点数据都是通过这些文件夹下面的文件来获取到的,比如在使用 top 命令可以查看当前 cpu 使用情况,数据就来源于文件 /proc/stat,使用 free 命令可以查看当前内存使用情况,其数据来源是来自 /proc/meminfo 文件。

代码语言:javascript复制
$ kubectl get pods -n kube-system -l app=node-exporter -o wide
NAME                  READY   STATUS    RESTARTS      AGE   IP           NODE          NOMINATED NODE   READINESS GATES
node-exporter-q9bq8   1/1     Running   1 (27h ago)   27h   10.1.1.130   k8s-node2     <none>           <none>
node-exporter-wlwk9   1/1     Running   1 (27h ago)   27h   10.1.1.100   k8s-master1   <none>           <none>
node-exporter-xr47x   1/1     Running   1 (27h ago)   27h   10.1.1.120   k8s-node1     <none>           <none>

部署完成后,可以看到在几个节点上都运行了一个 Pod,由于指定了 hostNetwork=true,所以在每个节点上就会绑定一个端口 9100,可以通过这个端口去获取到监控指标数据:

代码语言:javascript复制
$ curl 10.1.1.100:9100/metrics
......
# TYPE node_os_info gauge
node_os_info{build_id="",id="centos",id_like="rhel fedora",image_id="",image_version="",name="CentOS Linux",pretty_name="CentOS Linux 7 (Core)",variant="",variant_id="",version="7 (Core)",version_codename="",version_id="7"} 1

自动服务发现

在 Kubernetes 下,Promethues 通过与 Kubernetes API 集成,主要支持 5 中服务发现模式,分别是:NodeServicePodEndpointsIngress。不同的服务发现模式适用于不同的场景,例如:Node 适用于与主机相关的监控资源,如节点中运行的Kubernetes 组件状态、节点上运行的容器状态等;ServiceIngress 适用于通过黑盒监控的场景,如对服务的可用性以及服务质量的监控;EndpointsPod 均可用于获取 Pod 实例的监控数据,如监控用户或者管理员部署的支持 Prometheus 的应用。

通过 kubectl 命令可以很方便的获取到当前集群中的所有节点信息:

代码语言:javascript复制
$ kubectl get nodes
NAME          STATUS                     ROLES    AGE   VERSION
k8s-master1   Ready,SchedulingDisabled   <none>   44d   v1.23.6
k8s-node1     Ready                      <none>   44d   v1.23.6
k8s-node2     Ready                      <none>   44d   v1.23.6

但是要让 Prometheus 也能够获取到当前集群中的所有节点信息的话,就需要利用 Node 的服务发现模式,同样的,在 prometheus.yml 文件中配置如下的 job 任务即可:

代码语言:javascript复制
- job_name: 'k8s-nodes'
  kubernetes_sd_configs:
    - role: node

通过指定 kubernetes_sd_configs 的模式为 node,Prometheus 就会自动从 Kubernetes 中发现所有的 node 节点并作为当前 job 监控的目标实例,发现的节点 /metrics 接口是默认的 kubelet 的 HTTP 接口。

prometheus 的 ConfigMap 更新完成后,同样的执行 reload 操作,让配置生效:

代码语言:javascript复制
$ kubectl apply -f prometheus-cm.yaml
configmap/prometheus-config configured
# 隔一会儿执行reload操作
$ curl -X POST "http://prometheus.od.com/-/reload"

可以看到上面的 k8s-nodes 这个 job 任务已经自动发现了 3 个 node 节点,但是在获取数据的时候失败了。

这个是因为 prometheus 去发现 Node 模式的服务的时候,访问的端口默认是 10250,而默认是需要认证的 https 协议才有权访问的,但实际上并不是希望让去访问 10250 端口的 /metrics 接口,而是 node-exporter 绑定到节点的 9100 端口,所以应该将这里的 10250 替换成 9100端口。

需要使用到 Prometheus 提供的 relabel_configs 中的 replace 能力了,relabel 可以在 Prometheus 采集数据之前,通过 Target 实例的 Metadata 信息,动态重新写入 Label 的值。除此之外,还能根据 Target 实例的 Metadata 信息选择是否采集或者忽略该 Target 实例。比如这里就可以去匹配 __address__ 这个 Label 标签,然后替换掉其中的端口,如果你不知道有哪些 Label 标签可以操作的话,可以在 Service Discovery 页面获取到相关的元标签,这些标签都是可以进行 Relabel 的标签:

代码语言:javascript复制
- job_name: 'k8s-nodes'
  kubernetes_sd_configs:
    - role: node
  relabel_configs:
    - source_labels: [__address__]
      regex: '(.*):10250'
      replacement: '${1}:9100'
      target_label: __address__
      action: replace
    - action: labelmap
      regex: __meta_kubernetes_node_label_(. )

这个正则表达式表示:去匹配 __address__ 这个标签,然后将 host 部分保留下来,port 替换成了 9100,重新更新配置文件,执行 reload 操作,然后再去看 Prometheus 的 Dashboard 的 Targets 路径下面 kubernetes-nodes 这个 job 任务是否正常了:

可以看到现在已经正常了,但是还有一个问题就是采集的指标数据 Label 标签中内容缺少,这对于在进行监控分组分类查询的时候带来了很多不方便的地方,要是能够将集群中 Node 节点的 Label 标签也能获取到就很好了。这里可以通过 labelmap 这个属性来将 Kubernetes 的 Label 标签添加为 Prometheus 的指标数据的标签:

代码语言:javascript复制
- job_name: 'k8s-nodes'
  kubernetes_sd_configs:
    - role: node
  relabel_configs:
    - source_labels: [__address__]
      regex: '(.*):10250'
      replacement: '${1}:9100'
      target_label: __address__
      action: replace
    - action: labelmap
      regex: __meta_kubernetes_node_label_(. )

添加了一个 action 为 labelmap,正则表达式是 __meta_kubernetes_node_label_(. ) 的配置,这里的意思就是表达式中匹配都的数据也添加到指标数据的 Label 标签中去。

对于 kubernetes_sd_configs 下面可用的元信息标签如下:

  • __meta_kubernetes_node_name:节点对象的名称
  • _meta_kubernetes_node_label:节点对象中的每个标签
  • _meta_kubernetes_node_annotation:来自节点对象的每个注释
  • _meta_kubernetes_node_address:每个节点地址类型的第一个地址(如果存在)

关于 kubernets_sd_configs 更多信息可以查看官方文档:kubernetes_sd_config

kubelet 监控

kubelet 也自带了一些监控指标数据,就上面提到的 10250 端口,所以这里也把 kubelet 的监控任务也一并配置上:

代码语言:javascript复制
- job_name: 'kubelet'
  kubernetes_sd_configs:
  - role: node
  scheme: https
  tls_config:
    insecure_skip_verify: true
    ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt
  bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token
  relabel_configs:
  - action: labelmap
    regex: __meta_kubernetes_node_label_(. )

这里需要特别注意的是这里必须使用 https 协议访问,这样就必然需要提供证书,这里是通过配置 insecure_skip_verify: true 来跳过了证书校验,但是除此之外,要访问集群的资源,还必须要有对应的权限才可以,也就是对应的 ServiceAccount 棒的 权限允许才可以,这里部署的 prometheus 关联的 ServiceAccount 对象前面已经提到过了,这里只需要将 Pod 中自动注入的 /var/run/secrets/kubernetes.io/serviceaccount/ca.crt/var/run/secrets/kubernetes.io/serviceaccount/token 文件配置上,就可以获取到对应的权限了。

现在再去更新下配置文件,执行 reload 操作,让配置生效,然后访问 Prometheus 的 Dashboard 查看 Targets 路径:

现在可以看到上面添加的 kubernetes-kubeletkubernetes-nodes 这两个 job 任务都已经配置成功了,而且二者的 Labels 标签都和集群的 node 节点标签保持一致了。

现在就可以切换到 Graph 路径下面查看采集的一些指标数据了,比如查询 node_load1 指标:

可以看到将几个节点对应的 node_load1 指标数据都查询出来了,同样的,还可以使用 PromQL 语句来进行更复杂的一些聚合查询操作,还可以根据的 Labels 标签对指标数据进行聚合,比如这里只查询 node1 节点的数据,可以使用表达式 node_load1{instance="k8s-master1"} 来进行查询:

容器监控

说到容器监控自然会想到 cAdvisor,前面也说过 cAdvisor 已经内置在了 kubelet 组件之中,所以不需要单独去安装,cAdvisor 的数据路径为 /api/v1/nodes/<node>/proxy/metrics,但是不推荐使用这种方式,因为这种方式是通过 APIServer 去代理访问的,对于大规模的集群比如会对 APIServer 造成很大的压力,所以可以直接通过访问 kubelet 的 /metrics/cadvisor 这个路径来获取 cAdvisor 的数据, 同样这里使用 node 的服务发现模式,因为每一个节点下面都有 kubelet,自然都有 cAdvisor 采集到的数据指标,配置如下:

代码语言:javascript复制
- job_name: 'kubernetes-cadvisor'
  kubernetes_sd_configs:
    - role: node
  scheme: https
  metrics_path: /metrics/cadvisor
  tls_config:
    insecure_skip_verify: true
    ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt
  bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token
  relabel_configs:
    - action: labelmap
      regex: __meta_kubernetes_node_label_(. )
      replacement: $1
    # 下面的方式不推荐使用
    #- source_labels: [__meta_kubernetes_node_name]
    #  regex: (. )
    #  replacement: /metrics/cadvisor # <nodeip>/metrics -> <nodeip>/metrics/cadvisor
    #  target_label: __metrics_path__

上面的配置和之前配置 node-exporter 的时候几乎是一样的,区别是这里使用了 https 的协议,另外需要注意的是配置了 ca.cart 和 token 这两个文件,这两个文件是 Pod 启动后自动注入进来的,然后加上 __metrics_path__ 的访问路径 /metrics/cadvisor,现在同样更新下配置,然后查看 Targets 路径:

可以切换到 Graph 路径下面查询容器相关数据,比如这里来查询集群中所有 Pod 的 CPU 使用情况,kubelet 中的 cAdvisor 采集的指标和含义,可以查看 Monitoring cAdvisor with Prometheus 说明,其中有一项:

代码语言:javascript复制
container_cpu_usage_seconds_total   Counter     Cumulative cpu time consumed    seconds

container_cpu_usage_seconds_total 是容器累计使用的 CPU 时间,用它除以 CPU 的总时间,就可以得到容器的 CPU 使用率了:

首先计算容器的 CPU 占用时间,由于节点上的 CPU 有多个,所以需要将容器在每个 CPU 上占用的时间累加起来,Pod 在 1m 内累积使用的 CPU 时间为:(根据 pod 和 namespace 进行分组查询)

代码语言:javascript复制
sum(rate(container_cpu_usage_seconds_total{image!="",pod!=""}[1m])) by (namespace, pod)

然后计算 CPU 的总时间,这里的 CPU 数量是容器分配到的 CPU 数量,container_spec_cpu_quota 是容器的 CPU 配额,它的值是容器指定的 CPU 个数 * 100000,所以 Pod 在 1s 内 CPU 的总时间为:Pod 的 CPU 核数 * 1s:

代码语言:javascript复制
sum(container_spec_cpu_quota{image!="", pod!=""}) by(namespace, pod) / 100000

CPU 配额

由于 container_spec_cpu_quota 是容器的 CPU 配额,所以只有配置了 resource-limit CPU 的 Pod 才可以获得该指标数据。

将上面这两个语句的结果相除,就得到了容器的 CPU 使用率:

代码语言:javascript复制
(sum(rate(container_cpu_usage_seconds_total{image!="",pod!=""}[1m])) by (namespace, pod))
/
(sum(container_spec_cpu_quota{image!="", pod!=""}) by(namespace, pod) / 100000) * 100

在 promethues 里面执行上面的 promQL 语句可以得到下面的结果:

Pod 内存使用率的计算就简单多了,直接用内存实际使用量除以内存限制使用量即可:

代码语言:javascript复制
sum(container_memory_rss{image!=""}) by(namespace, pod) / sum(container_spec_memory_limit_bytes{image!=""}) by(namespace, pod) * 100 !=  inf

在 promethues 里面执行上面的 promQL 语句可以得到下面的结果:

监控 Pod

为解决服务发现的问题,prometheus 为提供了一个额外的抓取配置来解决这个问题,可以通过添加额外的配置来进行服务发现进行自动监控。可以在 kubernetes 当中去自动发现并监控具有 prometheus.io/scrape=true 这个 annotations 的 Service是专门发现普通类型的 Endpoint,其实就是 Service 关联的 Pod 列表。 其中通过 kubernetes_sd_configs 支持监控其各种资源。kubernetes SD 配置允许从 kubernetes REST API 接受搜集指标,且总是和集群保持同步状态,任何一种 role 类型都能够配置来发现想要的对象。

规则配置使用 yaml 格式,下面是文件中一级配置项。自动发现 k8s Metrics 接口是通过 scrape_configs 来实现的:

代码语言:javascript复制
- job_name: 'kubernetes-pods'
  kubernetes_sd_configs:
  # 角色为 endpoints
    - role: endpoints
  relabel_configs:
  # 重新打标仅抓取到的具有 "prometheus.io/scrape: true" 的annotation的端点,意思是说如果某个service具有prometheus.io/scrape = true annotation声明则抓取
  # annotation本身也是键值结构,所以这里的源标签设置为键,而regex设置值,当值匹配到regex设定的内容时则执行keep动作也就是保留,其余则丢弃.
  # node-exporter这个POD的service里面就有一个叫做prometheus.io/scrape = true的annotations所以就找到了node-exporter这个POD
    - source_labels: [__meta_kubernetes_service_annotation_prometheus_io_scrape]
    # 动作 删除 regex 与串联不匹配的目标 source_labels
      action: keep
    # 通过正式表达式匹配 true
      regex: true
    - source_labels: [__meta_kubernetes_service_annotation_prometheus_io_scheme]
    # 匹配源标签__meta_kubernetes_service_annotation_prometheus_io_scheme也就是prometheus.io/scheme annotation
    # 如果源标签的值匹配到regex则把值替换为__scheme__对应的值
      action: replace
      target_label: __scheme__       # 重新设置scheme
      regex: (https?)
    - source_labels: [__meta_kubernetes_service_annotation_prometheus_io_path]
      # 匹配来自 pod annotationname prometheus.io/path 字段
      # 获取POD的 annotation 中定义的"prometheus.io/path: XXX"定义的值,这个值就是你的程序暴露符合prometheus规范的metrics的地址
      # 如果你的metrics的地址不是 /metrics 的话,通过这个标签说,那么这里就会把这个值赋值给 __metrics_path__这个变量,因为prometheus
   # 是通过这个变量获取路径然后进行拼接出来一个完整的URL,并通过这个URL来获取metrics值的,因为prometheus默认使用的就是 http(s)://X.X.X.X/metrics
   # 这样一个路径来获取的
      action: replace
      target_label: __metrics_path__
      regex: (. )
    - source_labels:          # 匹配出 Pod ip地址和 Port
        [__address__, __meta_kubernetes_service_annotation_prometheus_io_port]
      action: replace
      target_label: __address__
      regex: ([^:] )(?::d )?;(d ) # RE2 正则规则, 是一次多多次,?是0次或1次,其中?:表示非匹配组(意思就是不获取匹配结果)
      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]
    # service 对象的名称
      action: replace
      target_label: kubernetes_name
    - source_labels: [__meta_kubernetes_pod_name]
    # pod对象的名称
      action: replace
      target_label: kubernetes_pod_name

要想自动发现集群中的 Endpoint,就需要在 Service 的 annotation 区域添加 prometheus.io/scrape=true 的声明,现在先将上面的配置更新,在部署prometheus时,已经将这些声明都加到Service中了,查看下效果:

代码语言:javascript复制
metadata:
  annotations:                            # 通过endpoints 自动发现时使用
    prometheus.io/port: "9090"            # 监听端口
    prometheus.io/scrape: "true"          # 是否开启监控
    prometheus.io/path: "/metrics"        # 监控路径

kube-state-metrics

上面配置了自动发现 Endpoints 的监控,但是这些监控数据都是应用内部的监控,需要应用本身提供一个 /metrics 接口,或者对应的 exporter 来暴露对应的指标数据,但是在 Kubernetes 集群上 Pod、DaemonSet、Deployment、Job、CronJob 等各种资源对象的状态也需要监控,这也反映了使用这些资源部署的应用的状态。比如:

  • 我调度了多少个副本?现在可用的有几个?
  • 多少个 Pod 是 running/stopped/terminated 状态?
  • Pod 重启了多少次?
  • 我有多少 job 在运行中等等

通过查看前面从集群中拉取的指标(这些指标主要来自 apiserver 和 kubelet 中集成的 cAdvisor),并没有具体的各种资源对象的状态指标。对于 Prometheus 来说,当然是需要引入新的 exporter 来暴露这些指标,Kubernetes 提供了一个kube-state-metrics 就是需要的。

与 metric-server 的对比

  • metric-server 是从 APIServer 中获取 cpu、内存使用率这种监控指标,并把他们发送给存储后端,如 influxdb 或云厂商,当前的核心作用是为 HPA 等组件提供决策指标支持。
  • kube-state-metrics 关注于获取 Kubernetes 各种资源的最新状态,如 deployment 或者 daemonset,metric-server 仅仅是获取、格式化现有数据,写入特定的存储,实质上是一个监控系统。而 kube-state-metrics 是获取集群最新的指标。
  • 像 Prometheus 这种监控系统,并不会去用 metric-server 中的数据,他都是自己做指标收集、集成的,但 Prometheus 可以监控 metric-server 本身组件的监控状态并适时报警,这里的监控就可以通过 kube-state-metrics 来实现,如 metric-server pod 的运行状态。

创建资源配置清单

kube-state-metrics 已经给出了在 Kubernetes 部署的 manifest 定义文件,直接将代码 Clone 到集群中(能用 kubectl 工具操作就行),不过需要注意兼容的版本:

RBACDeployment

代码语言:javascript复制
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  labels:
    app.kubernetes.io/component: exporter
    app.kubernetes.io/name: kube-state-metrics
    app.kubernetes.io/version: 2.10.0
  name: kube-state-metrics
rules:
- apiGroups:
  - ""
  resources:
  - configmaps
  - secrets
  - nodes
  - pods
  - services
  - serviceaccounts
  - resourcequotas
  - replicationcontrollers
  - limitranges
  - persistentvolumeclaims
  - persistentvolumes
  - namespaces
  - endpoints
  verbs:
  - list
  - watch
- apiGroups:
  - apps
  resources:
  - statefulsets
  - daemonsets
  - deployments
  - replicasets
  verbs:
  - list
  - watch
- apiGroups:
  - batch
  resources:
  - cronjobs
  - jobs
  verbs:
  - list
  - watch
- apiGroups:
  - autoscaling
  resources:
  - horizontalpodautoscalers
  verbs:
  - list
  - watch
- apiGroups:
  - authentication.k8s.io
  resources:
  - tokenreviews
  verbs:
  - create
- apiGroups:
  - authorization.k8s.io
  resources:
  - subjectaccessreviews
  verbs:
  - create
- apiGroups:
  - policy
  resources:
  - poddisruptionbudgets
  verbs:
  - list
  - watch
- apiGroups:
  - certificates.k8s.io
  resources:
  - certificatesigningrequests
  verbs:
  - list
  - watch
- apiGroups:
  - discovery.k8s.io
  resources:
  - endpointslices
  verbs:
  - list
  - watch
- apiGroups:
  - storage.k8s.io
  resources:
  - storageclasses
  - volumeattachments
  verbs:
  - list
  - watch
- apiGroups:
  - admissionregistration.k8s.io
  resources:
  - mutatingwebhookconfigurations
  - validatingwebhookconfigurations
  verbs:
  - list
  - watch
- apiGroups:
  - networking.k8s.io
  resources:
  - networkpolicies
  - ingressclasses
  - ingresses
  verbs:
  - list
  - watch
- apiGroups:
  - coordination.k8s.io
  resources:
  - leases
  verbs:
  - list
  - watch
- apiGroups:
  - rbac.authorization.k8s.io
  resources:
  - clusterrolebindings
  - clusterroles
  - rolebindings
  - roles
  verbs:
  - list
  - watch
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  labels:
    app.kubernetes.io/component: exporter
    app.kubernetes.io/name: kube-state-metrics
    app.kubernetes.io/version: 2.10.0
  name: kube-state-metrics
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: kube-state-metrics
subjects:
- kind: ServiceAccount
  name: kube-state-metrics
  namespace: kube-system
---
apiVersion: v1
automountServiceAccountToken: false
kind: ServiceAccount
metadata:
  labels:
    app.kubernetes.io/component: exporter
    app.kubernetes.io/name: kube-state-metrics
    app.kubernetes.io/version: 2.10.0
  name: kube-state-metrics
  namespace: kube-system
代码语言:javascript复制
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app.kubernetes.io/component: exporter
    app.kubernetes.io/name: kube-state-metrics
    app.kubernetes.io/version: 2.10.0
  name: kube-state-metrics
  namespace: kube-system
spec:
  replicas: 1
  selector:
    matchLabels:
      app.kubernetes.io/name: kube-state-metrics
  template:
    metadata:
      annotations:
        prometheus.io/path: "/metrics"
        prometheus.io/scheme: "kube-state-metrics"
        prometheus.io/port: "8080"  # 8081是kube-state-metrics应用本身指标的端口
      labels:
        app.kubernetes.io/component: exporter
        app.kubernetes.io/name: kube-state-metrics
        app.kubernetes.io/version: 2.10.0
    spec:
      automountServiceAccountToken: true
      containers:
      - image: wangxiansen/kube-state-metrics:v2.10.0
        livenessProbe:
          httpGet:
            path: /healthz
            port: 8080
          initialDelaySeconds: 5
          timeoutSeconds: 5
        name: kube-state-metrics
        ports:
        - containerPort: 8080
          name: http-metrics
        - containerPort: 8081
          name: telemetry
        readinessProbe:
          httpGet:
            path: /
            port: 8081
          initialDelaySeconds: 5
          timeoutSeconds: 5
        securityContext:
          allowPrivilegeEscalation: false
          capabilities:
            drop:
            - ALL
          readOnlyRootFilesystem: true
          runAsNonRoot: true
          runAsUser: 65534
          seccompProfile:
            type: RuntimeDefault
      nodeSelector:
        kubernetes.io/os: linux
      serviceAccountName: kube-state-metrics

默认的镜像为 gcr 的,这里可以将 deployment.yaml 下面的镜像替换成 wangxiansen/kube-state-metrics:v2.10.0,此外上面为 Prometheus 配置了 Pod的自动发现,所以可以给 kube-state-metrics 的 Pod 配置上对应的 annotations 来自动被发现,然后直接创建即可:

代码语言:javascript复制
- job_name: 'kube-state-metrics'
  kubernetes_sd_configs:
    - role: pod                # 针对单独Pod做自动发现
  relabel_configs:
    - source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_scheme]
      action: keep
      regex: kube-state-metrics
    - 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
  metric_relabel_configs:
    - target_label: cluster
      replacement: k8s-version-1.23

部署完成后正常就可以被 Prometheus 采集到指标了:

水平缩放(分片)

kube-state-metrics 已经内置实现了一些自动分片功能,可以通过 --shard--total-shards 参数进行配置。现在还有一个实验性功能,如果将 kube-state-metrics 部署在 StatefulSet 中,它可以自动发现其命名位置,以便自动配置分片,这是一项实验性功能,可能以后会被移除。

要启用自动分片,必须运行一个 kube-state-metrics 的 StatefulSet,并且必须通过 --pod--pod-namespace 标志将 pod 名称和名称空间传递给 kube-state-metrics 进程。可以参考 /examples/autosharding 目录下面的示例清单文件进行说明。

使用

使用 kube-state-metrics 的一些典型场景:

  • 存在执行失败的 Job: kube_job_status_failed
  • 集群节点状态错误: kube_node_status_condition{condition="Ready", status!="true"}==1
  • 集群中存在启动失败的 Pod:kube_pod_status_phase{phase=~"Failed|Unknown"}==1
  • 最近 30 分钟内有 Pod 容器重启: changes(kube_pod_container_status_restarts_total[30m])>0

关于 kube-state-metrics 的更多用法可以查看官方 GitHub 仓库:https://github.com/kubernetes/kube-state-metrics

最终Prometheus配置文件

Prometheus配置文件

代码语言:javascript复制
apiVersion: v1
kind: ConfigMap
metadata:
  name: prometheus-config
  namespace: infra
data:
  prometheus.yml: |
    global:
      scrape_interval: 15s
      scrape_timeout: 15s
    scrape_configs:
    - job_name: 'etcd'
      tls_config:
        ca_file: /data/ssl/ca.pem
        cert_file: /data/ssl/server.pem
        key_file: /data/ssl/server-key.pem
      scheme: https
      static_configs:
      - targets:
        - '10.1.1.100:2379'
        labels:
          instance: etcd-server-1
      - targets:
        - '10.1.1.120:2379'
        labels:
          instance: etcd-server-2
      - targets:
        - '10.1.1.130:2379'
        labels:
          instance: etcd-server-3
    - 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
    - job_name: 'k8s-nodes'
      kubernetes_sd_configs:
        - role: node
      relabel_configs:
        - source_labels: [__address__]
          regex: '(.*):10250'
          replacement: '${1}:9100'
          target_label: __address__
          action: replace
        - action: labelmap
          regex: __meta_kubernetes_node_label_(. )
    - job_name: 'kubelet'
      kubernetes_sd_configs:
      - role: node
      scheme: https
      tls_config:
        insecure_skip_verify: true
        ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt
      bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token
      relabel_configs:
      - action: labelmap
        regex: __meta_kubernetes_node_label_(. )
    - job_name: 'kubernetes-cadvisor'
      kubernetes_sd_configs:
        - role: node
      scheme: https
      metrics_path: /metrics/cadvisor
      tls_config:
        insecure_skip_verify: true
        ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt
      bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token
      relabel_configs:
        - action: labelmap
          regex: __meta_kubernetes_node_label_(. )
          replacement: $1
    - job_name: 'kubernetes-pods'
      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 ) # RE2 正则规则, 是一次多多次,?是0次或1次,其中?:表示非匹配组(意思就是不获取匹配结果)
          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
        - source_labels: [__meta_kubernetes_pod_name]
          action: replace
          target_label: kubernetes_pod_name
    - job_name: 'traefik'
      kubernetes_sd_configs:
        - role: pod
      relabel_configs:
        - source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_scheme]
          action: keep
          regex: traefik
        - 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: 'kube-state-metrics'
      kubernetes_sd_configs:
        - role: pod
      relabel_configs:
        - source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_scheme]
          action: keep
          regex: kube-state-metrics
        - 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
      metric_relabel_configs:
        - target_label: cluster
          replacement: k8s-version-1.23

0 人点赞