监控kubernetes集群的方式
导航:这里主要是列出一个prometheus一些系统的学习过程,最后按照章节顺序查看,由于写作该文档经历了不同时期,所以在文中有时出现 的云环境不统一,但是学习具体使用方法即可,在最后的篇章,有一个完整的腾讯云的实战案例。 8.kube-state-metrics 和 metrics-server 13.Grafana简单用法 参考: https://prometheus.io/docs/prometheus/latest/configuration/configuration/#kubernetes_sd_config https://www.bookstack.cn/read/prometheus_practice/introduction-README.md |
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
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
安装完成后使用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
其中需要注意的是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配置文件,并重建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的结果
获取的是私网地址,如果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