惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

C
Check Point Blog
GbyAI
GbyAI
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
U
Unit 42
美团技术团队
NISL@THU
NISL@THU
C
Cisco Blogs
SecWiki News
SecWiki News
N
Netflix TechBlog - Medium
Forbes - Security
Forbes - Security
Cloudbric
Cloudbric
雷峰网
雷峰网
T
Tailwind CSS Blog
博客园 - 司徒正美
The Register - Security
The Register - Security
L
LangChain Blog
S
Security Affairs
Hacker News - Newest:
Hacker News - Newest: "LLM"
B
Blog
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
T
Threat Research - Cisco Blogs
I
InfoQ
S
Schneier on Security
L
Lohrmann on Cybersecurity
量子位
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
Martin Fowler
Martin Fowler
Schneier on Security
Schneier on Security
F
Fortinet All Blogs
TaoSecurity Blog
TaoSecurity Blog
K
Kaspersky official blog
Google DeepMind News
Google DeepMind News
Cisco Talos Blog
Cisco Talos Blog
PCI Perspectives
PCI Perspectives
Attack and Defense Labs
Attack and Defense Labs
WordPress大学
WordPress大学
Microsoft Azure Blog
Microsoft Azure Blog
H
Help Net Security
Project Zero
Project Zero
The GitHub Blog
The GitHub Blog
D
Docker
N
News | PayPal Newsroom
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
H
Hacker News: Front Page
云风的 BLOG
云风的 BLOG
Microsoft Security Blog
Microsoft Security Blog
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
博客园 - 聂微东
Webroot Blog
Webroot Blog
MongoDB | Blog
MongoDB | Blog

博客园 - py哥

rabbitmq集群docker部署 MongoDB副本集docker部署 MySQL8.0单实例部署 prometheus 监控 eureka 里面的服务状态 Redis管理平台 k8s网络与本地开发环境网络互通方案 CentOS7 FTP结合ssl/tls实现加密通信安装与配置 数据库运维平台 基于Docker构建Jenkins CI平台 KeepLived + nginx 高可用 k8s-1.16 二进制安装 Ansible自动化部署K8S集群 Kubernetes1.16下部署Prometheus+node-exporter+Grafana+AlertManager 监控系统 docker部署coredns kubeadm部署多master节点高可用k8s1.16.2 二进制搭建一个完整的K8S集群部署文档 kubeadm部署k8s集群 Keepalived+LVS+nginx搭建nginx高可用集群 centos7 dns(bind)安装配置
在Kubernetes下部署Prometheus
py哥 · 2019-12-03 · via 博客园 - py哥

使用ConfigMaps管理应用配置

当使用Deployment管理和部署应用程序时,用户可以方便了对应用进行扩容或者缩容,从而产生多个Pod实例。为了 能够统一管理这些Pod的配置信息,在Kubernetes中可以使用ConfigMaps资源定义和管理这些配置,并且通过环境 变量或者文件系统挂载的方式让容器使用这些配置。 这里将使用ConfigMaps管理Prometheus的配置文件,创建prometheus-config.yml文件,并写入以下内容:

apiVersion: v1
data:
  prometheus.yml: |-
    global:
      scrape_interval: 15s
      evaluation_interval: 15s
    scrape_configs:
    - job_name: ''prometheus''
      static_configs:
      - targets: ['localhost:9090']




kind: ConfigMap
metadata:
  name: prometheus-config

使用kubectl命令行工具,在命名空间default创建ConfigMap资源:

 kubectl create -f prometheus-config.yml
 configmap "prometheus-config" created

使用Deployment部署Prometheus

当ConfigMap资源创建成功后,我们就可以通过Volume挂载的方式,将Prometheus的配置文件挂载到容器中。 这 里我们通过Deployment部署Prometheus Server实例,创建prometheus-deployment.yml文件,并写入以下 内容:

apiVersion: v1
kind: "Service"
metadata:
  name: prometheus
  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
spec:
  replicas: 1
  selector:
    matchLabels:
      app: prometheus
  template:
    metadata:
      labels:
        app: prometheus
    spec:
      serviceAccountName: prometheus
      serviceAccount: prometheus
      containers:
      - name: prometheus
        image: prom/prometheus:v2.2.1
        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

该文件中分别定义了Service和Deployment,Service类型为NodePort,这样我们可以通过虚拟机IP和端口访问 到Prometheus实例。为了能够让Prometheus实例使用ConfigMap中管理的配置文件,这里通过volumes声明了一 个磁盘卷。并且通过volumeMounts将该磁盘卷挂载到了Prometheus实例的/etc/prometheus目录下。

使用以下命令创建资源,并查看资源的创建情况:

 $ kubectl create -f prometheus-deployment.yml
 service "prometheus" created
 deployment "prometheus" created
$ kubectl get pods

NAME                               READY   STATUS    RESTARTS   AGE
prometheus-7f57d48b8d-fxm9j        1/1     Running   0          8m31s
$ kubectl get svc
[root@k8s-01 ~]#  kubectl get svc
NAME                TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)          AGE
kubernetes          ClusterIP   10.1.0.1     <none>        443/TCP          29d
prometheus          NodePort    10.1.67.80   <none>        9090:30880/TCP   5h1m

至此,我们可以通过虚拟机的IP地址和端口3xxxx访问到Prometheus的服务。

Kubernetes下的服务发现

目前为止,我们已经能够在Kubernetes下部署一个简单的Prometheus实例,不过当前来说它并不能发挥其监控系 统的作用,除了Prometheus,暂时没有任何的监控采集目标。在第7章中,我们介绍了Prometheus的服务发现能 力,它能够与通过与“中间代理人“的交互,从而动态的获取需要监控的目标实例。而在Kubernetes下Prometheus 就是需要与Kubernetes的API进行交互,从而能够动态的发现Kubernetes中部署的所有可监控的目标资源。

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
  - nodes/proxy
  - services
  - endpoints
  - pods
  verbs: ["get", "list", "watch"]
- apiGroups:
  - extensions
  resources:
  - ingresses
  verbs: ["get", "list", "watch"]
- nonResourceURLs: ["/metrics"]
  verbs: ["get"]
---
apiVersion: v1
kind: ServiceAccount
metadata:
  name: prometheus
  namespace: default
---
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: default

其中需要注意的是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
  selector:
    matchLabels:
      app: prometheus
  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-7f57d48b8d-n4sns        1/1     Running   0          4m19s

指定ServiceAccount创建的Pod实例中,会自动将用于访问Kubernetes API的CA证书以及当前账户对应的访问令 牌文件挂载到Pod实例的/var/run/secrets/kubernetes.io/serviceaccount/目录下,可以通过以下命令进 行查看:

[root@k8s-01 ~]# kubectl exec -it prometheus-7f57d48b8d-n4sns ls /var/run/secrets/kubernetes.io/serviceaccount/
ca.crt     namespace  token

服务发现

在Kubernetes下,Promethues通过与Kubernetes API集成目前主要支持5种服务发现模式,分别是:Node、 Service、Pod、Endpoints、Ingress。

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

    - 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

    - job_name: 'prometheus'
      static_configs:
      - targets: ['localhost:9090'] 

kind: ConfigMap
metadata:
  name: prometheus-config

更新Prometheus配置文件,并重建Prometheus实例:

1. $ kubectl apply -f prometheus-config.yml
2. configmap "prometheus-config" configured
3.
4. $ kubectl get pods
5. prometheus-69f9ddb588-rbrs2 1/1 Running 0 4m
6.
7. $ kubectl delete pods prometheus-69f9ddb588-rbrs2
8. pod "prometheus-69f9ddb588-rbrs2" deleted
9.
10. $ kubectl get pods
11. prometheus-69f9ddb588-rbrs2 0/1 Terminating 0 4m
12. prometheus-69f9ddb588-wtlsn 1/1 Running 0 14s

Prometheus使用新的配置文件重建之后,打开Prometheus UI,通过Service Discovery页面可以查看到当前 Prometheus通过Kubernetes发现的所有资源对象了:

 同时Prometheus会自动将该资源的所有信息,并通过标签的形式体现在Target对象上。如下所示,是Promthues 获取到的Node节点的标签信息:

目前为止,我们已经能够通过Prometheus自动发现Kubernetes集群中的各类资源以及其基本信息。不过,如果现 在查看Promtheus的Target状态页面,结果可能会让人不太满意:

虽然Prometheus能够自动发现所有的资源对象,并且将其作为Target对象进行数据采集。 但并不是所有的资源对 象都是支持Promethues的,并且不同类型资源对象的采集方式可能是不同的。因此,在实际的操作中,我们需要有 明确的监控目标,并且针对不同类型的监控目标设置不同的数据采集方式。

接下来,我们将利用Promtheus的服务发现能力,实现对Kubernetes集群的全面监控。

使用Prometheus监控Kubernetes集群

下表中,梳理了监控Kubernetes集群监控的各个维度以及策略:

从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_(.+)
      - 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

通过获取各个节点中kubelet的监控指标,用户可以评估集群中各节点的性能表现。例如,通过指标 kubelet_pod_start_latency_microseconds可以获得当前节点中Pod启动时间相关的统计数据。

 kubelet_pod_start_latency_microseconds{quantile="0.99"}

 Pod平均启动时间大致为42s左右(包含镜像下载时间):

kubelet_pod_start_latency_microseconds_sum / kubelet_pod_start_latency_microseconds_count

除此以外,监控指标kubeletdocker*还可以体现出kubelet与当前节点的docker服务的调用情况,从而可以反映 出docker本身是否会影响kubelet的性能表现等问题。

从Kubelet获取节点容器资源使用情况

各节点的kubelet组件中除了包含自身的监控指标信息以外,kubelet组件还内置了对cAdvisor的支持。 cAdvisor能够获取当前节点上运行的所有容器的资源使用情况,通过访问kubelet的/metrics/cadvisor地址可 以获取到cadvisor的监控指标,因此和获取kubelet监控指标类似,这里同样通过node模式自动发现所有的 kubelet信息,并通过适当的relabel过程,修改监控采集任务的配置。 与采集kubelet自身监控指标相似:

    - 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_(.+)

使用NodeExporter监控集群资源使用情况

为了能够采集集群中各个节点的资源使用情况,我们需要在各节点中部署一个Node Exporter实例。在本章的“部署 Prometheus”小节,我们使用了Kubernetes内置的控制器之一Deployment。Deployment能够确保Prometheus 的Pod能够按照预期的状态在集群中运行,而Pod实例可能随机运行在任意节点上。而与Prometheus的部署不同的 是,对于Node Exporter而言每个节点只需要运行一个唯一的实例,此时,就需要使用Kubernetes的另外一种控制 器Daemonset。顾名思义,Daemonset的管理方式类似于操作系统中的守护进程。Daemonset会确保在集群中所有 (也可以指定)节点上运行一个唯一的Pod实例。

创建node-exporter-daemonset.yml文件,并写入以下内容:

apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: node-exporter
spec:
  selector:
    matchLabels:
      app: node-exporter
  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是以主机网络的形式运行,因此直接访问虚拟机IP加上Pod的端口即可访问当前节 点上运行的Node Exporter实例:

[root@k8s-01 ~]# curl http://k8s-02:9100/metrics  |head
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
  0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0# HELP go_gc_duration_seconds A summary of the GC invocation durations.
# TYPE go_gc_duration_seconds summary
go_gc_duration_seconds{quantile="0"} 1.7503e-05
go_gc_duration_seconds{quantile="0.25"} 2.9973e-05
go_gc_duration_seconds{quantile="0.5"} 5.2475e-05
go_gc_duration_seconds{quantile="0.75"} 8.2703e-05
go_gc_duration_seconds{quantile="1"} 0.001951054
go_gc_duration_seconds_sum 0.067789147
go_gc_duration_seconds_count 834
# HELP go_goroutines Number of goroutines that currently exist.
100 44764    0 44764    0     0  1207k      0 --:--:-- --:--:-- --:--:-- 1248k

目前为止,通过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

通过以上relabel过程实现对Pod实例的过滤,以及采集任务地址替换,从而实现对特定Pod实例监控指标的采集。需 要说明的是kubernetes-pods并不是只针对Node Exporter而言,对于用户任意部署的Pod实例,只要其提供了对 Prometheus的支持,用户都可以通过为Pod添加注解的形式为其添加监控指标采集的支持。

从kube-apiserver获取集群运行监控指标

在开始正式内容之前,我们需要先了解一下Kubernetes中Service是如何实现负载均衡的,如下图所示,一般来说 Service有两个主要的使用场景:

代理对集群内部应用Pod实例的请求:当创建Service时如果指定了标签选择器,Kubernetes会监听集群中所 有的Pod变化情况,通过Endpoints自动维护满足标签选择器的Pod实例的访问信息;

代理对集群外部服务的请求:当创建Service时如果不指定任何的标签选择器,此时需要用户手动创建 Service对应的Endpoint资源。例如,一般来说,为了确保数据的安全,我们通常讲数据库服务部署到集群 外。 这是为了避免集群内的应用硬编码数据库的访问信息,这是就可以通过在集群内创建Service,并指向外 部的数据库服务实例。

kube-apiserver扮演了整个Kubernetes集群管理的入口的角色,负责对外暴露Kubernetes API。kubeapiserver组件一般是独立部署在集群外的,为了能够让部署在集群内的应用(kubernetes插件或者用户应用)能 够与kube-apiserver交互,Kubernetes会默认在命名空间下创建一个名为kubernetes的服务,如下所示:

[root@k8s-01 ~]# kubectl get svc kubernetes -o wide
NAME         TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE   SELECTOR
kubernetes   ClusterIP   10.1.0.1     <none>        443/TCP   29d   <none>

而该kubernetes服务代理的后端实际地址通过endpoints进行维护,如下所示:

[root@k8s-01 ~]#  kubectl get endpoints kubernetes
NAME         ENDPOINTS            AGE
kubernetes   192.168.122.2:6443   29d

通过这种方式集群内的应用或者系统主机就可以通过集群内部的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实例,得到以下结果。

对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: apps/v1
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实例:

[root@k8s-01 ~]#  kubectl get pods
NAME                               READY   STATUS    RESTARTS   AGE
blackbox-exporter-5574646b-4wjg5   1/1     Running   0          46m
prometheus-7f57d48b8d-n4sns        1/1     Running   0          26m
[root@k8s-01 ~]# kubectl get svc
NAME                TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)          AGE
blackbox-exporter   ClusterIP   10.1.70.11   <none>        9115/TCP         46m
kubernetes          ClusterIP   10.1.0.1     <none>        443/TCP          29d
prometheus          NodePort    10.1.67.80   <none>        9090:30880/TCP   5h30m

为了能够让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