云原生和非云原生监控案例 十八岁 2026-08-13 2026-08-13
云原生和非云原生应用监控 1.云原生应用监控-Etcd 1.1测试是否能获取到监控数据 Etcd属于云原生应用,是k8s核心组件之一,它自带了/metrics接口:
1 2 3 4 5 6 7 # 在安装了etcd组件的服务器上 查看etcd服务的端口,以k8s-master01为例: [root@k8s-master01 manifests]# netstat -lntup|grep etcd tcp 0 0 127.0.0.1:2379 0.0.0.0:* LISTEN 909/etcd tcp 0 0 192.168.0.81:2379 0.0.0.0:* LISTEN 909/etcd tcp 0 0 192.168.0.81:2380 0.0.0.0:* LISTEN 909/etcd # etcd 目前默认使用2379端口提供HTTP API服务,2380端口和peer通信(这两个端口已经被IANA(互联网数字分配机构)官方预留给etcd)。 即etcd默认使用2379端口对外为客户端提供通讯,使用端口2380来进行服务器间内部通讯。 # 如果是监控etcd指标,则需要跟2379端口通信
访问etcd的metrics接口:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 # 本地访问可以使用http,但是Prometheus不能用127.0.0.1,只能通过192.168.0.81:2379访问,所以需要带着etcd的证书访问才会有数据返回 # 本地访问 [root@k8s-master01 manifests]# curl 127.0.0.1:2379/metrics .... # HELP etcd_debugging_disk_backend_commit_write_duration_seconds The latency distributions of commit.write called by bboltdb backend. # TYPE etcd_debugging_disk_backend_commit_write_duration_seconds histogram etcd_debugging_disk_backend_commit_write_duration_seconds_bucket{le="0.001"} 91885 etcd_debugging_disk_backend_commit_write_duration_seconds_bucket{le="0.002"} 155332 etcd_debugging_disk_backend_commit_write_duration_seconds_bucket{le="0.004"} 215254 # 证书访问 [root@k8s-master01 etcd-service-monitor]# curl -s --cacert /etc/kubernetes/pki/etcd/etcd-ca.pem --cert /etc/kubernetes/pki/etcd/etcd.pem --key /etc/kubernetes/pki/etcd/etcd-key.pem https://192.168.0.200:2379/metrics # 如何查找自己etcd的证书? # 证书的位置可以在 Etcd 配置文件中获得(注意配置文件的位置,不同的集群位置可能不同, # Kubeadm 安装方式可能会在/etc/kubernetes/manifests/etcd.yml 中): # 二进制安装方式,执行systemctl status etcd命令,找到配置文件--config-file=/etc/etcd/etcd.config.yml # 在/etc/etcd/etcd.config.yml文件中查看证书的路径 # 可以使用命令过滤出来: [root@k8s-master01 etcd-service-monitor]# grep -E "key-file|cert-file|trusted-ca-file" /etc/etcd/etcd.config.yml cert-file: '/etc/kubernetes/pki/etcd/etcd.pem' key-file: '/etc/kubernetes/pki/etcd/etcd-key.pem' trusted-ca-file: '/etc/kubernetes/pki/etcd/etcd-ca.pem' cert-file: '/etc/kubernetes/pki/etcd/etcd.pem' key-file: '/etc/kubernetes/pki/etcd/etcd-key.pem' trusted-ca-file: '/etc/kubernetes/pki/etcd/etcd-ca.pem' # 也可以cat 配置文件查看: [root@k8s-master01 manifests]# cat /etc/etcd/etcd.config.yml
使用带参数的指令获取etcd监控指标:
1 2 3 4 5 6 7 8 9 curl -s --cacert /etc/kubernetes/pki/etcd/etcd-ca.pem --cert /etc/kubernetes/pki/etcd/etcd.pem --key /etc/kubernetes/pki/etcd/etcd-key.pem https://192.168.0.81:2379/metrics # 结果如下: .... # TYPE process_open_fds gauge process_open_fds 335 # HELP process_resident_memory_bytes Resident memory size in bytes. # TYPE process_resident_memory_bytes gauge promhttp_metric_handler_requests_total{code="200"} 6 promhttp_metric_handler_requests_total{code="500"} 0
1.2为Etcd创建svc 因为我的 etcd 是二进制部署在 Node 上,不是 k8s Pod,所以需要手工创建一个 Service + Endpoints,把三个 etcd IP 暴露成一个 “虚拟” k8s 服务:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 # 为etcd创建 Service + Endpoints # 编写资源配置 [root@k8s-master01 etcd-service-monitor]# vim etcd-service.yaml # 假如下面配置内容 apiVersion: v1 # Service的API版本 kind: Service # 定义资源的类型,这里是Service metadata: # 定义资源的元数据 name: etcd-service # 定义Service的名字,如果需要手动配置endpoints,这个service名称必须与endpoints中定义的名字相同 namespace: kube-system # 定义资源所在的命名空间。 labels: # 定义这个Service资源的标签,建议和Endpoints 资源的标签保持一致 etcd: monitoring spec: # 定义资源的具体规格 type: ClusterIP # 集群内部访问的service类型 ports: # 定义Service的端口 - name: metrics # metrics端口名称,需要和后面的 ServiceMonitor 保持一致 port: 2379 # 定义Service暴露的端口 protocol: TCP # 使用TCP协议,默认值,不加该参数也可以 targetPort: 2379 # etcd服务的实际监听端口,和Endpoints.subsets.ports.port的端口保持一致 --- # 配套的Endpoints配置(如果etcd是静态部署的(比如直接部署在主机上),需要手动配置Endpoints) apiVersion: v1 # Endpoints的API版本 kind: Endpoints # Endpoints类型 ,创建的资源类型是Endpoints metadata: #定义资源的元数据 name: etcd-service # Endpoints的名称,必须与Service的名称相同 namespace: kube-system # Endpoints所在的命名空间 ,必须与Service在同一个命名空间。 labels: # Endpoints的标签,与Service的标签保持一致 etcd: monitoring subsets: # Endpoints的子集,定义了每个Endpoint的地址和端口,必须与Service的端口相同。 - addresses: # 定义Endpoint的地址,可以是Pod的IP地址,也可以是其他服务或节点的IP地址 - ip: "192.168.0.81" # 替换为实际的etcd节点IP,有几个节点就写几个IP - ip: "192.168.0.82" - ip: "192.168.0.83" ports: # 定义Endpoint的端口,必须与Service的端口相同。 - name: metrics # metrics端口名称,和service中.sepc.ports.name字段保持一致 port: 2379 # 以实际外部服务etcd监听端口为准 protocol: TCP # 使用TCP协议,默认值,不加该参数也可以 ------------------- 在手动创建Service和Endpoints时需要注意以下问题: Service.metadata.name 和 Endpoints.metadata.name 的值必须相同 Service.metadata.namespace 和 Endpoints.metadata.namespace 的值必须相同 Service.metadata.labels 和 Endpoints.metadata.labels 的值可以不相同,但是为了方便建议相同 Service.spec.ports.name 和 Endpoints.subsets.ports.name 的值必须保持一致 Service.spec.ports.targetPort 和 Endpoints.subsets.ports.port 的值必须保持一致 Service.spec.ports.protocol 和 Endpoints.subsets.ports.protocol 的值必须保持一致 Endpoints.subsets.ports.port的端口是由实际服务监听的端口号决定,例如MySQL实际监听3306端口,这个就应该配置3306 Service.spec.ports.targetPort的端口号由Endpoints.subsets.ports.port决定,所以两个保持一致 Service.spec.ports.port是自定义的service对外暴露的端口号,这个可以自己定义,也可以和targetPort保持一致 -------------------
创建该资源并查看 Service 的 ClusterIP:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 # 创建前先看下kube-system命名空间是没有相应的资源 [root@k8s-master01 etcd-service-monitor]# kubectl get service -n kube-system NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE kube-dns ClusterIP 10.96.0.10 <none> 53/UDP,53/TCP,9153/TCP 144d kubelet ClusterIP None <none> 10250/TCP,10255/TCP,4194/TCP 2d20h metrics-server ClusterIP 10.96.78.88 <none> 443/TCP 144d snapshot-controller ClusterIP 10.96.85.201 <none> 80/TCP 51d # 创建资源 [root@k8s-master01 etcd-service-monitor]# kubectl create -f etcd-service.yaml service/etcd-service created endpoints/etcd-service created # 创建后可以看到在 kube-system命名空间etcd-monitoring 名字的service [root@k8s-master01 etcd-service-monitor]# kubectl get service -n kube-system NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE etcd-service ClusterIP 10.96.8.216 <none> 2379/TCP 32s kube-dns ClusterIP 10.96.0.10 <none> 53/UDP,53/TCP,9153/TCP 144d kubelet ClusterIP None <none> 10250/TCP,10255/TCP,4194/TCP 2d20h metrics-server ClusterIP 10.96.78.88 <none> 443/TCP 144d snapshot-controller ClusterIP 10.96.85.201 <none> 80/TCP 51d [root@k8s-master01 etcd-service-monitor]# kubectl get -f etcd-service.yaml NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE service/etcd-monitoring ClusterIP 10.96.8.216 <none> 2379/TCP 6s NAME ENDPOINTS AGE endpoints/etcd-monitoring 192.168.0.200:2379,192.168.0.201:2379,192.168.0.202:2379 6s
通过etcd-service的Service的ClusterIP进行访问测试:
1 2 3 4 5 6 [root@k8s-master01 etcd-service-monitor]# curl -s --cacert /etc/kubernetes/pki/etcd/etcd-ca.pem --cert /etc/kubernetes/pki/etcd/etcd.pem --key /etc/kubernetes/pki/etcd/etcd-key.pem https://10.96.8.216:2379/metrics -k|tail -5 # HELP promhttp_metric_handler_requests_total Total number of scrapes by HTTP status code. # TYPE promhttp_metric_handler_requests_total counter promhttp_metric_handler_requests_total{code="200"} 2 promhttp_metric_handler_requests_total{code="500"} 0 promhttp_metric_handler_requests_total{code="503"} 0
1.3创建Secret Secret 的作用是把 Prometheus 访问 etcd 所需的 TLS 凭据交给 Prometheus Pod 使用。kube-prometheus 的外部 etcd 方案同样会将 CA、客户端证书、私钥存入 Secret,再由 Operator 使 Prometheus 加载该 Secret
接下来创建 Etcd 证书的 Secret(证书路径根据实际环境进行更改):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 # 创建etcd的secret,将这个secret挂载到prometheus的pod中,因为prometheus请求etcd的metrics接口需要证书,secret有命名空间隔离性,所以创建的secret要跟prometheus的pod在同一个命名空间中 [root@k8s-master01 etcd-service-monitor]# kubectl create secret generic etcd-ssl \ --from-file=/etc/kubernetes/pki/etcd/etcd-ca.pem \ --from-file=/etc/kubernetes/pki/etcd/etcd.pem \ --from-file=/etc/kubernetes/pki/etcd/etcd-key.pem -n monitoring # 命令解释: kubectl:Kubernetes 命令行工具,用于与 Kubernetes API 进行交互。 create secret:kubectl 子命令,用于创建 Secret 资源。Secret 用于在 Kubernetes 中安全地存储敏感信息,比如密码、证书、密钥等。 generic:表示创建一个“通用”类型的 Secret(即 Opaque 类型),可以存储任意数据。 etcd-ssl:创建的Secret名称,名字是etcd-ssl。这个名称用于标识这个 Secret,后续引用这个 Secret 时可以使用该名称。 -n monitoring::指定 Secret 创建到的命名空间(namespace)。在这里,将 Secret 创建在 monitoring 命名空间下,这样只有该命名空间中的 Pod 或应用能够引用和访问此 Secret --from-file:用于将文件中的内容作为 Secret 的数据存储。可以多次使用此参数添加多个文件。 etcd-ca.pem 文件是 etcd 的 CA(Certificate Authority,证书颁发机构)证书,用于验证证书链的可信度 etcd.pem 文件是 etcd 服务端的 SSL 证书,用于身份验证。 etcd-key.pem 文件是 etcd 的私钥,用于加密和解密与 etcd 的 SSL 通信。
将证书挂载至 Prometheus 容器(由于 Prometheus 是 Operator 部署的,所以只需要修改Prometheus 资源即可):
1 2 3 4 5 6 7 8 9 10 # Prometheus资源是 Prometheus Operator 所管理的自定义资源(Custom Resource,CR) [root@k8s-master01 30-Prometheus]# kubectl get prometheus -n monitoring NAME VERSION DESIRED READY RECONCILED AVAILABLE AGE k8s 2.54.1 1 1 True True 296d # 编辑名字是k8s的prometheus资源 [root@k8s-master01 etcd-service-monitor]# kubectl edit prometheus k8s -n monitoring # 在prometheus的spec级别下添加证书配置 secrets: - etcd-ssl #要和上面创建的secret名字保持一致
保存退出后,Prometheus 的 Pod (prometheus-k8s-0)会自动重启,重启完成后,查看证书是否挂载(任意一个Prometheus 的 Pod 均可):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 [root@k8s-master01 etcd-service-monitor]# kubectl get po -n monitoring NAME READY STATUS RESTARTS AGE alertmanager-main-0 2/2 Running 4 (12m ago) 3d3h blackbox-exporter-75c7985cb8-xkxrs 3/3 Running 6 (12m ago) 3d3h grafana-75dcfd79-sk29h 1/1 Running 1 (12m ago) 2d5h kube-state-metrics-bbcd9ff4f-8c5vq 3/3 Running 7 (9m34s ago) 3d3h node-exporter-7b428 2/2 Running 2 (11m ago) 3d3h node-exporter-m2g8z 2/2 Running 2 (11m ago) 3d3h node-exporter-nvpz5 2/2 Running 2 (11m ago) 3d3h node-exporter-w7lrs 2/2 Running 2 (12m ago) 3d3h node-exporter-wwtnm 2/2 Running 4 (12m ago) 3d3h prometheus-adapter-77f8587965-5x7bn 1/1 Running 4 (10m ago) 3d3h prometheus-adapter-77f8587965-wgp55 1/1 Running 2 (9m38s ago) 3d3h prometheus-k8s-0 0/2 Init:0/1 0 2s prometheus-operator-6f9479b5f5-4zpfm 2/2 Running 3 (9m48s ago) 3d3h # 待pod重启完成,进入prometheus-k8s-0的pod中验证证书是否挂载成功: [root@k8s-master01 30-Prometheus]# kubectl exec -ti -n monitoring prometheus-k8s-0 -- sh /prometheus $ ls -l /etc/prometheus/secrets/etcd-ssl/ #证书已经成功挂载 total 0 lrwxrwxrwx 1 root 2000 18 Jul 12 05:50 etcd-ca.pem -> ..data/etcd-ca.pem lrwxrwxrwx 1 root 2000 19 Jul 12 05:50 etcd-key.pem -> ..data/etcd-key.pem lrwxrwxrwx 1 root 2000 15 Jul 12 05:50 etcd.pem -> ..data/etcd.pem
1.4创建ServiceMonitor 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 # 配置ServiceMonitor并介绍配置参数 [root@k8s-master01 etcd-service-monitor]# vim etcd-servicemonitor.yaml # ServiceMonitor资源配置内容如下: kind: ServiceMonitor #定义资源类型为 ServiceMonitor,这是用于 Prometheus Operator 中监控服务的资源类型。 apiVersion: monitoring.coreos.com/v1 #该字段指定了 API 的版本,monitoring.coreos.com/v1 是 ServiceMonitor 的标准 API 版本。 metadata: #定义该资源的元数据部分,用于定义资源的名称和标签命名空间等信息。 name: etcd-servicemonitor #定义该 ServiceMonitor 资源的名称为 etcd-servicemonitor。 namespace: monitoring #定义该 ServiceMonitor 资源所在的命名空间为 monitoring。 labels: #定义该 ServiceMonitor 资源的标签,用于标识该资源。 app: etcd-servicemonitor #标签的键为 app,值为 etcd-servicemonitor。Prometheus(由 Prometheus Operator 管理)通过 .spec.serviceMonitorSelector 字段来决定:“我只监控那些带有特定标签的 ServiceMonitor” 。因为在prometheus资源中"serviceMonitorSelector: {}" 定义了空选择器,空选择器匹配所有资源。(kubectl get prometheus -n monitoring k8s -oyaml|grep serviceMonitorSelector) 如果Prometheus的.spec.serviceMonitorSelector不是空选择器,那么ServiceMonitor这里定义的标签就要和Prometheus的.spec.serviceMonitorSelector中定义的标签保持一致。 spec: #定义该 ServiceMonitor 资源的具体配置。 jobLabel: etcd #jobLabel的值应该填写 Service 中label的 key(键名),Prometheus Operator 会去读取 Service 上对应 key 的 value,作为最终的 job 标签。 namespaceSelector: #命名空间选择器,用于指定监控哪些命名空间下的 Service。 matchNames: #名字空间匹配列表,从该列表中定义的命名空间下找目标 Service。 - kube-system #找kube-system 命名空间下的 Service。 selector: #选择器,用于指定监控哪些 Service。 matchLabels: #标签匹配器 etcd: monitoring #找标签是etcd: monitoring的Service。也就是从namespaceSelector.matchNames中定义的命名空间下,选择标签是etcd: monitoring的Service。 endpoints: #定义监控的目标端点。 - port: metrics #这个port字段的值对应 Service.spec.ports.name的值保持一致,必须与 Service 的定义一致。 interval: 30s #配置 Prometheus 拉取该服务指标的间隔时间,表示每 30 秒拉取一次。 scheme: https #设置请求协议为 https。如果其他服务不需要证书验证,可以设置为 http。 tlsConfig: #配置 TLS 证书验证。 caFile: /etc/prometheus/secrets/etcd-ssl/etcd-ca.pem #指定 CA 证书文件的路径, 这个路径是Prometheus 容器内的路径,而不是 Kubernetes 主机的路径。 certFile: /etc/prometheus/secrets/etcd-ssl/etcd.pem #指定客户端证书文件的路径。这个路径是Prometheus 容器内的路径,而不是 Kubernetes 主机的路径。 keyFile: /etc/prometheus/secrets/etcd-ssl/etcd-key.pem #指定客户端私钥文件的路径。这个路径是Prometheus 容器内的路径,而不是 Kubernetes 主机的路径。 insecureSkipVerify: true #是否跳过证书验证,true 表示跳过,false 表示不跳过。如果你在开发/测试环境中使用自签名证书,这个可以设置为 true,但在生产环境中建议为 false。 ---------------------------------------------- # 配置ServiceMonitor资源时产生的疑问解答: 背景:prometheus相关的pod服务是部署在monitoring命名空间中,而要监控的etcd是二进制安装的服务,为etcd创建的service是在kube-system命名空间中,为etcd的service配置的ServiceMonitor资源是部署在monitoring命名空间中。 问题1:ServiceMonitor 与 Prometheus 的命名空间关系:ServiceMonitor 不需要与 Prometheus Pod 在同一个命名空间,Prometheus 可以发现并使用不同命名空间中的 ServiceMonitor,关键是要在 Prometheus CR (Custom Resource) 中正确配置,serviceMonitorNamespaceSelector 和 serviceMonitorSelector 问题2:ServiceMonitor 与被监控 Service 的命名空间关系:ServiceMonitor 不需要与被监控的 Service 在同一个命名空间,通过 ServiceMonitor资源中的namespaceSelector 字段可以指定要监控的 Service 所在的命名空间,可以监控多个命名空间中的 Service 问题3:ServiceMonitor资源的配置中spec.jobLabel的使用: # Service 配置 apiVersion: v1 kind: Service metadata: name: etcd-service labels: etcd: monitoring # 这个标签的value将被用作 job 名称,标签的key作为ServiceMonitor.spec.jobLabel的名称 ... --- # ServiceMonitor 配置 apiVersion: monitoring.coreos.com/v1 kind: ServiceMonitor metadata: name: etcd-monitor spec: jobLabel: etcd # 使用 Service 中 key 为 "etcd" 的标签值作为 job 名称 selector: matchLabels: etcd: monitoring # 这样配置在 Prometheus 中的表现为: # 没有配置 jobLabel 时 etcd_cluster_version{cluster_version="3.5", endpoint="etcd-client", instance="192.168.0.81:2379",job="etcd-service",namespace="kube-system", service="etcd-service"} # 配置了 jobLabel: etcd 后 etcd_cluster_version{cluster_version="3.5", endpoint="etcd-client", instance="192.168.0.81:2379", job="monitoring", namespace="kube-system", service="etcd-service"} # 使用场景:当你需要自定义 Prometheus 中显示的 job 名称时 # 想要使用 Service 中的特定标签作为作业标识时 # 在有多个相同类型服务时,需要区分不同实例的监控数据 问题4:ServiceMonitor中tlsConfig的作用: # ServiceMonitor 资源中的 tlsConfig 是用来配置 Prometheus 与目标服务(例如 etcd 服务)之间的 TLS/SSL 安全连接的。具体而言,tlsConfig 用来指定 Prometheus 在抓取目标服务的 /metrics 端点时,如何处理 HTTPS 请求的证书校验和加密配置。tlsConfig中配置的证书文件是 Prometheus 容器内的路径,而不是 Kubernetes 宿主机的路径。 # caFile这是 Prometheus 用于验证 etcd 服务端证书的 CA 证书 (Certificate Authority) # certFile这是 Prometheus 客户端使用的证书文件,用于客户端认证。 # keyFile这是 Prometheus 客户端的私钥文件,配合 certFile 来进行客户端认证。。 问题5:已经在Prometheus的pod中挂载了证书文件为什么还要在ServiceMonitor中配置tlsConfig?: # 答:在 Prometheus 中挂载了相关的证书 和 在 ServiceMonitor 中配置 tlsConfig 是两个不同的概念,虽然它们看似相关,但它们的目的和作用是不同的。让我们深入理解为什么即使证书已经挂载到 Prometheus 中,仍然需要在 ServiceMonitor 中配置 tlsConfig。Prometheus 中挂载的证书的作用:挂载的目的仅仅是将证书文件放置在 Prometheus 容器的文件系统中,供 Prometheus 使用。证书文件可以被 Prometheus 访问使用,但 Prometheus 不会自动知道每个抓取任务应该如何使用这些证书,除非你在 ServiceMonitor 中明确指定。tlsConfig 是 ServiceMonitor 的一部分,用于配置 Prometheus 在抓取 HTTPS 端点时,如何使用证书处理 TLS/SSL 协议、证书校验和客户端认证。换句话说就是当你有多个服务需要使用证书进行通信时,需要将每个服务的证书都挂载到Prometheus的容器中,这时Prometheus并不知道哪个服务应该使用哪个证书,这是就需要在ServiceMonitor定义tlsConfig来告诉Prometheus如何使用证书,所以这两个配置缺一不可:①证书挂载:提供文件访问能力;②tlsConfig:指导证书使用方式
创建上述的ServiceMonitor资源:
1 2 3 4 5 6 7 8 # 创建资源 [root@k8s-master01 etcd-service-monitor]# kubectl create -f etcd-servicemonitor.yaml servicemonitor.monitoring.coreos.com/etcd-servicemonitor created # 查看资源创建情况etcd-servicemonitor [root@k8s-master01 ~]# kubectl get servicemonitors.monitoring.coreos.com -n monitoring NAME AGE etcd-servicemontion 294d
通过prometheus的service暴露的端口在网页端查看是否存在etcd的监控:
点击页面的[Status]—[Targets]
按照下图的选择,能看到配置的ServiceMonitor资源名称(etcd-servicemonitor),则说明配置的正确:
1.5Grafana配置etcd监控模板 接下来打开Grafana,添加 Etcd 的监控面板:
首先去https://grafana.com/grafana/dashboards找合适的模板:输入条件,在结果中找适合自己的模板。
以下图中的模板为例:打开模板复制连接(https://grafana.com/grafana/dashboards/9733-etcd-for-k8s-cn/),在grafana的控制台中添加:
在grafana中新建模板:【导入模板】-【加载模板链接】-【自定义模板名字】-【选择数据源】-点击【import】即可导入。
配置完成后可以看到下图的监控指标:
2.非云原生监控 2.1监控MySQL服务 如果想要监控一些没有提供 Metrics 接口的服务,比如 MySQL、Redis 等,需要安装对应的 Exporter 才能进行监控。本笔记将使用 MySQL 作为一个测试用例,演示如何使用 Exporter 监控非云原生应用。
如果已经有现成的mysql就不需要创建了,我这里是没有,所以部署一个用于测试的MySQL实例来演示。
2.1.1部署测试实例 直接部署一个MySQL服务:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 # 简单运行一个mysql的deployment服务,该命令不适用生产环境 [root@k8s-master01 ~]# kubectl create deployment mysql --image=registry.cn-beijing.aliyuncs.com/k8s-liujunwei/mysql:8.0.39 # 查看pod发现无法启动 [root@k8s-master01 mysql-monitor]# kubectl get po NAME READY STATUS RESTARTS AGE mysql-76b85c9b9d-mr6hq 0/1 CrashLoopBackOff 4 (44s ago) 2m54s # 此时pod无法正常启动,查看日志提示需要设置root用户密码 [root@k8s-master01 mysql-monitor]# kubectl logs -f mysql-76b85c9b9d-mr6hq 2026-07-15 15:02:02+00:00 [Note] [Entrypoint]: Entrypoint script for MySQL Server 8.0.39-1.el9 started. 2026-07-15 15:02:02+00:00 [Note] [Entrypoint]: Switching to dedicated user 'mysql' 2026-07-15 15:02:02+00:00 [Note] [Entrypoint]: Entrypoint script for MySQL Server 8.0.39-1.el9 started. 2026-07-15 15:02:03+00:00 [ERROR] [Entrypoint]: Database is uninitialized and password option is not specified You need to specify one of the following as an environment variable: - MYSQL_ROOT_PASSWORD - MYSQL_ALLOW_EMPTY_PASSWORD - MYSQL_RANDOM_ROOT_PASSWORD # 设置mysql的密码,否则pod是不能正常启动的 [root@k8s-master01 mysql-monitor]# kubectl set env deployment mysql MYSQL_ROOT_PASSWORD=mysql deployment.apps/mysql env updated # 查看pod的状态是否正常 [root@k8s-master01 mysql-monitor]# kubectl get po NAME READY STATUS RESTARTS AGE mysql-965c7bd7f-zf42t 1/1 Running 0 3s
2.1.2为MySQL服务创建service: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 # 可以使用命令为deployment创建一个service [root@k8s-master01 30-Prometheus]# kubectl expose deployment mysql --port 3306 service/mysql exposed # kubectl get svc -l ap # 也可以通过编写yaml文件: kind: Service apiVersion: v1 metadata: name: mysql-service labels: app: mysql spec: type: ClusterIP ports: - name: mysql port: 3306 targetPort: 3306 selector: app: mysql 命令和yaml的方式二选一即可。
检查service是否可用:
1 2 3 4 5 6 7 [root@k8s-master01 etcd-service-monitor]# telnet 10.96.150.170 3306 Trying 10.96.150.170... Connected to 10.96.150.170. Escape character is '^]'. J 5.7.446d0t'4OyA!&CYVE%Dmysql_native_passwordXshell !#08S01Got packets out of orderConnection closed by foreign host.
2.1.3.在mysql中创建一个监控用户: 在数据库中创建一个监控专用的用户给Exporter,不要直接使用root用户 ,Exporter 使用一个最小权限 MySQL 账户连接数据库并转换为 Prometheus 指标;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 # 进入pod中创建监控使用的用户并授予相应的权限 [root@k8s-master01 etcd-service-monitor]# kubectl exec -ti mysql-85d75646bc-9nw68 -- bash bash-4.2# mysql -uroot -p Enter password: Welcome to the MySQL monitor. Commands end with ; or \g. Your MySQL connection id is 7 Server version: 5.7.44 MySQL Community Server (GPL) Copyright (c) 2000, 2023, Oracle and/or its affiliates. Oracle is a registered trademark of Oracle Corporation and/or its affiliates. Other names may be trademarks of their respective owners. Type 'help;' or '\h' for help. Type '\c' to clear the current input statement. # 创建用户 mysql> create user 'exporter' @'%' identified by 'exporter' with max_user_connections 10; Query OK, 0 rows affected (0.00 sec) #with max_user_connections 10参数作用是限制用户最大的连接数是10 # 授权 mysql> GRANT PROCESS, REPLICATION CLIENT, SELECT ON *.* TO 'exporter' @'%' ; Query OK, 0 rows affected (0.00 sec) # 刷新数据库 mysql> FLUSH PRIVILEGES; Query OK, 0 rows affected (0.00 sec) # 创建好监控用的账号就可以退出MySQL了
2.1.4配置 MySQL Exporter 采集 MySQL 监控数据: 方式一:使用ConfigMap形式配置MySQL账号密码 创建 MySQL Exporter 的 ConfigMap、Deployment、Service:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 # MySQL Exporter 的 ConfigMap只是用来保存连接目标MySQL的一些连接信息,下面两种创建ConfigMap的方式二选一即可 # 方式一:直接创建ConfigMap apiVersion: v1 kind: ConfigMap metadata: name: mysql-exporter-config namespace: default data: .my.cnf: | [client] user=exporter #这里指定的是2.1.3步骤中创建的用户 password=exporter #这里的密码是2.1.3步骤中创建用户指定的密码 host=mysql.default.svc.cluster.local #这里mysql的主机地址是service暴露的地址,推荐写dns格式而不是ip地址 port=3306 #mysql的端口号 # 方式二:借助文件来创建,将连接MySQL的信息保存到my.cnf中,在使用命令创建ConfigMap时指定my.cnf文件 # 创建.my.cnf文件,内容如下: [root@k8s-master01 mysql-monitor]# cat >.my.cnf << EOF [client] user = exporter #这里指定的是2.1.3步骤中创建的用户 password = exporter #这里的密码是2.1.3步骤中创建用户指定的密码 host= mysql.default.svc.cluster.local port= 3306 EOF # .my.cnf内容如下,检查一遍 [root@k8s-master01 mysql-monitor]# cat .my.cnf [client] user = exporter password = exporter host= mysql.default.svc.cluster.local port= 3306 # 通过.my.cnf创建configmap,创建在default命名空间 [root@k8s-master01 mysql-monitor]# kubectl create cm mysql-exporter-config --from-file=.my.cnf configmap/mysql-exporter-config created # 查看创建的ConfigMap [root@k8s-master01 mysql-monitor]# kubectl get cm mysql-exporter-config -oyaml apiVersion: v1 data: .my.cnf: | [client] user = exporter password = exporter host= mysql.default.svc.cluster.local port= 3306 kind: ConfigMap metadata: creationTimestamp: "2026-07-20T11:23:01Z" name: mysql-exporter-config namespace: default resourceVersion: "74954979" uid: 644fe1ac-6b20-4aec-b100-87577440cd46 --- # 下面是创建 MySQL Exporter的 Deployment配置 [root@k8s-master01 mysql-monitor]# cat mysqld-export-deploy.yaml apiVersion: apps/v1 kind: Deployment metadata: name: mysql-exporter namespace: monitoring labels: #定义该Deployment资源的标签 app: mysql-exporter spec: replicas: 1 revisionHistoryLimit: 10 # 保留 10 个历史版本,方便回滚 selector: #选择器,用来根据 标签 选择要管理的pod,要跟下面template.metadatalabels中配置的标签保持一致 matchLabels: app: mysql-exporter template: #定义pod的模板 metadata: #pod的元数据 labels: #这里定义的是pod的标签 app: mysql-exporter #定义pod的标签,要和上面的spec.selector.matchLabels中定义的保持一致 spec: containers: - name: mysql-exporter image: registry.cn-beijing.aliyuncs.com/k8s-liujunwei/mysqld-exporter:v0.17.2 imagePullPolicy: IfNotPresent args: - --config.my-cnf=/etc/mysql-exporter/.my.cnf #这里指定的路径是volumeMounts中mountPath参数的路径 ports: - containerPort: 9104 name: metrics protocol: TCP volumeMounts: - name: mysql-config #引用在volumes.name的值 mountPath: /etc/mysql-exporter #容器中挂载的路径 readOnly: true #资源限制 resources: requests: cpu: 50m memory: 64Mi limits: cpu: 200m memory: 256Mi # 存活检查探针 livenessProbe: httpGet: path: /metrics port: metrics # 这里的port可以是9104,也可以指定containers.ports.name的值 initialDelaySeconds: 5 periodSeconds: 10 timeoutSeconds: 3 failureThreshold: 3 # 就绪检查探针 readinessProbe: httpGet: path: /metrics port: metrics # 这里的port可以是9104,也可以指定containers.ports.name的值 initialDelaySeconds: 15 periodSeconds: 20 timeoutSeconds: 5 failureThreshold: 3 volumes: #定义卷的配置 - name: mysql-config # 定义卷的名字,这个mysql-config名字会在上面volumeMounts.name中引用 configMap: name: mysql-exporter-config #这里name的值是上面创建的ConfigMap的名字mysql-exporter-config # 创建资源mysqld export 的deployment资源,资源创建在monitoring命名空间 [root@k8s-master01 mysql-monitor]# kubectl create -f mysqld-export-deploy.yaml deployment.apps/mysql-exporter created # 查看创建的资源,pod名是mysql-exporter-8588bb76c4-krf2p [root@k8s-master01 mysql-monitor]# kubectl get po -n monitoring NAME READY STATUS RESTARTS AGE alertmanager-main-0 2/2 Running 30 (<invalid> ago) 118d blackbox-exporter-86745676c9-gh88k 3/3 Running 45 (5h48m ago) 118d grafana-765f8849f-jmww8 1/1 Running 8 (5h44m ago) 9d kube-state-metrics-6797ccd666-2kfvz 3/3 Running 153 (5h48m ago) 271d mysql-exporter-8588bb76c4-krf2p 1/1 Running 0 75s #pod正常启动 node-exporter-4wjrj 2/2 Running 102 (5h48m ago) 302d node-exporter-k47mk 2/2 Running 96 (<invalid> ago) 302d node-exporter-m2j25 2/2 Running 100 (5h48m ago) 302d node-exporter-mf5cs 2/2 Running 100 (5h46m ago) 302d node-exporter-wjz6w 2/2 Running 98 (5h48m ago) 302d node-exporter-z8xsm 2/2 Running 94 (5h47m ago) 302d prometheus-adapter-684447ddb-l9dzw 1/1 Running 61 (5h48m ago) 271d prometheus-adapter-684447ddb-swdb9 1/1 Running 23 (5h48m ago) 205d prometheus-k8s-0 2/2 Running 7 (5h44m ago) 9d prometheus-operator-57b579d5b9-dwnww 2/2 Running 44 (5h48m ago) 205d # 检查通过pod的ip能不能正常获取到MySQL的监控数据,mysql_up 1 表示 Exporter 成功连接 MySQL,数据正常采集 [root@k8s-master01 mysql-monitor]# curl -s 172.16.135.177:9104/metrics|grep mysql_up # HELP mysql_up Whether the MySQL server is up. # TYPE mysql_up gauge mysql_up 1 # 为mysql exporter的deployment服务创建service [root@k8s-master01 mysql-monitor]# cat mysql-export-svc.yaml # mysql-exporter的service内容如下 apiVersion: v1 kind: Service metadata: name: mysql-exporter namespace: monitoring labels: app: mysql-exporter spec: type: ClusterIP ports: - port: 9104 targetPort: 9104 name: metrics #这里name定义的值会被ServiceMonitor中spec.endpoints.port引用 protocol: TCP selector: #这里的标签选择器是定义要关联pod的标签,作用是根据标签将流量转发到相应的pod上 app: mysql-exporter #这里的标签要和mysql exporter的Deployment中定义的pod标签保持一致 # 配置ServiceMonitor,用于Prometheus Operator发现并抓取mysql-exporter的metrics数据。 [root@k8s-master01 mysql-monitor]# cat mysql-exporter-servicemonitor.yaml # mysqld exporter的ServiceMonitor资源配置如下 apiVersion: monitoring.coreos.com/v1 kind: ServiceMonitor metadata: name: mysql-exporter-servicemonitor namespace: monitoring labels: # 定义该ServiceMonitor资源的标签。要想Prometheus能监听到ServiceMonitor,那么在 Prometheus CR(k8s)的serviceMonitorSelector参数中要包含该标签,默认配置是{},表示会监控所有ServiceMonitor。不配置标签也可以 release: prometheus spec: endpoints: - interval: 30s port: metrics #该字段与上述service资源中spec.ports.name的值保持一致,通过指定的端口名查找 path: /metrics scheme: http selector: matchLabels: app: mysql-exporter namespaceSelector: matchNames: - monitoring
创建上述资源:(可以在一个文件中写多个资源,也可以分开写,每个资源单独一个文件)
1 2 3 4 # 创建资源的命令如果已经执行过就不用在执行 kubectl create -f mysqld-export-deploy.yaml kubectl create -f mysql-export-svc.yaml kubectl create -f mysql-exporter-servicemonitor.yaml
方式二:使用Secret形式定义MySQL账号密码 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 # 配置一个secret,给mysql exporter存储mysql的连接信息。 [root@k8s-master01 mysql-monitor]# cat mysql-secret.yaml # Secret配置如下 apiVersion: v1 kind: Secret metadata: name: mysql-exporter-secret namespace: monitoring type: Opaque stringData: .my.cnf: |- [client] #host=192.168.0.117 #host定义mysql服务器的IP地址,如果mysql服务器是在k8s集群外部,直接定义为mysql服务器的IP地址即可。 host=mysql.default.svc.cluster.local #mysql的主机地址,这种配置是mysql服务部署在k8s集群内部,如果mysql服务器在k8s集群内部,则需要使用服务名来定义,mysql是MySQL服务的service名称,default是数据库service所在的命名空间 port=3306 #mysql服务的端口 user=exporter #监控使用的用户 password=exporter #监控用户的密码 # 创建 Secret 资源,Secret资源创建在monitoring命名空间 [root@k8s-master01 mysql-monitor]# kubectl create -f mysql-secret.yaml secret/mysqld-exporter-secret created # 查看创建的Secret [root@k8s-master01 mysql-monitor]# kubectl get secrets -n monitoring NAME TYPE DATA AGE alertmanager-main Opaque 1 302d alertmanager-main-generated Opaque 1 302d alertmanager-main-tls-assets-0 Opaque 0 302d alertmanager-main-web-config Opaque 1 302d etcd-ssl Opaque 3 299d grafana-config Opaque 1 302d grafana-datasources Opaque 1 302d mysqld-exporter-secret Opaque 1 73s #这里 prometheus-k8s Opaque 1 302d prometheus-k8s-tls-assets-0 Opaque 0 302d prometheus-k8s-web-config Opaque 1 302d --- # 配置Deployment,用于部署mysql-exporter。 [root@k8s-master01 mysql-monitor]# cat mysqld-export-deploy.yaml # mysql-exporter的deployment内容如下 apiVersion: apps/v1 kind: Deployment metadata: name: mysql-exporter namespace: monitoring labels: #定义该Deployment资源的标签 app: mysql-exporter spec: replicas: 1 revisionHistoryLimit: 10 # 保留 10 个历史版本,方便回滚 selector: #选择器,用来根据 标签 选择要管理的pod,要跟下面template.metadatalabels中配置的标签保持一致 matchLabels: app: mysql-exporter template: #定义pod的模板 metadata: #pod的元数据 labels: #这里定义的是pod的标签 app: mysql-exporter #定义pod的标签,要和上面的spec.selector.matchLabels中定义的保持一致 spec: containers: - name: mysql-exporter image: registry.cn-beijing.aliyuncs.com/k8s-liujunwei/mysqld-exporter:v0.17.2 env: - name: TZ value: "Asia/Shanghai" args: - --config.my-cnf=/etc/mysql/.my.cnf #这里指定的路径是volumeMounts中mountPath参数的路径 ports: - containerPort: 9104 name: metrics protocol: TCP volumeMounts: - name: mysql-config mountPath: /etc/mysql #资源限制 resources: requests: cpu: 50m memory: 64Mi limits: cpu: 200m memory: 256Mi # 存活检查探针 livenessProbe: httpGet: path: /metrics port: 9104 # 这里的port可以是9104,也可以指定containers.ports.name中指定的名称metrics initialDelaySeconds: 5 periodSeconds: 10 timeoutSeconds: 3 failureThreshold: 3 # 就绪检查探针 readinessProbe: httpGet: path: /metrics port: 9104 # 这里的port可以是9104,也可以指定containers.ports.name中指定的名称metrics initialDelaySeconds: 15 periodSeconds: 20 timeoutSeconds: 5 failureThreshold: 3 volumes: #定义卷 - name: mysql-config #定义卷的名字 secret: #卷类型是secret secretName: mysql-exporter-secret #指定secret的名字 # 配置Service,用于将mysql-exporter暴露给集群内部的其他服务。 [root@k8s-master01 mysql-monitor]# cat mysql-export-svc.yaml # mysql-exporter的service内容如下 apiVersion: v1 kind: Service metadata: name: mysql-exporter namespace: monitoring labels: app: mysql-exporter spec: selector: #这里的标签选择器是定义要关联pod的标签,作用是根据标签将流量转发到相应的pod上 app: mysql-exporter ports: - port: 9104 targetPort: metrics #这里可以指定对应 Deployment 中容器定义的端口号9104(字段containers.ports.containerPort的值),也可以指定容器定义的端口名字metrics(字段containers.ports.name的值) name: metrics # 创建上述service资源,也是在monitoring空间中 [root@k8s-master01 mysql-monitor]# kubectl create -f mysql-export-svc.yaml service/mysql-exporter created # 查看名字是mysql-exporter的service [root@k8s-master01 mysql-monitor]# kubectl get svc -n monitoring NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE alertmanager-main NodePort 10.96.212.247 <none> 9093:31264/TCP,8080:31841/TCP 302d alertmanager-operated ClusterIP None <none> 9093/TCP,9094/TCP,9094/UDP 302d blackbox-exporter ClusterIP 10.96.84.30 <none> 9115/TCP,19115/TCP 302d grafana NodePort 10.96.203.120 <none> 3000:30783/TCP 302d kube-state-metrics ClusterIP None <none> 8443/TCP,9443/TCP 302d mysql-exporter ClusterIP 10.96.169.112 <none> 9104/TCP 11h node-exporter ClusterIP None <none> 9100/TCP 302d prometheus-adapter ClusterIP 10.96.99.174 <none> 443/TCP 302d prometheus-k8s NodePort 10.96.79.200 <none> 9090:32600/TCP,8080:30317/TCP 302d prometheus-operated ClusterIP None <none> 9090/TCP 302d prometheus-operator ClusterIP None <none> 8443/TCP 302d # 使用临时容器测试通过service名称是否能获取到MySQL的监控数据,有mysql_up 1返回表示正常 kubectl run test --rm -it --image=registry.cn-beijing.aliyuncs.com/k8s-liujunwei/busybox:latest -n monitoring -- wget -qO- http://mysql-exporter:9104/metrics | grep mysql_up If you don't see a command prompt, try pressing enter. # HELP mysql_up Whether the MySQL server is up. # TYPE mysql_up gauge mysql_up 1 # 使用curl 命令通过service的ip也能获取到mysql的监控数据 [root@k8s-master01 mysql-monitor]# curl 10.96.169.112:9104/metrics |grep mysql_up % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 100 175k 0 175k 0 0 878k 0 --:--:-- --:--:-- --:--:-- 887k # HELP mysql_up Whether the MySQL server is up. # TYPE mysql_up gauge mysql_up 1 # 配置ServiceMonitor,用于Prometheus Operator发现并抓取mysql-exporter的metrics数据。 [root@k8s-master01 mysql-monitor]# cat mysql-exporter-servicemonitor.yaml # mysqld exporter的ServiceMonitor资源配置如下 apiVersion: monitoring.coreos.com/v1 kind: ServiceMonitor metadata: name: mysql-exporter-servicemonitor namespace: monitoring # labels: #release: prometheus spec: jobLabel: app #jobLabel的值应该填写 Service 中label的 key(键名),Prometheus Operator 会去读取 Service 上对应 key 的 value,作为最终的 job 标签。 namespaceSelector: #定义service所在的命名空间 matchNames: #命名空间匹配,也就是从哪个命名空间找具有上述标签的service - monitoring selector: #标签选择器 matchLabels: #匹配标签 app: mysql-exporter #意思是匹配具有app=mysql-exporter标签的service endpoints: - port: metrics #该字段与上述service资源中的port字段对应(Service.spec.ports.name),用于指定抓取的metrics端口 interval: 30s scheme: http path: /metrics # 创建servicemonitor资源 [root@k8s-master01 mysql-monitor]# kubectl create -f mysql-exporter-servicemonitor.yaml servicemonitor.monitoring.coreos.com/mysql-exporter-servicemonitor created # 查看创建的资源 [root@k8s-master01 mysql-monitor]# kubectl get servicemonitors.monitoring.coreos.com -n monitoring NAME AGE alertmanager-main 302d blackbox-exporter 302d coredns 302d grafana 302d kube-apiserver 302d kube-controller-manager 302d kube-scheduler 302d kube-state-metrics 302d kubelet 302d mysql-exporter-servicemonitor 91s node-exporter 302d prometheus-adapter 302d prometheus-k8s 302d prometheus-operator 302d
上述的两种(ConfigMap和Secret)配置密码的方式二选一配置即可,建议使用方式二Secret
所有资源创建完成后在prometheus的web端查看是否有mysql的监控指标:
2.1.5Grafana配置mysql监控模板 导入 Grafana Dashboard,地址:https://grafana.com/grafana/dashboards/14057-mysql/,https://grafana.com/grafana/dashboards/6239-mysql/ ,https://grafana.com/grafana/dashboards/17320-1-mysqld-exporter-dashboard/(选择一个模板使用即可,)导入步骤和之前类似,在此不再演示。导入完成后,即可在 Grafana 看到监控数据:
如果输入mysql关键字只有下图两个指标,是不对的,表示mysql exporter并没有拿到各项指标数据,需要进一步排查错误。这里遇到的就是在mysql中创建的exporter用户密码不正确导致的。
2.1.6告警中服务的真实地址 在使用”独立部署的 exporter + 被监控的目标服务分离”这种架构,几乎所有同类 exporter(PostgreSQL exporter、Kafka exporter 等)都会遇到PrometheusRule资源中获取到的 instance 并不是服务真是的地址,而是exporter的地址,在收到的告警信息中是exporter的地址挂了,当MySQL服务宕机时,收到的告警信息并不能真实反应宕机的目标MySQL。
常见受影响的 exporter 举例
Exporter
默认 instance 显示的地址
你期望看到的地址
mysqld_exporter
exporter 的 IP:9104
MySQL 的 IP:3306
redis_exporter
exporter 的 IP:9121
Redis 的 IP:6379
kafka_exporter
exporter 的 IP:9308
Kafka broker 地址
blackbox_exporter
exporter 的 IP:9115
被探测的网站/服务地址
postgres_exporter
exporter 的 IP:9187
PostgreSQL 的地址
不管哪种 exporter,本质思路都一样,单目标exporter中,给exporter服务打上annotations标签来记录真实目标地址,ServiceMonitor 里用 relabelings 把它写入 instance
第一步:给 Pod 打上真实 MySQL 地址
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 # 编辑exporter添加annotations标签,关键点说明:annotation 一定要写在 spec.template.metadata.annotations 下才会被同步到实际运行的 Pod 上; [root@k8s-master01 ~]# kubectl edit deployments.apps -n monitoring mysql-exporter 1 # Please edit the object below. Lines beginning with a '#' will be ignored, 2 # and an empty file will abort the edit. If an error occurs while saving this file will be 3 # reopened with the relevant failures. 4 # 5 apiVersion: apps/v1 6 kind: Deployment 7 metadata: 8 annotations: 9 deployment.kubernetes.io/revision: "2" 10 creationTimestamp: "2026-07-20T15:09:43Z" 11 generation: 2 12 labels: 13 app: mysql-exporter 14 name: mysql-exporter 15 namespace: monitoring 16 resourceVersion: "82339152" 17 uid: e3ef65c7-5564-4924-a46b-3f232121c194 18 spec: 19 progressDeadlineSeconds: 600 20 replicas: 1 21 revisionHistoryLimit: 10 22 selector: 23 matchLabels: 24 app: mysql-exporter 25 strategy: 26 rollingUpdate: 27 maxSurge: 25% 28 maxUnavailable: 25% 29 type: RollingUpdate 30 template: 31 metadata: 32 annotations: #在pod区域定义该标签 33 mysql_target: mysql.default.svc.cluster.local:3306 34 creationTimestamp: null 35 labels: 36 app: mysql-exporter 37 spec: 38 containers: 39 - args:
第二步:修改 ServiceMonitor,加 relabelings
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 # 在ServiceMonitor的spec.endpoints下添加relabelings配置 [root@k8s-master01 ~]# kubectl edit servicemonitors.monitoring.coreos.com -n monitoring mysql-exporter-servicemonitor 1 # Please edit the object below. Lines beginning with a '#' will be ignored, 2 # and an empty file will abort the edit. If an error occurs while saving this file will be 3 # reopened with the relevant failures. 4 # 5 apiVersion: monitoring.coreos.com/v1 6 kind: ServiceMonitor 7 metadata: 8 creationTimestamp: "2026-07-21T04:44:03Z" 9 generation: 4 10 name: mysql-exporter-servicemonitor 11 namespace: monitoring 12 resourceVersion: "82344397" 13 uid: ed8df757-e5e2-4a1c-b8c0-7887b530a7bc 14 spec: 15 endpoints: 16 - interval: 30s 17 path: /metrics 18 port: metrics 19 relabelings: #添加19-22行的配置 20 - action: replace 21 sourceLabels: [__meta_kubernetes_pod_annotation_mysql_target] 22 targetLabel: instance 23 24 scheme: http 25 namespaceSelector: 26 matchNames: 27 - monitoring 28 selector: 29 matchLabels: 30 app: mysql-exporter
第三步:验证效果
打开 Prometheus UI,在 Graph 页面执行 mysql_up,确认返回结果的 instance 标签值:
第四步:告警规则无需改动
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 apiVersion: monitoring.coreos.com/v1 kind: PrometheusRule metadata: name: database-monitor-alerts namespace: monitoring labels: prometheus: k8s role: alert-rules spec: groups: - name: database-alerts rules: # 🔴 规则 1:MySQL 宕机 - alert: MySQLDown expr: mysql_up == 0 for: 1m labels: severity: critical team: dba annotations: summary: "MySQL 实例 {{ $labels.instance }} 宕机 🚨" description: "数据库已断开连接超过 1 分钟,请立即排查业务影响!"
现在触发时 {{ $labels.instance }} 渲染出来的就是 mysql.default.svc.cluster.local:3306,即真实的 MySQL 地址,语义就对了。
注意:在ServiceMonitor中定义的 [__meta_kubernetes_pod_annotation_mysql_target] 参数,其中mysql_target要和exporter中annotations定义key保持一致,如果在annotations定义成mysql_host,那么在ServiceMonitor中sourceLabels就要写成 [__meta_kubernetes_pod_annotation_mysql_host]
1 2 3 4 30 template: 31 metadata: 32 annotations: 33 mysql_host: mysql.default.svc.cluster.local:3306
1 2 3 4 5 6 7 8 9 14 spec: 15 endpoints: 16 - interval: 30s 17 path: /metrics 18 port: metrics 19 relabelings: 20 - action: replace 21 sourceLabels: [__meta_kubernetes_pod_annotation_mysql_host] 22 targetLabel: instance
2.2监控Redis服务 下面将演示通过Service Monitor 和 ScrapeConfig 两种方式对Redis进行监控,实际工作中选择其中一种方式即可。
使用ScrapeConfig监控Redid服务,参考文档:https://github.com/oliver006/redis_exporter
在生产环境中,ScrapeConfig 主要用于解决监控「目标不在 K8s 内」或「ServiceMonitor 的声明式抽象不够用」的问题 。
以下是典型适用场景:
目标类型
示例
为什么不用 ServiceMonitor
物理机/虚拟机
裸金属服务器、VMware/Proxmox 虚拟机
没有 K8s Pod/Service 可以关联
网络设备
交换机、路由器、防火墙(通过 SNMP exporter 或专用 exporter)
设备不在 K8s 中
服务器硬件
IPMI/BMC(通过 ipmi_exporter)、RAID 卡
硬件层面,无 K8s 概念
K8s 节点本身
Node Exporter 直接跑在节点上(非 DaemonSet 方式)
二进制部署的 node-exporter
2.2.1部署Redis服务 部署一个Redis服务作为监控对象,如果环境中已经有现成的redis可以省略该步骤。
下面将采用 StatefulSet + PVC + ConfigMap + Secret 的组合基于CubeFS 持久化存储部署一个单实例redis服务。
创建命名空间:
1 2 # 如果希望redis在单独的命名空间就创建一个ns,如redis-prod命名空间,笔记中我用default空间 kubectl create ns redis-prod
创建密码的Secret:
1 2 # 生产环境中必须设置redis密码 kubectl create secret generic redis-secret --from-literal=redis-password='redis'
通过ConfigMap配置redis.conf:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 # 使用自定义的redis配置文件 cat >redis.conf<< EOF bind 0.0.0.0 port 6379 protected-mode yes save 900 1 save 300 10 save 60 10000 rdbcompression yes rdbchecksum yes dbfilename dump.rdb dir /data appendonly yes appendfilename "appendonly.aof" appendfsync everysec no-appendfsync-on-rewrite no auto-aof-rewrite-percentage 100 auto-aof-rewrite-min-size 256mb aof-load-truncated yes maxmemory 512mb maxmemory-policy allkeys-lru maxmemory-samples 5 lazyfree-lazy-eviction yes lazyfree-lazy-expire yes lazyfree-lazy-server-del yes slowlog-log-slower-than 10000 slowlog-max-len 1024 loglevel notice rename-command FLUSHALL "" rename-command FLUSHDB "" rename-command DEBUG "" rename-command SHUTDOWN "SHUTDOWN_XINCHUAN_2026" maxclients 500 tcp-keepalive 300 tcp-backlog 511 timeout 0 databases 16 hz 10 activedefrag yes EOF # 创建configmap [root@k8s-master01 redis-monitor]# kubectl create configmap redis-config-configmap --from-file=redis.conf configmap/redis-config-configmap created
以StatefulSet 创建redis资源:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 [root@k8s-master01 redis-monitor ] apiVersion: apps/v1 kind: StatefulSet metadata: name: redis labels: app: redis spec: replicas: 1 selector: matchLabels: app: redis template: metadata: labels: app: redis spec: containers: - name: redis image: registry.cn-beijing.aliyuncs.com/k8s-liujunwei/redis:latest command: ["redis-server" , "/etc/redis/redis.conf" ] args: - --requirepass - "$(REDIS_PASSWORD)" ports: - containerPort: 6379 name: redis env: - name: REDIS_PASSWORD valueFrom: secretKeyRef: name: redis-secret key: redis-password resources: requests: cpu: "500m" memory: "1Gi" limits: cpu: "1000m" memory: "2Gi" volumeMounts: - name: redis-config mountPath: /etc/redis - name: redis-data mountPath: /data readinessProbe: exec: command: - sh - -c - redis-cli -a "$REDIS_PASSWORD" ping initialDelaySeconds: 5 periodSeconds: 10 livenessProbe: exec: command: - sh - -c - redis-cli -a "$REDIS_PASSWORD" ping initialDelaySeconds: 15 periodSeconds: 20 volumes: - name: redis-config configMap: name: redis-config-configmap volumeClaimTemplates: - metadata: name: redis-data spec: accessModes: ["ReadWriteOnce" ] storageClassName: cfs-sc resources: requests: storage: 10Gi [root@k8s-master01 redis-monitor ] statefulset.apps/redis created [root@k8s-master01 redis-monitor ] NAME READY STATUS RESTARTS AGE mysql-965c7bd7f-zf42t 1 /1 Running 1 (2d2h ago) 6d21h redis-0 0 /1 ContainerCreating 0 48s
验证服务:
1 2 3 4 5 6 7 8 # redis服务已经正常运行 [root@k8s-master01 redis-monitor]# kubectl exec -ti redis-0 -- bash redis@redis-0:/data$ redis-cli 127.0.0.1:6379> auth redis OK 127.0.0.1:6379> ping PONG 127.0.0.1:6379>
为redis的StatefulSet创建一个Service:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 [root@k8s-master01 redis-monitor ] apiVersion: v1 kind: Service metadata: name: redis-headless-service labels: app: redis spec: clusterIP: None selector: app: redis ports: - port: 6379 targetPort: 6379 protocol: TCP name: redis apiVersion: v1 kind: Service metadata: name: redis-service labels: app: redis spec: type: ClusterIP selector: app: redis ports: - port: 6379 targetPort: 6379 protocol: TCP name: redis [root@k8s-master01 redis-monitor ] service/redis-service created [root@k8s-master01 redis-monitor ] NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE kubernetes ClusterIP 10.96 .0 .1 <none> 443 /TCP 204d mysql ClusterIP 10.96 .162 .46 <none> 3306 /TCP 6d10h redis-headless ClusterIP None <none> 6379 /TCP 37m redis-service ClusterIP 10.96 .7 .166 <none> 6379 /TCP 41m [root@k8s-master01 redis-monitor ] NAME ENDPOINTS AGE kubernetes 192.168 .0 .81 :6443,192.168.0.82:6443,192.168.0.83:6443 204d mysql 172.16 .135 .181 :3306 6d10h redis-headless 172.16 .135 .186 :6379 37m redis-service 172.16 .135 .186 :6379 41m
2.2.2通过Service Monitor监控 1.部署Redis Exporter服务 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 [root@k8s-master01 redis-monitor ] apiVersion: apps/v1 kind: Deployment metadata: name: redis-exporter-deploy spec: replicas: 1 selector: matchLabels: app: redis-exporter template: metadata: labels: app: redis-exporter spec: containers: - name: redis-exporter image: registry.cn-beijing.aliyuncs.com/k8s-liujunwei/redis_exporter:v1.86.0 ports: - containerPort: 9121 env: - name: REDIS_ADDR value: redis://redis-service.default.svc.cluster.local:6379 - name: REDIS_PASSWORD valueFrom: secretKeyRef: name: redis-secret key: redis-password [root@k8s-master01 redis-monitor ] deployment.apps/redis-exporter created [root@k8s-master01 redis-monitor ] NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES mysql-965c7bd7f-zf42t 1 /1 Running 1 (2d22h ago) 7d16h 172.16 .135 .181 k8s-node03 <none> <none> redis-0 1 /1 Running 0 19h 172.16 .135 .186 k8s-node03 <none> <none> redis-exporter-deploy-5d4ff76c6d-dkhv9 1 /1 Running 0 35s 172.16 .85 .248 k8s-node01 <none> <none> [root@k8s-master01 redis-monitor ] % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 100 33671 0 33671 0 0 967k 0 --:--:-- --:--:-- --:--:-- 967k redis_up 1 redis_uptime_in_seconds 69353
2.为Redis Exporter创建Service服务 将Redis Exporter通过Service服务暴露到集群中,Service Monitor通过该Service获取监控数据
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 # Redis Exporter 的Service内容如下 [root@k8s-master01 redis-monitor]# cat redis-exporter-deployment-service.yaml apiVersion: v1 kind: Service metadata: name: redis-exporter-service labels: app: redis-exporter spec: selector: app: redis-exporter #这里的标签要与Redis Exporter的pod标签保持一致 ports: - name: http port: 9121 targetPort: 9121
创建该Service:
1 2 [root@k8s-master01 redis-monitor]# kubectl create -f redis-exporter-deployment-service.yaml service/redis-exporter-service created
验证通过service的ip是否能获取监控数据:
1 2 3 4 5 6 7 8 9 10 11 # 看到redis_up 1 说明 Exporter 已正常采集 Redis。 [root@k8s-master01 redis-monitor]# curl http://10.96.89.229:9121/metrics |grep redis_up % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 100 37155 0 37155 0 0 1451k 0 --:--:-- --:--:-- --:--:-- 1511k # 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 70072
3.创建 ServiceMonitor 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 # mysqld exporter的ServiceMonitor资源配置如下 [root@k8s-master01 redis-monitor]# cat redis-exporter-servicemonitor.yaml apiVersion: monitoring.coreos.com/v1 kind: ServiceMonitor metadata: name: redis-exporter-servicemonitor namespace: monitoring # labels: #release: prometheus spec: jobLabel: app #jobLabel的值应该填写 Service 中label的 key(键名),Prometheus Operator 会去读取 Service 上对应 key 的 value,作为最终的 job 标签。 namespaceSelector: #定义service所在的命名空间 matchNames: #命名空间匹配,也就是从哪个命名空间找具有目标 标签的service - default selector: #标签选择器 matchLabels: #匹配标签 app: redis-exporter #意思是匹配具有app=redis-exporter标签的service endpoints: - port: http #该字段与service资源中的ports字段中的name对应(Service.spec.ports.name),用于指定抓取的metrics端口 interval: 30s scheme: http path: /metrics
创建 ServiceMonitor,资源创建在monitoring空间:
1 2 3 [root@k8s-master01 redis-monitor]# kubectl create -f redis-exporter-servicemonitor.yaml servicemonitor.monitoring.coreos.com/redis-exporter-servicemonitor created
查看资源ServiceMonitor:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 [root@k8s-master01 redis-monitor]# kubectl get servicemonitors.monitoring.coreos.com -n monitoring NAME AGE alertmanager-main 304d blackbox-exporter 304d coredns 304d grafana 304d kube-apiserver 304d kube-controller-manager 304d kube-scheduler 304d kube-state-metrics 304d kubelet 304d mysql-exporter-servicemonitor 2d3h node-exporter 304d prometheus-adapter 304d prometheus-k8s 304d prometheus-operator 304d redis-exporter-servicemonitor 95s #已经成功创建资源
4.验证 Prometheus 是否发现目标
5.Grafana 导入 监控模板 可以从https://grafana.com/grafana/dashboards/寻找合适的模板,我用的模板id是763
2.2.3通过ScrapeConfig监控 在演示ScrapeConfig监控之前,我把2.2.2中部署的资源都删除,实际的工作中选择一种方式对redis进行监控即可
,监控目标redis还是继续使用2.2.1中部署的。
Redis版本:7.2.5,Redis 6.0及以上版本支持ACL用户名和密码
Redis-Exporter版本:v1.86.0,在 redis_exporter:v1.86.0 的一个 exporter 监控多个 Redis模式下,直接把密码写进 ScrapeConfig.targets 的 URI 里是不正确的,至少不能作为有效认证方式。
1 2 3 4 5 6 staticConfigs: # 静态目标配置(也可使用其他 SD 如 kubernetesSDConfigs) - targets: # 场景 1:如果redis没有密码可以这样写 # - redis://redis-service.default.svc.cluster.local:6379 # 场景 2:有密码的外部/生产 Redis (保留冒号,前面为空代表默认用户),这种写法是错误的 - redis://:redis@redis-service.default.svc.cluster.local:6379
redis_exporter 的 --redis.password 命令行参数是全局的,只能配一个密码,所以如果用它,那么监控的多个redis密码就要保持相同,多个不同的密码就做不到。针对不同密码的多实例,官方专门提供了 --redis.password-file 参数(一个 JSON 文件,按 redis 地址映射密码),它在使用 /scrape 多目标端点时对每个不同地址生效。所以一个 exporter 完全可以监控两个不同密码的 redis 。
下面演示通过一个redis exporter 对多个redis实例进行监控,并且不同redis实例之间的密码是不同的。
Redis A实例的地址是redis-service.default.svc.cluster.local:6379(集群内通过Service连接的地址,redis-service是Service的名称,default是所在的命名空间,.svc.cluster.local固定写法,6379是Service暴露的端口,密码是redis)
Redis B实例的地址是redis-service.redis-prod.svc.cluster.local:6379(集群内通过Service连接的地址,redis-service是Service的名称,redis-prod是所在的命名空间,.svc.cluster.local固定写法,6379是Service暴露的端口,密码是asdqwe123)
也就是说在default和redis-prod命名空间下都有redis服务,都需要进行监控。
1.先创建密码文件 以Secret保存redis的地址和密码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 [root@k8s-master01 redis-pord]# cat redis-exporter-passwords.yaml apiVersion: v1 kind: Secret metadata: name: redis-exporter-passwords namespace: monitoring type: Opaque stringData: # 协议: redis:// , redis-service.default.svc.cluster.local:6379是redis的实际地址,redis是密码,如果有用户名按照 "redis://default@redis-service.default.svc.cluster.local:6379" : "redis" 格式写,default是redis的用户,用@做分隔符 redis-passwords.json: | { "redis://redis-service.default.svc.cluster.local:6379": "redis", "redis://redis-service.redis-prod.svc.cluster.local:6379": "asdqwe123" }
创建资源:
1 [root@k8s-master01 redis-pord]# kubectl create -f redis-exporter-passwords.yaml
2.部署redis_exporter 部署一个 exporter,关键是挂载密码文件并传入 --redis.addr= 和 --redis.password-file。
以deployment的方式部署redis_exporter:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 # 注意:redis-exporter部署在monitoring命名空间 [root@k8s-master01 redis-pord]# vim redis-exporter-deployment.yaml # 下面是定义redis exporter的deployment资源配置 apiVersion: apps/v1 kind: Deployment metadata: name: redis-exporter namespace: monitoring labels: app: redis-exporter spec: replicas: 1 selector: matchLabels: app: redis-exporter template: metadata: labels: app: redis-exporter spec: containers: - name: redis-exporter # 镜像是从官方同步的,dockerhub官方仓库oliver006/redis_exporter image: registry.cn-beijing.aliyuncs.com/k8s-liujunwei/redis_exporter:v1.86.0 args: # --redis.password-file 只在 --redis.password 为空时才生效(默认就是空),不指定也行 - --redis.addr= - --redis.password-file=/etc/redis-exporter/redis-passwords.json - --web.listen-address=:9121 ports: - name: metrics containerPort: 9121 volumeMounts: #定义卷挂在 - name: passwords # 引用volumes中定义过的卷的名字 mountPath: /etc/redis-exporter #容器中挂载的路径 readOnly: true #设置只读 volumes: #声明存储卷 - name: passwords #定义卷得名字是passwords,volumeMounts挂载要引用这个名字 secret: # 定义这个存储卷的存储介质类型是secret secretName: redis-exporter-passwords #指定secret的名字,要提取哪一个 Secret 的数据,引用创建的secret
创建资源:
1 [root@k8s-master01 redis-pord]# kubectl create -f redis-exporter-deployment.yaml
3.创建Service暴露redis_exporter 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 # 创建Service,用来在集群中暴露redis_exporter的deployment服务 [root@k8s-master01 redis-pord]# vim redis-exporter-service.yaml # 下面是定义redis exporter的service资源配置 apiVersion: v1 kind: Service metadata: name: redis-exporter #Service的名字 namespace: monitoring #Service所在的命名空间 labels: app: redis-exporter #Service的标签 spec: selector: #通过pod的标签关联pod app: redis-exporter #这里的标签要和上述步骤2中deployment里定义的pod标签保持一致 ports: - name: metrics port: 9121 targetPort: metrics
创建资源:
1 [root@k8s-master01 redis-pord]# kubectl create -f redis-exporter-service.yaml
3.创建ScrapeConfig 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 # 创建ScrapeConfig资源,配置如下 [root@k8s-master01 redis-monitor]# cat redis-scrapeconfig.yaml apiVersion: monitoring.coreos.com/v1alpha1 kind: ScrapeConfig #定义资源的类型是ScrapeConfig metadata: # 资源的元数据 name: redis-exporter-targets #定义该资源的名字是redis-exporter-targets namespace: monitoring # 资源创建后所在的命名空间是monitoring # labels: #prometheus: k8s # 注意:这里的 label 必须匹配你 Prometheus 对象中的 scrapeConfigSelector # 例如 kube-prometheus-stack 默认可能不需要特殊 label,或需要 release: prometheus # 这里我把标签注释了,因为 Prometheus 对象中的 scrapeConfigSelector是{},表示匹配所有 spec: #描述该资源的具体配置 jobName: redis-exporter-targets # 指标中的 job 标签值 metricsPath: /scrape # 【关键】必须是 /scrape,而不是默认的 /metrics scrapeInterval: 30s # 【重要】抓取间隔,推荐 15s~60s scheme: HTTP # 协议类型 staticConfigs: - targets: # --- 实例 1: Default 命名空间的 Redis ,这里的地址要和步骤1中创建secret中的redis-passwords.json里面定义的地址完全一致,如果secret中指定了用户名,这里也需要带着用户名,不要带密码--- - redis://redis-service.default.svc.cluster.local:6379 labels: env: test redis_namespace: default redis_name: redis-default # --- 实例 2: Prod 命名空间的 Redis --- - targets: - redis://redis-service.redis-prod.svc.cluster.local:6379 labels: env: prod redis_namespace: redis-prod redis_name: redis-prod relabelings: # 动作 1: 将 targets 定义的 Redis 地址,赋值给 HTTP 请求参数 ?target= - sourceLabels: [__address__] targetLabel: __param_target # 动作 2: 将 Redis 地址设为指标的 instance 标签,确保监控面板展示的是真实的 Redis 实例名 - sourceLabels: [__param_target] targetLabel: instance # 动作 3: 移花接木,将 Prometheus 发起网络请求的真实目的地,重定向给 Exporter 的服务地址 - targetLabel: __address__ replacement: redis-exporter.monitoring.svc.cluster.local:9121 #这里的地址是redis exporter的地址
步骤
操作
底层发生了什么?
动作 1
[__address__] -> __param_target
Prometheus 刚读取 staticConfigs 时,内部标签 __address__ 的值是 redis://...。这个动作将它复制给了 __param_target。在 Prometheus 的机制中,所有 __param_<name> 都会被自动转换为 HTTP GET 请求的 Query 参数。因此,请求变为了:GET /scrape?target=redis://...
动作 2
[__param_target] -> instance
如果不加这一步,Prometheus 会默认把最终的 __address__ 作为数据的 instance 标签。这会导致 Grafana 中所有 Redis 指标的来源都显示为 exporter 的地址,你将无法区分数据来自哪个 Redis。通过这步,强制把 instance 设置为真正的 Redis URI。
动作 3
替换 __address__
Prometheus 最终发起的 TCP 连接是基于 __address__ 标签的。通过 replacement,我们将请求强行扭转,发送给 redis-exporter.monitoring.svc.cluster.local 的 9121 端口。
资源创建好后验证采集链路:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 # 控制台执行port-forward指令 [root@k8s-master01 redis-pord]# kubectl -n monitoring port-forward svc/redis-exporter 9121:9121 Forwarding from 127.0.0.1:9121 -> 9121 Forwarding from [::1]:9121 -> 9121 # 在开一个命令行窗口执行下面指令 curl http://127.0.0.1:9121/scrape?target=redis://redis-service.default.svc.cluster.local:6379 curl http://127.0.0.1:9121/scrape?target=redis://redis-service.redis-prod.svc.cluster.local:6379|grep redis_up # 看到 redis_up 1参数表示已经正常获取到redis监控数据 [root@k8s-master01 ~]# curl http://127.0.0.1:9121/scrape?target=redis://redis-service.redis-prod.svc.cluster.local:6379|grep redis_up % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 100 42100 0 42100 0 0 956k 0 --:--:-- --:--:-- --:--:-- 1027k # 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 96433
4.检查web端是否获取到监控数据 通过Prometheus可以看到有两个redis实例的监控
5.Grafana 导入 监控模板 可以从https://grafana.com/grafana/dashboards/寻找合适的模板,依然使用id是763的模板,可以看到Grafana的监控模板中也是有两个redis的监控数据。
3黑盒监控 黑盒监控 (Blackbox Monitoring)
定义 :黑盒监控指的是通过模拟用户请求来监控外部服务或系统的可用性和性能,而不是直接监控这些服务的内部指标。这种监控方式通常用于检查网络服务的健康状态,如HTTP、HTTPS、DNS、TCP等协议的响应时间、状态码等。
特点 :
从用户的视角来评估服务的可用性和性能。
不需要对被监控的系统有深入的内部了解。
主要关注外部表现,如响应时间、状态码、是否可达等。
通常使用blackbox_exporter来实现。
应用 :
网站监控:检查网站是否可达,响应时间是否在可接受范围内。
DNS监控:验证DNS解析是否正常工作。
API监控:监控API的响应时间、状态码。
网络服务监控:检查TCP连接的建立时间、丢包率等。
白盒监控 (Whitebox Monitoring)
定义 :白盒监控指的是直接从系统内部获取指标数据,监控系统的内部状态和性能。这种监控方式需要对被监控的系统有深入的了解,能够获取到系统的内部运行情况。
特点 :
直接监控系统的内部指标,如CPU使用率、内存使用、磁盘I/O、网络流量等。
需要对系统的内部结构和运行机制有详细的了解。
可以提供更详细的性能数据和问题诊断信息。
通常通过Prometheus的exporter来暴露系统的内部指标。
应用 :
系统资源监控:监控CPU、内存、磁盘、网络等资源的使用情况。
应用性能监控:监控应用程序的内部指标,如请求处理时间、错误率等。
数据库监控:监控数据库的性能指标,如查询时间、连接数等。
容器和Kubernetes监控:监控容器和Kubernetes集群的内部状态。
总结
黑盒监控 关注的是服务的外部表现,适用于检查服务的可用性和用户体验,但无法提供关于系统内部状态的详细信息。
白盒监控 则深入到系统内部,提供更详细的性能数据和问题诊断信息,但需要对系统有深入的了解。
新版Prometheus Stack已经默认安装了BlackboxExporter(黑盒监控),可以通过以下命令查看:
1 kubectl get po -n monitoring
同时也会创建一个Service,可以通过该Service访问BlackboxExporter并传递一些参数:
1 kubectl get service -n monitoring
可以通过blackbox-exporter的service的ip地址对网站进行探测:
比如检测下www.baidu.com (使用任何一个公网域名或者公司内的域名探测即可)网站的状态,可以通过如下命令进行检查:
1 2 3 4 5 6 7 8 9 10 11 [root@k8s-master01 kube-scheduler]# curl -s "http://10.96.69.178:19115/probe?target=www.baidu.com&module=http_2xx" | tail -5 # TYPE probe_ip_protocol gauge probe_ip_protocol 4 # HELP probe_success Displays whether or not the probe was a success # TYPE probe_success gauge probe_success 1 # probe是blackbox-exporter服务的接口地址。 # target是检测的目标。 # module是使用哪个模块进行探测。 # https://github.com/prometheus/blackbox_exporter进行安装。
3.1用Probe监控站点 参考文档:https://github.com/prometheus/blackbox_exporter
CRD 文档: https://github.com/prometheus-operator/kube-prometheus/blob/main/docs/blackboxexporter.md
Probe 类型的监控通常都会和 Blackbox 配合使用,用于监控域名的可用性。
3.1.1.验证已有组件(必须先做) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 # 确认 namespace kubectl get ns monitoring # 确认 blackbox-exporter 已运行,期望:blackbox-exporter-xxx 3/3 Running [root@k8s-master01 ~]# kubectl get po -n monitoring | grep blackbox blackbox-exporter-86745676c9-gh88k 3/3 Running 45 (6d3h ago) 124d # 确认 Service,期望有 blackbox-exporter 服务 [root@k8s-master01 ~]# kubectl get svc -n monitoring | grep blackbox blackbox-exporter ClusterIP 10.96.84.30 <none> 9115/TCP,19115/TCP 308d # 确认 Probe CRD 存在(Prometheus Operator 自带) [root@k8s-master01 ~]# kubectl get crd | grep probes.monitoring.coreos.com probes.monitoring.coreos.com 2025-09-21T12:12:08Z # 确认 Prometheus 能发现 Probe(kube-prometheus 默认 probeSelector: {},即匹配所有) [root@k8s-master01 ~]# kubectl get prometheus -n monitoring -o yaml | grep -A5 probeSelector probeSelector: {} replicas: 1 resources: requests: memory: 400Mi ruleNamespaceSelector: {}
如果 blackbox-exporter 不存在,才需要重新从 kube-prometheus 生成并 apply(你已有,跳过):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 # 仅在没有时执行 # 进入项目的release-0.14/kube-prometheus-release-0.14/manifests路径 [root@k8s-master01 manifests]# ll blackboxExporter-* -rw-r--r-- 1 root root 461 Jul 23 2025 blackboxExporter-clusterRoleBinding.yaml -rw-r--r-- 1 root root 287 Jul 23 2025 blackboxExporter-clusterRole.yaml -rw-r--r-- 1 root root 1392 Jul 23 2025 blackboxExporter-configuration.yaml -rw-r--r-- 1 root root 3645 Jul 23 2025 blackboxExporter-deployment.yaml -rw-r--r-- 1 root root 722 Jul 23 2025 blackboxExporter-networkPolicy.yaml -rw-r--r-- 1 root root 315 Jul 23 2025 blackboxExporter-serviceAccount.yaml -rw-r--r-- 1 root root 680 Jul 23 2025 blackboxExporter-serviceMonitor.yaml -rw-r--r-- 1 root root 540 Jul 23 2025 blackboxExporter-service.yaml # 使用 jsonnet 生成或直接从官方 manifests 复制 blackboxExporter 相关 yaml 后 kubectl apply -f blackboxExporter-*.yaml -n monitoring
3.1.2检查 / 确认 blackbox-exporter 模块配置 默认已包含常用模块(http_2xx、http_post_2xx、tcp_connect 等)。 站点 HTTP/HTTPS 监控直接用 http_2xx 即可 ,无需修改。如果以后需要 ICMP(ping),需要额外加模块并重启(可选,当前不需要)。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 [root@k8s-master01 manifests]# kubectl get cm blackbox-exporter-configuration -n monitoring -o yaml apiVersion: v1 data: config.yml: |- "modules": "http_2xx": "http": "preferred_ip_protocol": "ip4" "prober": "http" "http_post_2xx": "http": "method": "POST" "preferred_ip_protocol": "ip4" "prober": "http" "irc_banner": "prober": "tcp" "tcp": "preferred_ip_protocol": "ip4" "query_response": - "send": "NICK prober" - "send": "USER prober prober prober :prober" - "expect": "PING :([^ ]+)" "send": "PONG ${1}" - "expect": "^:[^ ]+ 001" "pop3s_banner": "prober": "tcp" "tcp": "preferred_ip_protocol": "ip4" "query_response": - "expect": "^+OK" "tls": true "tls_config": "insecure_skip_verify": false "ssh_banner": "prober": "tcp" "tcp": "preferred_ip_protocol": "ip4" "query_response": - "expect": "^SSH-2.0-" "tcp_connect": "prober": "tcp" "tcp": "preferred_ip_protocol": "ip4" kind: ConfigMap metadata: creationTimestamp: "2025-09-21T12:35:52Z" labels: app.kubernetes.io/component: exporter app.kubernetes.io/name: blackbox-exporter app.kubernetes.io/part-of: kube-prometheus app.kubernetes.io/version: 0.25.0 name: blackbox-exporter-configuration namespace: monitoring resourceVersion: "16387650" uid: db5fb4c5-f1dc-4f35-b6e4-a4ec10ce0aa6
3.1.3创建 Probe 资源(核心步骤) 创建文件 web-probe.yaml(把目标改成要监控的站点域名):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 [root@k8s-master01 manifests]# vim web-probe.yaml apiVersion: monitoring.coreos.com/v1 kind: Probe metadata: name: web-probe namespace: monitoring labels: app: web-probe spec: # 可选,任务名称(Prometheus 中会显示为 job) jobName: web-probe # 探测间隔 interval: 30s # 超时 scrapeTimeout: 10s # 使用的模块(这里使用的模块必须要在3.1.2中 blackbox-exporter-configuration 存在) module: http_2xx # prober 地址(kube-prometheus 默认内部端口是 19115,不是 9115) prober: #url定义的地址是集群中blackbox-exporter的Service暴露的地址 url: blackbox-exporter.monitoring.svc.cluster.local:19115 # 可选 path(默认 /probe) path: /probe scheme: http targets: staticConfig: static: - https://www.xinchuanlake.com # 改成要监控的站点 - https://smart.jiugen.net/ # 可多个 # - http://internal-service.default.svc:8080 # 可选:给每个 target 加标签 labels: #要想为不同站点定义不懂的标签只能写多个probe资源 env: prod # targets: staticConfig: static: - https://www.xinchuanlake.com labels: site: xinchuanlake env: prod team: frontend business: lake staticConfig: static: - https://smart.jiugen.net/ labels: site: jiugen env: prod team: backend business: smart
创建资源:
1 2 [root@k8s-master01 Probe]# kubectl create -f web-probe.yaml probe.monitoring.coreos.com/web-probe created
验证:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 [root@k8s-master01 Probe]# kubectl get probes.monitoring.coreos.com -n monitoring NAME AGE web-probe 68s [root@k8s-master01 Probe]# kubectl describe probes.monitoring.coreos.com -n monitoring web-probe Name: web-probe Namespace: monitoring Labels: app=web-probe Annotations: <none> API Version: monitoring.coreos.com/v1 Kind: Probe Metadata: Creation Timestamp: 2026-07-26T13:04:33Z Generation: 1 Resource Version: 77867679 UID: 8c3fd73f-be91-4d44-b282-99a3942e33c9 Spec: Interval: 30s Job Name: web-probe Module: http_2xx Prober: Path: /probe Scheme: http URL: blackbox-exporter.monitoring.svc.cluster.local:19115 Scrape Timeout: 10s Targets: Static Config: Labels: Env: prod Static: https://www.xinchuanlake.com https://smart.jiugen.net Events: <none>
3.1.4验证 Prometheus 已成功抓取 直接验证 blackbox-exporter 能否探测到目标(最底层)
1 2 # 端口转发 blackbox-exporter(注意用内部端口 19115) kubectl -n monitoring port-forward svc/blackbox-exporter 19115:19115
再开一个新的终端:
1 2 3 4 5 # 探测你的站点(把 URL 换成真实的) curl -s "http://127.0.0.1:19115/probe?target=https://www.xinchuanlake.com&module=http_2xx" # 或者加 debug 看详细过程 curl -s "http://127.0.0.1:19115/probe?target=https://www.xinchuanlake.com&module=http_2xx&debug=true"
1 2 3 成功标志:输出里有 probe_success 1 有 probe_duration_seconds、probe_http_status_code 等指标 如果这里就是 probe_success 0,说明是目标站点本身的问题(网络、证书、防火墙等),跟 Prometheus 无关。
3.1.5检查web端
3.1.6Grafana导入监控模板 推荐 Dashboard ID(任选其一):
ID
名称
说明
7587
Blackbox Exporter
经典、使用最广
13659
Blackbox Exporter Overview
较新
14928
Prometheus Blackbox Exporter
另一个常用版本
19342
Blackbox Exporter
较新版本
3.2老式教程写法 Prometheus支持的 额外抓取配置(additionalScrapeConfigs),通过配置额外抓取配置来实现对某些网站的监控。
当 Prometheus Operator 默认生成的 scrape_configs 无法覆盖特殊场景(如黑盒监控、自定义导出器)时,additionalScrapeConfigs 提供了一种灵活扩展机制。
Prometheus Operator 会自动检测 additionalScrapeConfigs,将其内容合并到主 Prometheus 的配置中(scrape_configs 部分)。
通过prometheus的静态配置对某个网站进行监控—黑盒监控
第一步:创建一个空文件,然后通过该文件创建一个secret,那么这个secret即可作为prometheus的静态配置:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 # 创建一个空文件prometheus-additional.yaml,用它来创建secret [root@k8s-master01 blackbox-exporter]# touch prometheus-additional.yaml # 创建secret [root@k8s-master01 blackbox-exporter]# kubectl create secret generic prometheus-additional-config --from-file=prometheus-additional.yaml -n monitoring secret/prometheus-additional-config created # 查看创建的secret [root@k8s-master01 blackbox-exporter]# kubectl get secrets -n monitoring prometheus-additional-config NAME TYPE DATA AGE prometheus-additional-config Opaque 1 47s # 修改prometheus的配置,这里的prometheus是一个CRD(自定义资源定义),由Prometheus Operator管理,修改CRD会自动触发Operator重新配置Prometheus [root@k8s-master01 blackbox-exporter]# kubectl edit prometheus -n monitoring k8s # 在 Prometheus 的配置中,additionalScrapeConfigs 是 Prometheus Operator 提供的一个参数,用于扩展和动态管理 scrape_configs(抓取配置)。它的作用是指定一组额外的抓取配置,这些配置通过一个 Kubernetes Secret 提供,并与 Prometheus 的默认 scrape_configs 合并 serviceMonitorNamespaceSelector: {} serviceMonitorSelector: {} additionalScrapeConfigs: #定义额外抓取配置 name: prometheus-additional-config #对应上述创建的secret的名称 key: prometheus-additional.yaml #key对应是的上述创建的secret时指定的文件名 optional: true #可选参数,true表示即使Secret不存在也不会报错,提供了配置的容错性便于后续增量更新 version: 2.54.1 status: availableReplicas: 1 conditions:
主要是在prometheus资源中增加下面配置:
1 2 3 4 additionalScrapeConfigs: #定义额外抓取配置 name: prometheus-additional-config #对应上述创建的secret的名称 key: prometheus-additional.yaml #key对应是的上述创建的secret时指定的文件名 optional: true #可选参数,true表示即使Secret不存在也不会报错,提供了配置的容错性便于后续增量更新
添加上述配置后保存退出,无需重启 Prometheus 的 Pod 即可生效。之后在prometheus-additional.yaml文件内编辑一些静态配置,此处用黑盒监控的配置进行演示:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 [root@k8s-master01 blackbox-exporter]# vim prometheus-additional.yaml # 添加下面配置 - job_name: 'blackbox' # 任务名称 metrics_path: /probe # 指标获取路径 params: module: [http_2xx] # 使用的探测模块 static_configs: - targets: #targets模块下配置的是要监控的网站域名 - http://gaoxin.kubeasy.com # 监控目标 - https://www.baidu.com relabel_configs: # 标签重写规则,固定写法 - source_labels: [__address__] target_label: __param_target - source_labels: [__param_target] target_label: instance - target_label: __address__ replacement: blackbox-exporter:19115 #Blackbox Exporter 的地址
可以看到此处的内容,基本和命令行配置的内容一致,只需要添加对应的 job 即可。之后通过该文件热更新该 Secret:
1 2 3 # 热更新secret命令 [root@k8s-master01 blackbox-exporter]# kubectl create secret generic prometheus-additional-config --from-file=prometheus-additional.yaml --dry-run=client -oyaml|kubectl replace -f - -n monitoring secret/prometheus-additional-config replaced
检查secret是否被更新:
1 2 3 4 5 6 7 8 9 10 11 12 [root@k8s-master01 blackbox-exporter]# kubectl get secrets -n monitoring prometheus-additional-config -oyaml apiVersion: v1 data: prometheus-additional.yaml: I+a3u+WKoOS4i+mdoumFjee9rg0KLSBqb2JfbmFtZTogJ2JsYWNrYm94JyAgICAgICAgICAgICAgICAjIOS7u+WKoeWQjeensA0KICBtZXRyaWNzX3BhdGg6IC9wcm9iZSAgICAgICAgICAgICAgICMg5oyH5qCH6I635Y+W6Lev5b6EDQogIHBhcmFtczoNCiAgICBtb2R1bGU6IFtodHRwXzJ4eF0gICAgICAgICAgICAgICMg5L2/55So55qE5o6i5rWL5qih5Z2XDQogIHN0YXRpY19jb25maWdzOg0KICAgIC0gdGFyZ2V0czogI3RhcmdldHPmqKHlnZfkuIvphY3nva7nmoTmmK/opoHnm5HmjqfnmoTnvZHnq5nln5/lkI0NCiAgICAgICAgLSBodHRwOi8vZ2FveGluLmt1YmVhc3kuY29tICAgIyDnm5Hmjqfnm67moIcNCiAgICAgICAgLSBodHRwczovL3d3dy5iYWlkdS5jb20NCiAgcmVsYWJlbF9jb25maWdzOiAgICAgICAgICAgICAgICAgICMg5qCH562+6YeN5YaZ6KeE5YiZ77yM5Zu65a6a5YaZ5rOVDQogICAgLSBzb3VyY2VfbGFiZWxzOiBbX19hZGRyZXNzX19dDQogICAgICB0YXJnZXRfbGFiZWw6IF9fcGFyYW1fdGFyZ2V0DQogICAgLSBzb3VyY2VfbGFiZWxzOiBbX19wYXJhbV90YXJnZXRdDQogICAgICB0YXJnZXRfbGFiZWw6IGluc3RhbmNlDQogICAgLSB0YXJnZXRfbGFiZWw6IF9fYWRkcmVzc19fDQogICAgICByZXBsYWNlbWVudDogYmxhY2tib3gtZXhwb3J0ZXI6MTkxMTU= kind: Secret metadata: creationTimestamp: "2024-11-22T14:40:30Z" name: prometheus-additional-config namespace: monitoring resourceVersion: "18827266" uid: efc2196d-fbc4-4425-8c05-d94963289e21 type: Opaque
可以看到上述secret已经有内容了,可以使用base64解码查看内容是否是我们配置的:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 [root@k8s-master01 blackbox-exporter]# echo """I+a3u+WKoOS4i+mdoumFjee9rg0KLSBqb2JfbmFtZTogJ2JsYWNrYm94JyAgICAgICAgICAgICAgICAjIOS7u+WKoeWQjeensA0KICBtZXRyaWNzX3BhdGg6IC9wcm9iZSAgICAgICAgICAgICAgICMg5oyH5qCH6I635Y+W6Lev5b6EDQogIHBhcmFtczoNCiAgICBtb2R1bGU6IFtodHRwXzJ4eF0gICAgICAgICAgICAgICMg5L2/55So55qE5o6i5rWL5qih5Z2XDQogIHN0YXRpY19jb25maWdzOg0KICAgIC0gdGFyZ2V0czogI3RhcmdldHPmqKHlnZfkuIvphY3nva7nmoTmmK/opoHnm5HmjqfnmoTnvZHnq5nln5/lkI0NCiAgICAgICAgLSBodHRwOi8vZ2FveGluLmt1YmVhc3kuY29tICAgIyDnm5Hmjqfnm67moIcNCiAgICAgICAgLSBodHRwczovL3d3dy5iYWlkdS5jb20NCiAgcmVsYWJlbF9jb25maWdzOiAgICAgICAgICAgICAgICAgICMg5qCH562+6YeN5YaZ6KeE5YiZ77yM5Zu65a6a5YaZ5rOVDQogICAgLSBzb3VyY2VfbGFiZWxzOiBbX19hZGRyZXNzX19dDQogICAgICB0YXJnZXRfbGFiZWw6IF9fcGFyYW1fdGFyZ2V0DQogICAgLSBzb3VyY2VfbGFiZWxzOiBbX19wYXJhbV90YXJnZXRdDQogICAgICB0YXJnZXRfbGFiZWw6IGluc3RhbmNlDQogICAgLSB0YXJnZXRfbGFiZWw6IF9fYWRkcmVzc19fDQogICAgICByZXBsYWNlbWVudDogYmxhY2tib3gtZXhwb3J0ZXI6MTkxMTU="""|base64 -d #可以看到解密出来的配置是我们配置的内容 # 添加下面配置 - job_name: 'blackbox' # 任务名称 metrics_path: /probe # 指标获取路径 params: module: [http_2xx] # 使用的探测模块 static_configs: - targets: #targets模块下配置的是要监控的网站域名 - http://gaoxin.kubeasy.com # 监控目标 - https://www.baidu.com relabel_configs: # 标签重写规则,固定写法 - source_labels: [__address__] target_label: __param_target - source_labels: [__param_target] target_label: instance - target_label: __address__ replacement: blackbox-exporter:19115
检查Prometheus的Web 界面中查看是否存在该配置:
通过下图可以看到Prometheus已经成功看到该配置,状态也是up,接下来就可以配置监控模板了。
在grafana控制台中配置监控模板(模板连接地址https://grafana.com/grafana/dashboards/13659-blackbox-exporter-http-prober/):
导入网站监控模板:
最后可以看到监控界面即可:
如果需要新增加站点监控,直接编辑prometheus-additional.yaml文件,然后再次执行热更新secret的命令即可:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 # 例如,要新增加www.ibstd.cn站点的监控,在targets模块下增加监控目标即可 [root@k8s-master01 blackbox-exporter]# vim prometheus-additional.yaml # 添加下面配置 - job_name: 'blackbox' # 任务名称 metrics_path: /probe # 指标获取路径 params: module: [http_2xx] # 使用的探测模块 static_configs: - targets: #targets模块下配置的是要监控的网站域名 - http://gaoxin.kubeasy.com # 监控目标 - https://www.baidu.com - https://www.ibstd.cn #这是新增加的监控目标网站 relabel_configs: # 标签重写规则,固定写法 - source_labels: [__address__] target_label: __param_target - source_labels: [__param_target] target_label: instance - target_label: __address__ replacement: blackbox-exporter:19115 #Blackbox Exporter 的地址
修改prometheus-additional.yaml文件后保存退出,执行热更新的命令即可:
1 2 # 通过下面的命令热更新secret kubectl create secret generic prometheus-additional-config --from-file=prometheus-additional.yaml --dry-run=client -oyaml|kubectl replace -f - -n monitoring
4.通过Podmonitor监控pod 如果业务容器有Service推荐使用ServiceMonitor来监控服务,如果采用的是注册中心的形式,业务容器可能没有创建单独的Service,那么就可以用Podmonitor来监控。
1 2 # 案例中使用的是官方镜像:quay.io/brancz/prometheus-example-app:v0.3.0 # 同步到国内的镜像地址:registry.cn-beijing.aliyuncs.com/k8s-liujunwei/prometheus-example-app:v0.3.0
4.1部署测试示例 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 cat > app.yaml <<EOF apiVersion: apps/v1 kind: Deployment metadata: name: myapp namespace: prod spec: replicas: 2 selector: matchLabels: app: myapp template: metadata: labels: app: myapp spec: containers: - name: app: myapp image: registry.cn-beijing.aliyuncs.com/k8s-liujunwei/prometheus-example-app:v0.3.0 ports: - name: metrics containerPort: 8080 EOF
应用创建在prod命名空间:
1 2 3 4 5 [root@k8s-master01 podmonitor]# kubectl create ns prod namespace/prod created [root@k8s-master01 podmonitor]# kubectl create -f myapp.yaml deployment.apps/myapp created
查看pod创建情况:
1 2 3 4 [root@k8s-master01 podmonitor]# kubectl get po -n prod NAME READY STATUS RESTARTS AGE myapp-5d4cbb5d76-ls6c4 1/1 Running 0 14s myapp-5d4cbb5d76-tcd72 1/1 Running 0 14s
查看metrics数据:
1 2 3 4 5 6 7 8 9 10 [root@k8s-master01 podmonitor]# kubectl get po -n prod -owide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES myapp-5d4cbb5d76-ls6c4 1/1 Running 0 68s 172.16.58.197 k8s-node02 <none> <none> myapp-5d4cbb5d76-tcd72 1/1 Running 0 68s 172.16.135.179 k8s-node03 <none> <none> # 可以正常获取到数据 [root@k8s-master01 podmonitor]# curl 172.16.135.179:8080/metrics # HELP version Version information about this binary # TYPE version gauge version{version="v0.3.0"} 1
4.2创建Podmonitor 接下来创建Podmonitor服务来监控该服务
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 [root@k8s-master01 podmonitor]# vim myapp-podmonitor.yaml # PodMonitor资源内容如下 apiVersion: monitoring.coreos.com/v1 #固定写 monitoring.coreos.com/v1(当前主流版本) kind: PodMonitor #声明这是 PodMonitor资源(直接监控 Pod,不依赖 Service) metadata: #定义资源元数据 # 定义PodMonitor 资源的名字。Prometheus 会用它生成job名称,建议命名规范:{业务}-{组件}-monitor name: myapp-monitor namespace: monitoring #这个 PodMonitor 本身 存放在哪个命名空间 labels: #给这个 PodMonitor 打上标签。 release: k8s spec: #定义资源的具体规格 namespaceSelector: #指定要去哪些命名空间里找 Pod matchNames: #匹配命名空间名字 - prod # 指定要监控的pod所在的命名空间 selector: #标签选择器 matchLabels: #匹配标签 app: myapp #指定pod的标签,从default空间中找标签是app: myapp的pod进行监控 podMetricsEndpoints: # - port: metrics #端口的名称(不是数字),要和对应 Pod 容器里 ports[].name 的值保持一致 path: /metrics #指标的路径 interval: 30s #抓取间隔
创建资源:
1 2 [root@k8s-master01 podmonitor]# kubectl create -f myapp-podmonitor.yaml podmonitor.monitoring.coreos.com/myapp-monitor created
4.3web端验证监控 看到如图显示的信息表示可以正常获取到pod的监控信息
注意:prometheus-k8s-0的RBAC权限问题 在原生的 kube-prometheus (Kube-Prometheus项目地址:https://github.com/prometheus-operator/kube-prometheus/)项目中,基于最小权限原则,默认只为 prometheus-k8s 这个 ServiceAccount 创建了针对 default、kube-system 和 monitoring 命名空间的 RoleBinding。它并没有读取 其他 命名空间资源的权限。 具体的配置是在release-0.14/kube-prometheus-release-0.14/manifests目录中prometheus-roleSpecificNamespaces.yaml和prometheus-roleBindingSpecificNamespaces.yaml中定义的,因此,当需要Prometheus 监控其他命名空间中的pod时(例如prod空间),Kubernetes API 会拒绝请求,并在 Prometheus的pod 日志中打印类似以下的错误:
1 Failed to watch *v1.Pod: failed to list *v1.Pod: pods is forbidden: User "system:serviceaccount:monitoring:prometheus-k8s" cannot list resource "pods" in API group "" in the namespace "prod""
解决办法:直接把Prometheus 中定义的role和RoleBinding在prod命名空间中创建即可。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 cat > prometheus-prod-rbac.yaml << EOF # 该配置定义role apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: labels: app.kubernetes.io/component: prometheus app.kubernetes.io/instance: k8s app.kubernetes.io/name: prometheus app.kubernetes.io/part-of: kube-prometheus app.kubernetes.io/version: 2.54.1 name: prometheus-k8s namespace: prod rules: - apiGroups: - "" resources: - services - endpoints - pods verbs: - get - list - watch - apiGroups: - extensions resources: - ingresses verbs: - get - list - watch - apiGroups: - networking.k8s.io resources: - ingresses verbs: - get - list - watch --- # 该配置定义RoleBinding apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: labels: app.kubernetes.io/component: prometheus app.kubernetes.io/instance: k8s app.kubernetes.io/name: prometheus app.kubernetes.io/part-of: kube-prometheus app.kubernetes.io/version: 2.54.1 name: prometheus-k8s namespace: prod roleRef: apiGroup: rbac.authorization.k8s.io kind: Role name: prometheus-k8s subjects: - kind: ServiceAccount name: prometheus-k8s namespace: monitoring EOF
创建资源:
1 kubectl create -f prometheus-prod-rbac.yaml
以后希望 Prometheus 监控哪个命名空间,就在那个命名空间创建对应的 Role 和 RoleBinding即可。
5.k8s核心组件监控 Prometheus 原生提供了 Kubernetes 核心组件的监控,但是 Scheduler 和 Controller Manager 可能由于配置的问题导致监控失败,如下图所示:
Service Monitor找不到监控主机排查步骤:
①确认Service Monitor是否成功创建
②确认Service Monitor关联的service标签是否配置正确
③确认Prometheus是否生成了相关配置
④确认Service Monitor匹配的Service存在
⑤确认通过Service能够访问程序的Metrics接口
⑥确认Service服务配置的端口名字(Service.spec.ports.name)和Service Monitor中(ServiceMonitor.spec.endpoints.port)配置的一致
5.1、排查案例KubeControllerManager:
以上图KubeControllerManager 和KubeScheduler 为案例讲解排查过程:
以下方法不仅仅是针对KubeControllerManager或者KubeScheduler的排查思路,所有用到Service Monitor资源的均可以按照该流程排查问题。
第一步:确认Service Monitor是否成功创建
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 # KubeControllerManager [root@k8s-master01 mysql-exporter]# kubectl get servicemonitors.monitoring.coreos.com -n monitoring NAME AGE alertmanager-main 7d22h blackbox-exporter 7d22h coredns 7d22h etcd-servicemonitor 4d17h grafana 7d22h kube-apiserver 7d22h kube-controller-manager 7d22h kube-scheduler 7d22h kube-state-metrics 7d22h kubelet 7d22h mysql-exporter 25h node-exporter 7d22h prometheus-adapter 7d22h prometheus-k8s 7d22h prometheus-operator 7d22h # kube-scheduler和 kube-controller-manager是存在的
第二步:确认Service Monitor关联的service标签是否配置正确
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 # 检查servicemonitors资源中选择的sevice资源标签 [root@k8s-master01 mysql-exporter]# kubectl get servicemonitors.monitoring.coreos.com -n monitoring kube-controller-manager -oyaml .... insecureSkipVerify: true jobLabel: app.kubernetes.io/name namespaceSelector: matchNames: - kube-system #匹配的命名空间是kube-system selector: matchLabels: app.kubernetes.io/name: kube-controller-manager #在kube-system命名空间中匹配具有app.kubernetes.io/name=kube-controller-manager标签的service # 检查检查目标命名空间中是否有标签值是app.kubernetes.io/name=kube-controller-manager的service [root@k8s-master01 mysql-exporter]# kubectl get service -n kube-system -l app.kubernetes.io/name=kube-controller-manager No resources found in kube-system namespace. #没有目标service # 可以看到并没有此标签的Service,所以导致了找不到需要监控的目标,此时可以手动创建该Service和Endpoint指向自己的Controller Manager服务: vim kube-controller-manager-svc.yaml # 创建yaml文件,添加下面配置 kind: Service apiVersion: v1 metadata: name: kube-controller-manager-svc namespace: kube-system labels: app.kubernetes.io/name: kube-controller-manager #这里定义的标签和servicemonitors保持一致 spec: type: ClusterIP ports: - name: https-metrics #这里的名字要和下方Endpoints中subsets.ports.name定义的值保持一致,这样才能找到正确匹配并转发流量 port: 10257 targetPort: 10257 # 当service没有通过 selector 匹配pod时,targetPort参数实际上不会产生作用 protocol: TCP --- kind: Endpoints apiVersion: v1 metadata: name: kube-controller-manager-svc namespace: kube-system subsets: - addresses: - ip: 192.168.0.81 #这里的ip改为自己的ControllerManager的ip,有几个ControllerManager节点就写几个ip - ip: 192.168.0.82 - ip: 192.168.0.83 ports: - name: https-metrics #这里的名字要和上方Service中spec.ports.name定义的值保持一致,这样才能找到正确匹配并转发流量 port: 10257 #指定 ControllerManager服务实际的端口号 protocol: TCP # 创建上述kube-controller-manager-svc.yaml资源(创建Service和Endpoints) [root@k8s-master01 kube-controller-manager]# kubectl create -f kube-controller-manager-svc.yaml service/kube-controller-manager created endpoints/kube-controller-manager created # 查看创建的资源 [root@k8s-master01 mysql-monitor]# kubectl get -f kube-controller-manager-svc.yaml NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE service/kube-controller-manager-svc ClusterIP 10.96.245.176 <none> 10257/TCP 10s NAME ENDPOINTS AGE endpoints/kube-controller-manager-svc 192.168.0.81:10257,192.168.0.82:10257,192.168.0.83:10257 9s # 因为请求kube-controller-manager的接口也要使用https,所以也需要配置证书(可以参考etcd的证书配置方法,一个道理) # 首先找到证书,创建一个secret,这个secret要给prometheus-k8s-0使用,所以要个prometheus-k8s-0的pod在同一个命名空间中 kubectl create secret generic kube-controller-manager-secret \ --from-file=/etc/kubernetes/pki/ca.pem \ --from-file=/etc/kubernetes/pki/admin.pem \ --from-file=/etc/kubernetes/pki/admin-key.pem -n monitoring # 将secret证书挂载至 Prometheus 容器(由于 Prometheus 是 Operator 部署的,所以只需要修改Prometheus 资源即可): [root@k8s-master01 kube-controller-manager]# kubectl edit prometheus -n monitoring k8s scrapeConfigSelector: {} scrapeInterval: 30s secrets: #在secrets下添加刚才创建的secret名字,是kube-controller-manager-ssl - etcd-ssl #这个是etcd的证书 - kube-controller-manager-secret #这个是新增包含证书的secret,也就是kube-controller-manager-secret securityContext: fsGroup: 2000 # 保存退出后,Prometheus 的 Pod (prometheus-k8s-0)会自动重启,重启完成后,查看证书是否挂载(任意一个Prometheus 的 Pod 均可): [root@k8s-master01 kube-controller-manager]# kubectl exec -ti prometheus-k8s-0 -n monitoring -- sh /prometheus $ ls -l /etc/prometheus/secrets/ etcd-ssl/ kube-controller-manager-ssl/ /prometheus $ ls -l /etc/prometheus/secrets/kube-controller-manager-ssl/ total 0 lrwxrwxrwx 1 root 2000 20 Nov 20 10:27 admin-key.pem -> ..data/admin-key.pem lrwxrwxrwx 1 root 2000 16 Nov 20 10:27 admin.pem -> ..data/admin.pem lrwxrwxrwx 1 root 2000 13 Nov 20 10:27 ca.pem -> ..data/ca.pem # 编辑kube-controller-manager的ServiceMonitor,配置tlsConfig中证书文件部分,有两个tlsConfig都需要配置 [root@k8s-master01 kube-controller-manager]# kubectl edit servicemonitors.monitoring.coreos.com -n monitoring kube-controller-manager 56 sourceLabels: 57 - __name__ 58 port: https-metrics 59 scheme: https 60 tlsConfig: #这里也需要配置,这里的路径是pod中的路径,不是宿主的路径,也就是pod名字是prometheus-k8s-0中的路径 61 caFile: /etc/prometheus/secrets/kube-controller-manager-secret/ca.pem 62 certFile: /etc/prometheus/secrets/kube-controller-manager-secret/admin.pem 63 keyFile: /etc/prometheus/secrets/kube-controller-manager-secret/admin-key.pem 64 insecureSkipVerify: true 65 - bearerTokenFile: /var/run/secrets/kubernetes.io/serviceaccount/token 66 interval: 5s 67 metricRelabelings: 68 - action: drop 69 regex: process_start_time_seconds 70 sourceLabels: 71 - __name__ 72 path: /metrics/slis 73 port: https-metrics 74 scheme: https 75 tlsConfig: #这里也需要配置,这里的路径是pod中的路径,不是宿主的路径,也就是pod名字是prometheus-k8s-0中的路径 76 caFile: /etc/prometheus/secrets/kube-controller-manager-secret/ca.pem 77 certFile: /etc/prometheus/secrets/kube-controller-manager-secret/admin.pem 78 keyFile: /etc/prometheus/secrets/kube-controller-manager-secret/admin-key.pem 79 insecureSkipVerify: true 80 jobLabel: app.kubernetes.io/name 81 namespaceSelector: 82 matchNames: 83 - kube-system 84 selector: 85 matchLabels: 86 app.kubernetes.io/name: kube-controller-manager
在prometheus控制台查看是否成功:
下面已经看不到之前的报错了(KubeControllerManagerDown)
可以看到kube-controller-manager的状态也都是up,这就表示已经处理好了。
5.2、排查案例KubeScheduler: ①确认Service Monitor是否成功创建
②确认Service Monitor关联的service标签是否配置正确
③确认Prometheus是否生成了相关配置
④确认Service Monitor匹配的Service存在
⑤确认通过Service能够访问程序的Metrics接口
⑥确认Service服务配置的端口名字(Service.spec.ports.name)和Service Monitor中(ServiceMonitor.spec.endpoints.port)配置的一致
第一步:排查是否有KubeScheduler的Service Monitor
第二步:确认Service Monitor关联的service标签是否配置正确
检查kube-system命名空间中是否存在标签是app.kubernetes.io/name=kube-scheduler的Service:
1 2 kubectl get service -n kube-system -l app.kubernetes.io/name=kube-scheduler # 通过该命令看到没有找到相应的service资源,见下图
接下来手动为scheduler创建Service和Endpoint,指向安装的kube-scheduler
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 # 手动创建Service和Endpoint资源: vim kube-scheduler-svc.yaml # 创建yaml文件,添加下面配置 kind: Service apiVersion: v1 metadata: name: kube-scheduler namespace: kube-system labels: app.kubernetes.io/name: kube-scheduler #这里定义的标签和servicemonitors保持一致 spec: ports: - name: https-metrics #如果是通过ServiceMonitor资源对其进行监控,这里的name要和ServiceMonitor.spec.endpoints.port字段保持一致 port: 10259 targetPort: 10259 protocol: TCP --- kind: Endpoints apiVersion: v1 metadata: name: kube-scheduler namespace: kube-system subsets: - addresses: - ip: 192.168.0.81#这里的ip是的kube-scheduler的节点ip,有几个kube-scheduler节点就写几个ip - ip: 192.168.0.82 - ip: 192.168.0.83 ports: - name: https-metrics port: 10259 protocol: TCP # 创建上述kube-scheduler-svc.yaml资源(创建Service和Endpoints) [root@k8s-master01 kube-scheduler]# kubectl replace -f kube-scheduler-svc.yaml service/kube-scheduler replaced endpoints/kube-scheduler replaced [root@k8s-master01 30-Prometheus]# kubectl get -f kube-scheduler-svc.yaml NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE service/kube-scheduler ClusterIP 10.96.115.195 <none> 10259/TCP 17s NAME ENDPOINTS AGE endpoints/kube-scheduler 192.168.0.81:10259,192.168.0.82:10259,192.168.0.83:10259 16s
测试通过创建的service的ip是否能获取到监控数据:
1 2 3 4 5 6 7 [root@k8s-master01 30-Prometheus]# curl http://10.96.115.195:10259/metrics Client sent an HTTP request to an HTTPS server. # 这个返回信息的意思:“客户端向 HTTPS 服务器发送了一个 HTTP 请求。” # 出现这个提示的原因是,访问10259端口,这是 kube-scheduler 的安全端口(Secure Port),它只接收经过 TLS 加密的 HTTPS 请求。所以要通过证书进行访问 curl --cacert /etc/kubernetes/pki/ca.pem --cert /etc/kubernetes/pki/admin.pem --key /etc/kubernetes/pki/admin-key.pem https://10.96.115.195:10259/metrics -k|tail -5 # 通过下图可以看到通过service的ip能获取到监控数据
同样在Prometheus监控中请求kube-scheduler的接口也要使用https,所以也需要配置证书(可以参考etcd和kube-controller-manager的证书配置方法,一个道理)
1 2 3 4 5 # 首先找到证书,创建一个secret,这个secret要给prometheus-k8s-0使用,所以要个prometheus-k8s-0的pod在同一个命名空间中 kubectl create secret generic kube-scheduler-ssl \ --from-file=/etc/kubernetes/pki/ca.pem \ --from-file=/etc/kubernetes/pki/admin.pem \ --from-file=/etc/kubernetes/pki/admin-key.pem -n monitoring
将secret证书挂载至 Prometheus 容器(由于 Prometheus 是 Operator 部署的,所以只需要修改Prometheus 资源即可):
1 2 3 4 5 kubectl edit prometheus -n monitoring k8s secrets: #在secrets下添加刚才创建的secret名字,是kube-scheduler-ssl - etcd-ssl #这个是etcd的证书 - kube-controller-manager-ssl #这个是kube-controller-manager证书的名字 - kube-scheduler-ssl #这个是为kube-scheduler创建的secret
保存退出后,Prometheus 的 Pod (prometheus-k8s-0)会自动重启,重启完成后,查看证书是否挂载(任意一个Prometheus 的 Pod 均可):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 # 等待pod(prometheus-k8s-0)自动重启,查看证书是否挂载成功 [root@k8s-master01 kube-scheduler]# kubectl exec -ti prometheus-k8s-0 -n monitoring -- sh /prometheus $ ls -l /etc/prometheus/secrets/ total 0 drwxrwsrwt 3 root 2000 140 Nov 22 09:04 etcd-ssl drwxrwsrwt 3 root 2000 140 Nov 22 09:04 kube-controller-manager-ssl drwxrwsrwt 3 root 2000 140 Nov 22 09:04 kube-scheduler-ssl /prometheus $ ls -l /etc/prometheus/secrets/kube-scheduler-ssl/ total 0 lrwxrwxrwx 1 root 2000 20 Nov 22 09:04 admin-key.pem -> ..data/admin-key.pem lrwxrwxrwx 1 root 2000 16 Nov 22 09:04 admin.pem -> ..data/admin.pem lrwxrwxrwx 1 root 2000 13 Nov 22 09:04 ca.pem -> ..data/ca.pem # 编辑kube-scheduler的ServiceMonitor,配置tlsConfig中证书文件部分 [root@k8s-master01 kube-scheduler]# kubectl edit servicemonitors.monitoring.coreos.com -n monitoring kube-scheduler 2 # and an empty file will abort the edit. If an error occurs while saving this file will be 3 # reopened with the relevant failures. 4 # 5 apiVersion: monitoring.coreos.com/v1 6 kind: ServiceMonitor 7 metadata: 8 creationTimestamp: "2025-09-21T12:35:57Z" 9 generation: 1 10 labels: 11 app.kubernetes.io/name: kube-scheduler 12 app.kubernetes.io/part-of: kube-prometheus 13 name: kube-scheduler 14 namespace: monitoring 15 resourceVersion: "16387785" 16 uid: 70e55cbd-9a73-4103-a483-5a6fa99d6b40 17 spec: 18 endpoints: 19 - bearerTokenFile: /var/run/secrets/kubernetes.io/serviceaccount/token 20 interval: 30s 21 port: https-metrics 22 scheme: https 23 tlsConfig: #在tlsConfig下配置证书,证书路径是名字为prometheus-k8s-0 的 pod中的路径 24 caFile: /etc/prometheus/secrets/kube-scheduler-secret/ca.pem 25 certFile: /etc/prometheus/secrets/kube-scheduler-secret/admin.pem 26 keyFile: /etc/prometheus/secrets/kube-scheduler-secret/admin-key.pem 27 insecureSkipVerify: true 28 - bearerTokenFile: /var/run/secrets/kubernetes.io/serviceaccount/token 29 interval: 5s 30 metricRelabelings: 31 - action: drop 32 regex: process_start_time_seconds 33 sourceLabels: 34 - __name__ 35 path: /metrics/slis 36 port: https-metrics 37 scheme: https 38 tlsConfig: 39 caFile: /etc/prometheus/secrets/kube-scheduler-secret/ca.pem 40 certFile: /etc/prometheus/secrets/kube-scheduler-secret/admin.pem 41 keyFile: /etc/prometheus/secrets/kube-scheduler-secret/admin-key.pem 42 insecureSkipVerify: true 43 jobLabel: app.kubernetes.io/name 44 namespaceSelector: 45 matchNames: 46 - kube-system 47 selector: 48 matchLabels: 49 app.kubernetes.io/name: kube-scheduler # 在tlsConfig块下添加证书路径,路径是pod中容器的路径,不是宿主机的路径,增加24,25,26,39,40,41行的内容
在prometheus控制台查看是否还存在报错:
下面已经看不到之前的报错了(KubeSchedulerDown)
可能存在的问题:
可能会遇到Service不通的问题,因为在集群搭建时,可能ControllerManager和Scheduler是监听的127.0.0.1就导致无法被外部访问,此时需要更改它的监听地址为0.0.0.0:
1 2 3 4 5 6 7 8 9 10 11 # 查看服务监听地址: [root@k8s-master01 kube-scheduler]# netstat -lntup|grep kube-controlle tcp6 0 0 :::10257 :::* LISTEN 1126/kube-controlle [root@k8s-master01 kube-scheduler]# netstat -lntup|grep kube-scheduler tcp6 0 0 :::10259 :::* LISTEN 1125/kube-scheduler # 如果监听的地址是127.0.0.1,就需要修改对应服务的配置文件,将监听地址改为0.0.0.0,服务的配置文件路径根据自己的位置修改。例如: sed -i "s#address=127.0.0.1#address=0.0.0.0#g" /usr/lib/systemd/system/kube-controller-manager.service # 修改后重启 systemctl daemon-reload systemctl restart kube-controller-manager
6.Prometheus监控外部windows/Linux主机 监控 Linux主机 的 Exporter 是:https://github.com/prometheus/node_exporter,
监控 Windows主机的 Exporter 是:https://github.com/prometheus-community/windows_exporter。
首 先 下 载 对 应 的 Exporter 至 Windows 主 机 ( MSI 文 件 下 载 地 址 :https://github.com/prometheus-community/windows_exporter/releases):
下载后直接在要监控的windows主机上安装,Windows Exporter 会暴露一个 9182 端口,可以通过该端口访问到 Windows 的监控数据。
验证是否能获取到监控数据:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 # 可以正常获取到监控数据 [root@k8s-master01 30-Prometheus]# curl 192.168.0.4:9182/metrics|tail -10 % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 100 556k 0 556k 0 0 132k 0 --:--:-- 0:00:04 --:--:-- 132k windows_system_processor_queue_length 0 # HELP windows_system_system_calls_total Total number of system calls (WMI source : PerfOS_System.SystemCallsPersec) # TYPE windows_system_system_calls_total counter windows_system_system_calls_total 1.193316292e+09 # HELP windows_system_system_up_time System boot time (WMI source : PerfOS_System.SystemUpTime) # TYPE windows_system_system_up_time gauge windows_system_system_up_time 1.7851201259523022e+09 # HELP windows_system_threads Current number of threads (WMI source : PerfOS_System.Threads) # TYPE windows_system_threads gauge windows_system_threads 3992
接下来创建一个ScrapeConfig资源来监控外部服务:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 [root@k8s-master01 30-Prometheus]# cat scrape-config-windows.yaml # ScrapeConfig配置如下 apiVersion: monitoring.coreos.com/v1alpha1 kind: ScrapeConfig metadata: name: external-windows-exporter namespace: monitoring # labels: # 例如 kube-prometheus-stack 默认可能不需要特殊 label,或需要 release: prometheus # 这里我把标签注释了,因为 Prometheus 对象中的 scrapeConfigSelector是{},表示匹配所有 #release: prometheus # 关键点:用于被 Prometheus 的 scrapeConfigSelector 匹配 spec: jobName: windows-exporter # Prometheus 中的 job 名称 scrapeInterval: 30s # 抓取频率 scrapeTimeout: 10s # 抓取超时时间 metricsPath: /metrics # 指标暴露路径(默认是 /metrics) scheme: HTTP # 协议 staticConfigs: - targets: - 192.168.0.4:9182 # 外部 Windows 主机 IP 和端口 # - '192.168.1.101:9182' # 如果有多个 Windows,直接追加即可 labels: env: test # 自定义标签:环境 os: windows # 自定义标签:操作系统
创建资源:
1 2 [root@k8s-master01 30-Prometheus]# kubectl create -f scrape-config-windows.yaml scrapeconfig.monitoring.coreos.com/external-windows-exporter created
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 # 旧版本的写法,如果版本允许建议只用上面新的写法,仅供参考 [root@k8s-master01 blackbox-exporter]# cat prometheus-additional.yaml # 添加下面配置 - job_name: 'blackbox' # 任务名称 metrics_path: /probe # 指标获取路径 params: module: [http_2xx] # 使用的探测模块 static_configs: - targets: #targets模块下配置的是要监控的网站域名 - http://gaoxin.kubeasy.com # 监控目标 - https://www.baidu.com - https://www.ibstd.cn relabel_configs: # 标签重写规则,固定写法 - source_labels: [__address__] target_label: __param_target - source_labels: [__param_target] target_label: instance - target_label: __address__ replacement: blackbox-exporter:19115 # 下面部署是新增加对windows主机监控的部分, - job_name: 'WindowsMonitor' static_configs: - targets: - "192.168.0.103:9182" #这里是被监控电脑的ip地址,如果有多个参考上述站点的监控格式写多个即可 labels: server_type: 'windows' relabel_configs: - source_labels: [__address ] target_label: instance # Targets 配置的是监控主机,如果是多台 Windows 主机,配置多行即可,当然每台主机都需要配置 Exporter。 # 对该静态文件进行热更新:通过下面的命令热更新secret kubectl create secret generic prometheus-additional-config --from-file=prometheus-additional.yaml --dry-run=client -oyaml|kubectl replace -f - -n monitoring
之后可以在 Prometheus Web UI 看到监控数据表示配置正确:
上述都显示没问题了在grafana中导入监控模板(模板任选一个即可):
模板id:20763 模板id:12566