服务发现简介 在 Prometheus Operator 中, 我们无需手动编辑配置文件添加 kubernetes_sd_config 配置, Prometheus Operator 提供了下述资源:
serviceMonitor
:创建 endpoints 级别的服务发现podMonitor
:创建 pod 级别的服务发现probe
:创建 ingress 级别的服务发现(用于黑盒监控)通过对这三种 CRD 资源的管理实现 prometheus 动态的服务发现。
除了 Kubernetes 集群中的一些资源对象、节点以及组件都需要监控,有的时候可能还需要根据实际的业务需求去添加自定义的监控项,添加一个自定义监控的步骤也是非常简单的。
第一步建立一个 ServiceMonitor 或 podMonitor 对象,用于 Prometheus 添加监控项 第二步为 ServiceMonitor 或 podMonitor 对象关联 metrics 数据接口的一个 Service 对象 第三步确保 Service 或 Pod 对象可以正确获取到 metrics 数据 接下来就来为大家演示如何添加 etcd
、traefik
、kube-controller-manager
、kube-scheduler
的监控。无论是 Kubernetes 集群外的还是安装在集群内部的监控,这里都将其视作集群外的独立集群,因为对于二者的使用方法没什么特殊之处。
Kubernetes组件监控 kube-scheduler监控 Prometheus Operator 提供了kube-scheduler
监控配置文件,先来查看下 kube-scheduler 组件对应的 ServiceMonitor 资源的定义,kubernetesControlPlane-serviceMonitorKubeScheduler.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 apiVersion: monitoring.coreos.com/v1 kind: ServiceMonitor metadata: labels: app.kubernetes.io/name: kube-scheduler app.kubernetes.io/part-of: kube-prometheus name: kube-scheduler namespace: monitoring spec: endpoints: - bearerTokenFile: /var/run/secrets/kubernetes.io/serviceaccount/token interval: 30s port: https-metrics scheme: https tlsConfig: insecureSkipVerify: true jobLabel: app.kubernetes.io/name namespaceSelector: matchNames: - kube-system selector: matchLabels: app.kubernetes.io/name: kube-scheduler
上面是一个典型的 ServiceMonitor
资源对象的声明方式,通过 selector.matchLabels
在 kube-system
这个命名空间下面匹配具有 app.kubernetes.io/name=kube-scheduler
这样的 Service,但是这里采用二进制安装,系统中根本就没有对应的 Service。
1 2 $ kubectl get svc -n kube-system -l app.kubernetes.io/name=kube-scheduler No resources found in kube-system namespace.
所以我们需要去创建一个对应的 Service 对象,才能与 ServiceMonitor
进行关联,由于是集群外部的服务,所以要引入到集群中来我们就需要自定义 Endpoints
对象来创建 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 apiVersion: v1 kind: Service metadata: name: kube-scheduler namespace: kube-system labels: app.kubernetes.io/name: kube-scheduler spec: type: ClusterIP clusterIP: None ports: - name: https-metrics port: 10259 --- apiVersion: v1 kind: Endpoints metadata: name: kube-scheduler namespace: kube-system labels: app.kubernetes.io/name: kube-scheduler subsets: - addresses: - ip: 10.1 .1 .100 nodeName: kube-scheduler ports: - name: https-metrics port: 10259
创建的 kube-scheduler 监控是独立于集群之外的,这种情况下面就需要自定义一个 Endpoints,要注意 metadata
区域的内容要和 Service 保持一致,Service 的 clusterIP 设置为 None。
1 2 3 4 5 6 $ kubectl get Endpoints -n kube-system kube-scheduler NAME ENDPOINTS AGE kube-scheduler 10.1.1.100:10259 40d $ kubectl get svc -n kube-system kube-scheduler NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE kube-scheduler ClusterIP None <none> 10259/TCP 40d
创建完成后,隔一小会儿后去 Prometheus 页面上查看 targets 下面 kube-scheduler 已经有采集的目标了,如果报了 connect: connection refused
这样的错误,需要检查 kube-scheduler 启动的时候默认绑定的是IP地址。
1 2 3 4 5 6 7 8 9 $ cat kube-scheduler.conf KUBE_SCHEDULER_OPTS="--logtostderr=false \ --v=2 \ --log-dir=/opt/kubernetes/logs \ --leader-elect \ --authentication-kubeconfig=/opt/kubernetes/cfg/kube-scheduler.kubeconfig \ --authorization-kubeconfig=/opt/kubernetes/cfg/kube-scheduler.kubeconfig \ --kubeconfig=/opt/kubernetes/cfg/kube-scheduler.kubeconfig \ --bind-address=10.1.1.100"
Grafana 下面的 Dashboard 查看监控图表信息。
可以用同样的方式来修复下 kube-controller-manager 组件的监控
kube-controller-manager 监控 首先检查 kube-controller-manager 启动的时候默认绑定的是IP地址。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 $ cat kube-controller-manager.conf KUBE_CONTROLLER_MANAGER_OPTS="--logtostderr=false \ --v=2 \ --log-dir=/opt/kubernetes/logs \ --leader-elect=true \ --kubeconfig=/opt/kubernetes/cfg/kube-controller-manager.kubeconfig \ --authentication-kubeconfig=/opt/kubernetes/cfg/kube-controller-manager.kubeconfig \ --authorization-kubeconfig=/opt/kubernetes/cfg/kube-controller-manager.kubeconfig \ --bind-address=10.1.1.100 \ --cluster-cidr=172.17.0.0/16 \ --service-cluster-ip-range=192.168.0.0/16 \ --cluster-signing-cert-file=/opt/kubernetes/ssl/ca.pem \ --cluster-signing-key-file=/opt/kubernetes/ssl/ca-key.pem \ --root-ca-file=/opt/kubernetes/ssl/ca.pem \ --service-account-private-key-file=/opt/kubernetes/ssl/serviceaccount-key.pem \ --cluster-signing-duration=87600h0m0s"
引入到集群中来我们就需要自定义 Endpoints
对象来创建 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 apiVersion: v1 kind: Service metadata: name: kube-controller-manager namespace: kube-system labels: app.kubernetes.io/name: kube-controller-manager spec: type: ClusterIP clusterIP: None ports: - name: https-metrics port: 10257 --- apiVersion: v1 kind: Endpoints metadata: name: kube-controller-manager namespace: kube-system labels: app.kubernetes.io/name: kube-controller-manager subsets: - addresses: - ip: 10.1 .1 .100 nodeName: kube-controller-manager ports: - name: https-metrics port: 10257
Grafana 下面的 Dashboard 查看监控图表信息。
Etcd 监控 同样也可以使用这种方式来监控 etcd集群。
创建对应的 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 apiVersion: monitoring.coreos.com/v1 kind: ServiceMonitor metadata: name: etcd-cluster-k8s namespace: monitoring labels: k8s-app: etcd-k8s spec: jobLabel: k8s-app endpoints: - port: port interval: 15s scheme: https tlsConfig: caFile: /opt/etcd/ssl/ca.pem certFile: /opt/etcd/ssl/server.pem keyFile: /opt/etcd/ssl/server-key.pem insecureSkipVerify: true selector: matchLabels: k8s-app: etcd namespaceSelector: matchNames: - kube-system
匹配 kube-system 这个命名空间下面的具有 k8s-app=etcd-k8s
这个 label 标签的 Service,jobLabel
表示用于检索 job 任务名称的标签,由于 etcd 的 metrics 接口在 2379 端口下面。
引入到集群中来我们就需要自定义 Endpoints
对象来创建 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 --- apiVersion: v1 kind: Service metadata: name: etcd-k8s namespace: kube-system labels: k8s-app: etcd spec: type: ClusterIP clusterIP: None ports: - name: port port: 2379 --- apiVersion: v1 kind: Endpoints metadata: name: etcd-k8s namespace: kube-system labels: k8s-app: etcd subsets: - addresses: - ip: 10.1 .1 .100 nodeName: etcd-cluster-1 - ip: 10.1 .1 .120 nodeName: etcd-cluster-2 - ip: 10.1 .1 .130 nodeName: etcd-cluster-3 ports: - name: port port: 2379
创建存放证书的Secret
1 kubectl create secret generic etcd-certs --from-file=/opt/etcd/ssl/etcd-client-key.pem --from-file=/opt/etcd/ssl/etcd-client.pem --from-file=/opt/etcd/ssl/ca.pem -n monitoring
编辑prometheus-prometheus.yaml
1 2 3 4 5 6 7 8 9 10 11 ...... volumeMounts: - mountPath: /opt/etcd/ssl name: etcd-certs volumes: - name: etcd-certs secret: secretName: etcd-certs defaultMode: 0640 ......
创建完成后,隔一会儿去 Prometheus 的 Dashboard 中查看 targets,便会有 etcd 的监控项了
数据采集到后,可以在 grafana 中导入编号为 3070 的 dashboard,就可以获取到 etcd 的监控图表
Traefik 监控 以 Traefik 为例, 使用 podMonitor 资源监控 Traefik。traefik 安装请参考 traefik系列文章
创建 podMonitor
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 apiVersion: monitoring.coreos.com/v1 kind: PodMonitor metadata: labels: app.kubernetes.io/name: traefik name: traefik namespace: monitoring spec: jobLabel: app.kubernetes.io/name podMetricsEndpoints: - interval: 15s path: /metrics port: metrics namespaceSelector: matchNames: - kube-system selector: matchLabels: app: traefik-v2
查看 prometheus
数据采集到后,可以在 grafana 中导入编号为 4475 的 dashboard,就可以获取到 traefik 的监控图表
集群范围的自动发现 当 k8s 集群中 service 和 pod 达到一定规模后手动一个一个创建 serviceMonitor 和 podMonitor 不免又麻烦了起来, 我们可以使用不限制 namespace 的 kubernetes_sd_configs 实现集群范围内自动发现所有的 exporter 实例
接下来的演示中我们监控集群范围内的所有 endpoints, 并且将带有 prometheus.io/scrape=true
这个 annotations
的 service 注册到 prometheus
rbac 由于需要访问访问集群范围内的资源对象, 继续使用 role+roleBinding 模式显然不适合, prometheus-k8s 这个 serviceAccount 还绑定一个名为 prometheus-k8s 的 clusterRole, 该 clusterRole 默认权限是不够的, 添加需要的权限:
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 apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole 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.47 .2 name: prometheus-k8s rules: - apiGroups: - "" resources: - nodes/metrics verbs: - get - apiGroups: - "" resources: - services - endpoints - pods verbs: - list - watch - nonResourceURLs: - /metrics verbs: - get
自动发现配置 参考文章详解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 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 - job_name: 'kubernetes-pods' kubernetes_sd_configs: - role: endpoints relabel_configs: - source_labels: [__meta_kubernetes_service_annotation_prometheus_io_scrape ] action: keep regex: true - source_labels: [__meta_kubernetes_service_annotation_prometheus_io_scheme ] action: replace target_label: __scheme__ regex: (https?) - source_labels: [__meta_kubernetes_service_annotation_prometheus_io_path ] action: replace target_label: __metrics_path__ regex: (.+) - source_labels: [__address__ , __meta_kubernetes_service_annotation_prometheus_io_port ] action: replace target_label: __address__ regex: ([^:]+)(?::\d+)?;(\d+) replacement: $1:$2 - action: labelmap regex: __meta_kubernetes_service_label_(.+) - source_labels: [__meta_kubernetes_namespace ] action: replace target_label: kubernetes_namespace - source_labels: [__meta_kubernetes_service_name ] action: replace target_label: kubernetes_name - source_labels: [__meta_kubernetes_pod_name ] action: replace target_label: kubernetes_pod_name
通过 secret 挂载进容器中
1 kubectl create secret generic additional-scrape-configs -n monitoring --from-file=prometheus-additional.yaml
修改 prometheus 文件添加了 additionalScrapeConfigs
配置
1 2 3 4 5 6 7 8 spec: additionalScrapeConfigs: name: additional-scrape-configs key: prometheus-additional.yaml $ kubectl apply -f prometheus-prometheus.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 apiVersion: v1 kind: Namespace metadata: name: test --- apiVersion: v1 kind: Service metadata: name: test-node-exporter namespace: test labels: app: test-node-exporter annotations: prometheus.io/scrape: "true" prometheus.io/port: "9200" spec: selector: app: test-node-exporter ports: - name: metrics port: 9200 targetPort: metrics --- apiVersion: apps/v1 kind: Deployment metadata: name: test-node-exporter namespace: test labels: app: test-node-exporter spec: replicas: 1 selector: matchLabels: app: test-node-exporter template: metadata: labels: app: test-node-exporter spec: containers: - args: - --web.listen-address=:9200 image: prom/node-exporter:v1.6.1 name: node-exporter ports: - name: metrics containerPort: 9200
如下, 我们部署的 node-exporter 已经成功注册, 只要 service 设置了 annotations
即可,service coredns 默认有 prometheus.io/scrape=true
这个注解, 已经成功注册: