一、介绍

Operator是CoreOS公司开发,用于扩展kubernetes API或特定应用程序的控制器,它用来创建、配置、管理复杂的有状态应用,例如数据库,监控系统。其中Prometheus-Operator就是其中一个重要的项目。

其架构图如下:
5.6、Operator部署Prometheus - 图1
其中核心部分是Operator,它会去创建Prometheus、ServiceMonitor、AlertManager、PrometheusRule这4个CRD对象,然后会一直监控并维护这4个对象的状态。

  • Prometheus:作为Prometheus Server的抽象
  • ServiceMonitor:就是exporter的各种抽象
  • AlertManager:作为Prometheus AlertManager的抽象
  • PrometheusRule:实现报警规则的文件

上图中的 Service 和 ServiceMonitor 都是 Kubernetes 的资源,一个 ServiceMonitor 可以通过 labelSelector 的方式去匹配一类 Service,Prometheus 也可以通过 labelSelector 去匹配多个ServiceMonitor。

二、安装

注意集群版本的坑,自己先到Github上下载对应的版本。

image.png

我们使用源码来安装,首先克隆源码到本地:

  1. # git clone https://github.com/coreos/kube-prometheus.git

我们进入kube-prometheus/manifests/setup,就可以直接创建CRD对象:

  1. # cd kube-prometheus/manifests/setup
  2. # kubectl apply -f .

然后在上层目录创建资源清单:

  1. # cd kube-prometheus/manifests
  2. # kubectl apply -f .

可以看到创建如下的CRD对象:

  1. # kubectl get crd | grep coreos
  2. alertmanagers.monitoring.coreos.com 2019-12-02T03:03:37Z
  3. podmonitors.monitoring.coreos.com 2019-12-02T03:03:37Z
  4. prometheuses.monitoring.coreos.com 2019-12-02T03:03:37Z
  5. prometheusrules.monitoring.coreos.com 2019-12-02T03:03:37Z
  6. servicemonitors.monitoring.coreos.com 2019-12-02T03:03:37Z

查看创建的pod:

  1. # kubectl get pod -n monitoring
  2. NAME READY STATUS RESTARTS AGE
  3. alertmanager-main-0 2/2 Running 0 2m37s
  4. alertmanager-main-1 2/2 Running 0 2m37s
  5. alertmanager-main-2 2/2 Running 0 2m37s
  6. grafana-77978cbbdc-886cc 1/1 Running 0 2m46s
  7. kube-state-metrics-7f6d7b46b4-vrs8t 3/3 Running 0 2m45s
  8. node-exporter-5552n 2/2 Running 0 2m45s
  9. node-exporter-6snb7 2/2 Running 0 2m45s
  10. prometheus-adapter-68698bc948-6s5f2 1/1 Running 0 2m45s
  11. prometheus-k8s-0 3/3 Running 1 2m27s
  12. prometheus-k8s-1 3/3 Running 1 2m27s
  13. prometheus-operator-6685db5c6-4tdhp 1/1 Running 0 2m52s

查看创建的Service:

  1. # kubectl get svc -n monitoring
  2. NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
  3. alertmanager-main ClusterIP 10.68.97.247 <none> 9093/TCP 3m51s
  4. alertmanager-operated ClusterIP None <none> 9093/TCP,9094/TCP,9094/UDP 3m41s
  5. grafana ClusterIP 10.68.234.173 <none> 3000/TCP 3m50s
  6. kube-state-metrics ClusterIP None <none> 8443/TCP,9443/TCP 3m50s
  7. node-exporter ClusterIP None <none> 9100/TCP 3m50s
  8. prometheus-adapter ClusterIP 10.68.109.201 <none> 443/TCP 3m50s
  9. prometheus-k8s ClusterIP 10.68.9.232 <none> 9090/TCP 3m50s
  10. prometheus-operated ClusterIP None <none> 9090/TCP 3m31s
  11. prometheus-operator ClusterIP None <none> 8080/TCP 3m57s

我们看到我们常用的prometheus和grafana都是clustorIP,我们要外部访问可以配置为NodePort类型或者用ingress。比如配置为ingress:
prometheus-ingress.yaml

  1. apiVersion: extensions/v1beta1
  2. kind: Ingress
  3. metadata:
  4. name: prometheus-ingress
  5. namespace: monitoring
  6. annotations:
  7. kubernetes.io/ingress.class: "traefik"
  8. spec:
  9. rules:
  10. - host: prometheus.joker.com
  11. http:
  12. paths:
  13. - path:
  14. backend:
  15. serviceName: prometheus-k8s
  16. servicePort: 9090

grafana-ingress.yaml

  1. apiVersion: extensions/v1beta1
  2. kind: Ingress
  3. metadata:
  4. name: grafana-ingress
  5. namespace: monitoring
  6. annotations:
  7. kubernetes.io/ingress.class: "traefik"
  8. spec:
  9. rules:
  10. - host: grafana.joker.com
  11. http:
  12. paths:
  13. - path:
  14. backend:
  15. serviceName: grafana
  16. servicePort: 3000

但是我们这里由于没有域名进行备案,我们就用NodePort类型。修改后如下:

  1. # kubectl get svc -n monitoring
  2. NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
  3. grafana NodePort 10.68.234.173 <none> 3000:39807/TCP 3h1m 3h1m
  4. prometheus-k8s NodePort 10.68.9.232 <none> 9090:20547/TCP 3h1m

然后就可以正常在浏览器访问了。

三、配置

3.1、监控集群资源

我们可以看到大部分的配置都是正常的,只有两三个没有管理到对应的监控目标,比如 kube-controller-manager 和 kube-scheduler 这两个系统组件,这就和 ServiceMonitor 的定义有关系了,我们先来查看下 kube-scheduler 组件对应的 ServiceMonitor 资源的定义:(prometheus-serviceMonitorKubeScheduler.yaml)

  1. apiVersion: monitoring.coreos.com/v1
  2. kind: ServiceMonitor
  3. metadata:
  4. labels:
  5. k8s-app: kube-scheduler
  6. name: kube-scheduler
  7. namespace: monitoring
  8. spec:
  9. endpoints:
  10. - interval: 30s # 每30s获取一次信息
  11. port: http-metrics # 对应service的端口名
  12. jobLabel: k8s-app
  13. namespaceSelector: # 表示去匹配某一命名空间中的service,如果想从所有的namespace中匹配用any: true
  14. matchNames:
  15. - kube-system
  16. selector: # 匹配的 Service 的labels,如果使用mathLabels,则下面的所有标签都匹配时才会匹配该service,如果使用matchExpressions,则至少匹配一个标签的service都会被选择
  17. matchLabels:
  18. k8s-app: kube-scheduler

上面是一个典型的 ServiceMonitor 资源文件的声明方式,上面我们通过selector.matchLabels在 kube-system 这个命名空间下面匹配具有k8s-app=kube-scheduler这样的 Service,但是我们系统中根本就没有对应的 Service,所以我们需要手动创建一个 Service:(prometheus-kubeSchedulerService.yaml)

  1. apiVersion: v1
  2. kind: Service
  3. metadata:
  4. namespace: kube-system
  5. name: kube-scheduler
  6. labels:
  7. k8s-app: kube-scheduler
  8. spec:
  9. selector:
  10. component: kube-scheduler
  11. ports:
  12. - name: http-metrics
  13. port: 10251
  14. targetPort: 10251
  15. protocol: TCP

10251是kube-scheduler组件 metrics 数据所在的端口,10252是kube-controller-manager组件的监控数据所在端口。

其中最重要的是上面 labels 和 selector 部分,labels 区域的配置必须和我们上面的 ServiceMonitor 对象中的 selector 保持一致,selector下面配置的是component=kube-scheduler,为什么会是这个 label 标签呢,我们可以去 describe 下 kube-scheduelr 这个 Pod:

  1. $ kubectl describe pod kube-scheduler-master -n kube-system
  2. Name: kube-scheduler-master
  3. Namespace: kube-system
  4. Node: master/10.151.30.57
  5. Start Time: Sun, 05 Aug 2018 18:13:32 +0800
  6. Labels: component=kube-scheduler
  7. tier=control-plane
  8. ......

我们可以看到这个 Pod 具有component=kube-scheduler和tier=control-plane这两个标签,而前面这个标签具有更唯一的特性,所以使用前面这个标签较好,这样上面创建的 Service 就可以和我们的 Pod 进行关联了,直接创建即可:

  1. $ kubectl create -f prometheus-kubeSchedulerService.yaml
  2. $ kubectl get svc -n kube-system -l k8s-app=kube-scheduler
  3. NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
  4. kube-scheduler ClusterIP 10.102.119.231 <none> 10251/TCP 18m

创建完成后,隔一小会儿后去 prometheus 查看 targets 下面 kube-scheduler 的状态:
5.6、Operator部署Prometheus - 图3promethus kube-scheduler error
我们可以看到现在已经发现了 target,但是抓取数据结果出错了,这个错误是因为我们集群是使用 kubeadm 搭建的,其中 kube-scheduler 默认是绑定在127.0.0.1上面的,而上面我们这个地方是想通过节点的 IP 去访问,所以访问被拒绝了,我们只要把 kube-scheduler 绑定的地址更改成0.0.0.0即可满足要求,由于 kube-scheduler 是以静态 Pod 的形式运行在集群中的,所以我们只需要更改静态 Pod 目录下面对应的 YAML 文件即可:

  1. $ ls /etc/kubernetes/manifests/
  2. etcd.yaml kube-apiserver.yaml kube-controller-manager.yaml kube-scheduler.yaml

将 kube-scheduler.yaml 文件中-command的—address地址更改成0.0.0.0:

  1. containers:
  2. - command:
  3. - kube-scheduler
  4. - --leader-elect=true
  5. - --kubeconfig=/etc/kubernetes/scheduler.conf
  6. - --address=0.0.0.0

修改完成后我们将该文件从当前文件夹中移除,隔一会儿再移回该目录,就可以自动更新了,然后再去看 prometheus 中 kube-scheduler 这个 target 是否已经正常了:
5.6、Operator部署Prometheus - 图4promethues-operator-kube-scheduler
大家可以按照上面的方法尝试去修复下 kube-controller-manager 组件的监控。

3.2、监控集群外资源

很多时候我们并不是把所有资源都部署在集群内的,经常有比如ectd,kube-scheduler等都部署在集群外。其监控流程和上面大致一样,唯一的区别就是在定义Service的时候,其EndPoints是需要我们自己去定义的。

3.2.1、监控kube-scheduler

(1)、定义Service和EndPoints
prometheus-KubeSchedulerService.yaml

  1. apiVersion: v1
  2. kind: Service
  3. metadata:
  4. name: kube-scheduler
  5. namespace: kube-system
  6. labels:
  7. k8s-app: kube-scheduler
  8. spec:
  9. type: ClusterIP
  10. clusterIP: None
  11. ports:
  12. - name: http-metrics
  13. port: 10251
  14. targetPort: 10251
  15. protocol: TCP
  16. ---
  17. apiVersion: v1
  18. kind: Endpoints
  19. metadata:
  20. name: kube-scheduler
  21. namespace: kube-system
  22. labels:
  23. k8s-app: kube-scheduler
  24. subsets:
  25. - addresses:
  26. - ip: 172.16.0.33
  27. ports:
  28. - name: http-metrics
  29. port: 10251
  30. protocol: TCP

(2)、定义ServiceMonitor
prometheus-serviceMonitorKubeScheduler.yaml

  1. apiVersion: monitoring.coreos.com/v1
  2. kind: ServiceMonitor
  3. metadata:
  4. name: kube-scheduler
  5. namespace: monitoring
  6. labels:
  7. k8s-app: kube-scheduler
  8. spec:
  9. endpoints:
  10. - interval: 30s
  11. port: http-metrics
  12. jobLabel: k8s-app
  13. namespaceSelector:
  14. matchNames:
  15. - kube-system
  16. selector:
  17. matchLabels:
  18. k8s-app: kube-scheduler

然后我们就可以看到其监控上了:image.png

3.2.2、监控kube-controller-manager

(1)、配置Service和EndPoints,
prometheus-KubeControllerManagerService.yaml

  1. apiVersion: v1
  2. kind: Service
  3. metadata:
  4. name: kube-controller-manager
  5. namespace: kube-system
  6. labels:
  7. k8s-app: kube-controller-manager
  8. spec:
  9. type: ClusterIP
  10. clusterIP: None
  11. ports:
  12. - name: http-metrics
  13. port: 10252
  14. targetPort: 10252
  15. protocol: TCP
  16. ---
  17. apiVersion: v1
  18. kind: Endpoints
  19. metadata:
  20. name: kube-controller-manager
  21. namespace: kube-system
  22. labels:
  23. k8s-app: kube-controller-manager
  24. subsets:
  25. - addresses:
  26. - ip: 172.16.0.33
  27. ports:
  28. - name: http-metrics
  29. port: 10252
  30. protocol: TCP

(2)、配置ServiceMonitor
prometheus-serviceMonitorKubeControllerManager.yaml

  1. apiVersion: monitoring.coreos.com/v1
  2. kind: ServiceMonitor
  3. metadata:
  4. labels:
  5. k8s-app: kube-controller-manager
  6. name: kube-controller-manager
  7. namespace: monitoring
  8. spec:
  9. endpoints:
  10. - interval: 30s
  11. metricRelabelings:
  12. - action: drop
  13. regex: etcd_(debugging|disk|request|server).*
  14. sourceLabels:
  15. - __name__
  16. port: http-metrics
  17. jobLabel: k8s-app
  18. namespaceSelector:
  19. matchNames:
  20. - kube-system
  21. selector:
  22. matchLabels:
  23. k8s-app: kube-controller-manager

image.png

3.2.3、监控etcd

很多情况下,我们的etcd都需要进行SSL认证的,所以首先需要将用到的证书保存到集群中去。
(根据自己集群证书的位置修改)

  1. kubectl -n monitoring create secret generic etcd-certs --from-file=/etc/kubernetes/pki/etcd/healthcheck-client.crt --from-file=/etc/kubernetes/pki/etcd/healthcheck-client.key --from-file=/etc/kubernetes/pki/etcd/ca.crt

然后将上面创建的 etcd-certs 对象配置到 prometheus 资源对象中,直接更新 prometheus 资源对象即可:

  1. # kubectl edit prometheus k8s -n monitoring

添加如下的 secrets 属性:

  1. nodeSelector:
  2. beta.kubernetes.io/os: linux
  3. replicas: 2
  4. secrets:
  5. - etcd-certs

更新完成后,我们就可以在 Prometheus 的 Pod 中获取到上面创建的 etcd 证书文件了,具体的路径我们可以进入 Pod 中查看:

  1. # kubectl exec -it prometheus-k8s-0 -n monitoring -- /bin/sh
  2. Defaulting container name to prometheus.
  3. Use 'kubectl describe pod/prometheus-k8s-0 -n monitoring' to see all of the containers in this pod.
  4. /prometheus $ ls /etc/prometheus/secrets/etcd-certs/
  5. ca.crt healthcheck-client.crt healthcheck-client.key
  6. /prometheus $

(1)、创建ServiceMonitor
prometheus-serviceMonitorEtcd.yamlns

  1. apiVersion: monitoring.coreos.com/v1
  2. kind: ServiceMonitor
  3. metadata:
  4. name: k8s-etcd
  5. namespace: monitoring
  6. labels:
  7. k8s-app: k8s-etcd
  8. spec:
  9. jobLabel: k8s-app
  10. endpoints:
  11. - port: port
  12. interval: 30s
  13. scheme: https
  14. tlsConfig:
  15. caFile: /etc/prometheus/secrets/etcd-certs/ca.crt
  16. certFile: /etc/prometheus/secrets/etcd-certs/healthcheck-client.crt
  17. keyFile: /etc/prometheus/secrets/etcd-certs/healthcheck-client.key
  18. insecureSkipVerify: true
  19. selector:
  20. matchLabels:
  21. k8s-app: k8s-etcd
  22. namespaceSelector:
  23. matchNames:
  24. - kube-system

上面我们在 monitoring 命名空间下面创建了名为 k8s-etcd 的 ServiceMonitor 对象,基本属性和前面章节中的一致,匹配 kube-system 这个命名空间下面的具有 k8s-app=k8s-etcd 这个 label 标签的 Service,jobLabel 表示用于检索 job 任务名称的标签,和前面不太一样的地方是 endpoints 属性的写法,配置上访问 etcd 的相关证书,endpoints 属性下面可以配置很多抓取的参数,比如 relabel、proxyUrl,tlsConfig 表示用于配置抓取监控数据端点的 tls 认证,由于证书 serverName 和 etcd 中签发的可能不匹配,所以加上了 insecureSkipVerify=true.

然后创建这个配置清单:

  1. # kubectl apply -f prometheus-serviceMonitorEtcd.yaml

(2)、创建Service

  1. apiVersion: v1
  2. kind: Service
  3. metadata:
  4. name: k8s-etcd
  5. namespace: kube-system
  6. labels:
  7. k8s-app: k8s-etcd
  8. spec:
  9. type: ClusterIP
  10. clusterIP: None
  11. ports:
  12. - name: port
  13. port: 2379
  14. protocol: TCP
  15. ---
  16. apiVersion: v1
  17. kind: Endpoints
  18. metadata:
  19. name: k8s-etcd
  20. namespace: kube-system
  21. labels:
  22. k8s-app: k8s-etcd
  23. subsets:
  24. - addresses:
  25. - ip: 172.16.0.33
  26. ports:
  27. - name: port
  28. port: 2379
  29. protocol: TCP

image.png
然后在Grafana中导入3070的面板。
image.png

3.3、配置报警规则Rule

我们创建一个 PrometheusRule 资源对象后,会自动在上面的 prometheus-k8s-rulefiles-0 目录下面生成一个对应的-.yaml文件,所以如果以后我们需要自定义一个报警选项的话,只需要定义一个 PrometheusRule 资源对象即可,但是要求这个资源对象必须得有 prometheus=k8s 和 role=alert-rules 这一对标签。
如下配置Ectd报警规则:
prometheus-etcdRule.yaml

  1. apiVersion: monitoring.coreos.com/v1
  2. kind: PrometheusRule
  3. metadata:
  4. name: etcd-rules
  5. namespace: monitoring
  6. labels:
  7. prometheus: k8s
  8. role: alert-rules
  9. spec:
  10. groups:
  11. - name: etcd
  12. rules:
  13. - alert: EtcdClusterUnavailable
  14. annotations:
  15. summary: etcd cluster small
  16. description: If one more etcd peer goes down the cluster will be unavailable
  17. expr: |
  18. count(up{job="etcd"} == 0) > (count(up{job="etcd"}) / 2 - 1)
  19. for: 3m
  20. labels:
  21. severity: critical

然后我们创建这个配置清单:

  1. # kubectl apply -f prometheus-etcdRule.yaml
  2. prometheusrule.monitoring.coreos.com/etcd-rules created

然后我们刷新页面,就可以看到已经生效了
image.png

3.4、配置报警

首先我们将 alertmanager-main 这个 Service 改为 NodePort 类型的 Service,修改完成后我们可以在页面上的 status 路径下面查看 AlertManager 的配置信息:

  1. # kubectl get svc -n monitoring
  2. NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
  3. alertmanager-main NodePort 10.68.97.247 <none> 9093:21936/TCP 5h31m

然后在浏览器查看:
image.png

这些配置信息实际上是来自于我们之前在kube-prometheus/manifests目录下面创建的 alertmanager-secret.yaml 文件:

  1. apiVersion: v1
  2. data:
  3. alertmanager.yaml: Imdsb2JhbCI6CiAgInJlc29sdmVfdGltZW91dCI6ICI1bSIKInJlY2VpdmVycyI6Ci0gIm5hbWUiOiAibnVsbCIKInJvdXRlIjoKICAiZ3JvdXBfYnkiOgogIC0gImpvYiIKICAiZ3JvdXBfaW50ZXJ2YWwiOiAiNW0iCiAgImdyb3VwX3dhaXQiOiAiMzBzIgogICJyZWNlaXZlciI6ICJudWxsIgogICJyZXBlYXRfaW50ZXJ2YWwiOiAiMTJoIgogICJyb3V0ZXMiOgogIC0gIm1hdGNoIjoKICAgICAgImFsZXJ0bmFtZSI6ICJXYXRjaGRvZyIKICAgICJyZWNlaXZlciI6ICJudWxsIg==
  4. kind: Secret
  5. metadata:
  6. name: alertmanager-main
  7. namespace: monitoring
  8. type: Opaque

可以将 alertmanager.yaml 对应的 value 值做一个 base64 解码:

  1. # echo "Imdsb2JhbCI6CiAgInJlc29sdmVfdGltZW91dCI6ICI1bSIKInJlY2VpdmVycyI6Ci0gIm5hbWUiOiAibnVsbCIKInJvdXRlIjoKICAiZ3JvdXBfYnkiOgogIC0gImpvYiIKICAiZ3JvdXBfaW50ZXJ2YWwiOiAiNW0iCiAgImdyb3VwX3dhaXQiOiAiMzBzIgogICJyZWNlaXZlciI6ICJudWxsIgogICJyZXBlYXRfaW50ZXJ2YWwiOiAiMTJoIgogICJyb3V0ZXMiOgogIC0gIm1hdGNoIjoKICAgICAgImFsZXJ0bmFtZSI6ICJXYXRjaGRvZyIKICAgICJyZWNlaXZlciI6ICJudWxsIg==" | base64 -d
  2. "global":
  3. "resolve_timeout": "5m"
  4. "receivers":
  5. - "name": "null"
  6. "route":
  7. "group_by":
  8. - "job"
  9. "group_interval": "5m"
  10. "group_wait": "30s"
  11. "receiver": "null"
  12. "repeat_interval": "12h"
  13. "routes":
  14. - "match":
  15. "alertname": "Watchdog"
  16. "receiver": "null"

可以看到上面的内容和我们在网页上查到的是一致的。
如果要配置报警媒介,就可以修改这个模板:
alertmanager.yaml

  1. global:
  2. resolve_timeout: 5m
  3. smtp_smarthost: 'smtp.163.com:465'
  4. smtp_from: 'fmbankops@163.com'
  5. smtp_auth_username: 'fmbankops@163.com'
  6. smtp_auth_password: '<邮箱密码>'
  7. smtp_hello: '163.com'
  8. smtp_require_tls: false
  9. route:
  10. group_by: ['job', 'severity']
  11. group_wait: 30s
  12. group_interval: 5m
  13. repeat_interval: 12h
  14. receiver: default
  15. routes:
  16. - receiver: webhook
  17. match:
  18. alertname: CoreDNSDown
  19. receivers:
  20. - name: 'default'
  21. email_configs:
  22. - to: '517554016@qq.com'
  23. send_resolved: true
  24. - name: 'webhook'
  25. webhook_configs:
  26. - url: 'http://dingtalk-hook.kube-ops:5000' # 这是我们自定义的webhook
  27. send_resolved: true

然后我们更新secret对象:

  1. # 先将之前的 secret 对象删除
  2. $ kubectl delete secret alertmanager-main -n monitoring
  3. secret "alertmanager-main" deleted
  4. $ kubectl create secret generic alertmanager-main --from-file=alertmanager.yaml -n monitoring
  5. secret "alertmanager-main" created

然后就会收到报警信息:
image.png
image.png

四、高级配置

4.1、自动发现规则配置

我们在实际应用中会部署非常多的service和pod,如果要一个一个手动的添加监控将会是一个非常重复,浪费时间的工作,这时候就需要使用自动发现机制。我们在手动搭建Prometheus的过程中曾配置过自动发现service,其主要的配置文件如下:

  1. - job_name: 'kubernetes-service-endpoints'
  2. kubernetes_sd_configs:
  3. - role: endpoints
  4. relabel_configs:
  5. - source_labels: [__meta_kubernetes_service_annotation_prometheus_io_scrape]
  6. action: keep
  7. regex: true
  8. - source_labels: [__meta_kubernetes_service_annotation_prometheus_io_scheme]
  9. action: replace
  10. target_label: __scheme__
  11. regex: (https?)
  12. - source_labels: [__meta_kubernetes_service_annotation_prometheus_io_path]
  13. action: replace
  14. target_label: __metrics_path__
  15. regex: (.+)
  16. - source_labels: [__address__, __meta_kubernetes_service_annotation_prometheus_io_port]
  17. action: replace
  18. target_label: __address__
  19. regex: ([^:]+)(?::\d+)?;(\d+)
  20. replacement: $1:$2
  21. - action: labelmap
  22. regex: __meta_kubernetes_service_label_(.+)
  23. - source_labels: [__meta_kubernetes_namespace]
  24. action: replace
  25. target_label: kubernetes_namespace
  26. - source_labels: [__meta_kubernetes_service_name]
  27. action: replace
  28. target_label: kubernetes_name

要想自动被发现,只需要在service的配置清单中加上annotations: prometheus.io/scrape=true。
我们将上面的文件保存为prometheus-additional.yaml,然后用这个文件创建一个secret。

  1. # kubectl -n monitoring create secret generic additional-config --from-file=prometheus-additional.yaml
  2. secret/additional-config created

然后我们在prometheus的配置清单中添加这个配置:
cat prometheus-prometheus.yaml

  1. apiVersion: monitoring.coreos.com/v1
  2. kind: Prometheus
  3. metadata:
  4. labels:
  5. prometheus: k8s
  6. name: k8s
  7. namespace: monitoring
  8. spec:
  9. alerting:
  10. alertmanagers:
  11. - name: alertmanager-main
  12. namespace: monitoring
  13. port: web
  14. baseImage: quay.io/prometheus/prometheus
  15. nodeSelector:
  16. kubernetes.io/os: linux
  17. podMonitorSelector: {}
  18. replicas: 2
  19. resources:
  20. requests:
  21. memory: 400Mi
  22. ruleSelector:
  23. matchLabels:
  24. prometheus: k8s
  25. role: alert-rules
  26. securityContext:
  27. fsGroup: 2000
  28. runAsNonRoot: true
  29. runAsUser: 1000
  30. additionalScrapeConfigs:
  31. name: additional-config
  32. key: prometheus-additional.yaml
  33. serviceAccountName: prometheus-k8s
  34. serviceMonitorNamespaceSelector: {}
  35. serviceMonitorSelector: {}
  36. version: v2.11.0

然后更新一下prometheus的配置:

  1. # kubectl apply -f prometheus-prometheus.yaml
  2. prometheus.monitoring.coreos.com/k8s configured

然后我们查看prometheus的日志,发现很多错误:

  1. # kubectl logs -f prometheus-k8s-0 prometheus -n monitoring

image.png

从日志可以看出,其提示的是权限问题,在kubernetes中涉及到权限问题一般就是RBAC中配置问题,我们查看prometheus的配置清单发现其使用了一个prometheus-k8s的ServiceAccount:
image.png

而其绑定的是一个叫prometheus-k8s的ClusterRole:

  1. # kubectl get clusterrole prometheus-k8s -n monitoring -o yaml
  2. apiVersion: rbac.authorization.k8s.io/v1
  3. kind: ClusterRole
  4. metadata:
  5. annotations:
  6. kubectl.kubernetes.io/last-applied-configuration: |
  7. {"apiVersion":"rbac.authorization.k8s.io/v1","kind":"ClusterRole","metadata":{"annotations":{},"name":"prometheus-k8s"},"rules":[{"apiGroups":[""],"resources":["nodes/metrics"],"verbs":["get"]},{"nonResourceURLs":["/metrics"],"verbs":["get"]}]}
  8. creationTimestamp: "2019-12-02T03:03:44Z"
  9. name: prometheus-k8s
  10. resourceVersion: "1128592"
  11. selfLink: /apis/rbac.authorization.k8s.io/v1/clusterroles/prometheus-k8s
  12. uid: 4f87ca47-7769-432b-b96a-1b826b28003d
  13. rules:
  14. - apiGroups:
  15. - ""
  16. resources:
  17. - nodes/metrics
  18. verbs:
  19. - get
  20. - nonResourceURLs:
  21. - /metrics
  22. verbs:
  23. - get

从上面可以知道,这个clusterrole并没有service和pod的一些相关权限。接下来我们修改这个clusterrole。
prometheus-clusterRole.yaml

  1. apiVersion: rbac.authorization.k8s.io/v1
  2. kind: ClusterRole
  3. metadata:
  4. name: prometheus-k8s
  5. rules:
  6. - apiGroups:
  7. - ""
  8. resources:
  9. - nodes/metrics
  10. - configmaps
  11. verbs:
  12. - get
  13. - apiGroups:
  14. - ""
  15. resources:
  16. - nodes
  17. - pods
  18. - services
  19. - endpoints
  20. - nodes/proxy
  21. verbs:
  22. - get
  23. - list
  24. - watch
  25. - nonResourceURLs:
  26. - /metrics
  27. verbs:
  28. - get

然后我们更新这个资源清单:

  1. # kubectl apply -f prometheus-clusterRole.yaml
  2. clusterrole.rbac.authorization.k8s.io/prometheus-k8s configured

然后等待一段时间我们可以发现自动发现成功。
image.png

提示:配置自动发现,首先annotations里需要配置prometheus.io/scrape=true,其次你的应用要有exporter去收集信息,比如我们如下的redis配置:

  1. apiVersion: extensions/v1beta1
  2. kind: Deployment
  3. metadata:
  4. name: redis
  5. namespace: kube-ops
  6. spec:
  7. template:
  8. metadata:
  9. annotations:
  10. prometheus.io/scrape: "true"
  11. prometheus.io/port: "9121"
  12. labels:
  13. app: redis
  14. spec:
  15. containers:
  16. - name: redis
  17. image: redis:4
  18. resources:
  19. requests:
  20. cpu: 100m
  21. memory: 100Mi
  22. ports:
  23. - containerPort: 6379
  24. - name: redis-exporter
  25. image: oliver006/redis_exporter:latest
  26. resources:
  27. requests:
  28. cpu: 100m
  29. memory: 100Mi
  30. ports:
  31. - containerPort: 9121
  32. ---
  33. kind: Service
  34. apiVersion: v1
  35. metadata:
  36. name: redis
  37. namespace: kube-ops
  38. annotations:
  39. prometheus.io/scrape: "true"
  40. prometheus.io/port: "9121"
  41. spec:
  42. selector:
  43. app: redis
  44. ports:
  45. - name: redis
  46. port: 6379
  47. targetPort: 6379
  48. - name: prom
  49. port: 9121
  50. targetPort: 9121

4.2、数据持久化配置

如果我们直接git clone下来的,不做任何修改,Prometheus虽然使用的是statefuleSet,但是其用的存储卷是emptyDir,在删除Pod或者重建Pod,原始数据是会丢失的。所以在真实环境我们需要对其进行持久化,首先创建storageClass,如果是用NFS做持久化,详见第四章持久化存储中的storageClass部分。我们这里依然用的NFS做持久化。

创建StorageClass:
prometheus-storage.yaml

  1. apiVersion: storage.k8s.io/v1
  2. kind: StorageClass
  3. metadata:
  4. name: prometheus-storage
  5. provisioner: rookieops/nfs

其中provisioner需要指定我们在创建nfs-client-provisioner中指定的名字,不能随意修改。

配置prometheus的配置清单:
prometheus-prometheus.yaml

  1. apiVersion: monitoring.coreos.com/v1
  2. kind: Prometheus
  3. metadata:
  4. labels:
  5. prometheus: k8s
  6. name: k8s
  7. namespace: monitoring
  8. spec:
  9. alerting:
  10. alertmanagers:
  11. - name: alertmanager-main
  12. namespace: monitoring
  13. port: web
  14. storage:
  15. volumeClaimTemplate:
  16. spec:
  17. storageClassName: prometheus-storage
  18. resources:
  19. requests:
  20. storage: 20Gi
  21. baseImage: quay.io/prometheus/prometheus
  22. nodeSelector:
  23. kubernetes.io/os: linux
  24. podMonitorSelector: {}
  25. replicas: 2
  26. resources:
  27. requests:
  28. memory: 400Mi
  29. ruleSelector:
  30. matchLabels:
  31. prometheus: k8s
  32. role: alert-rules
  33. securityContext:
  34. fsGroup: 2000
  35. runAsNonRoot: true
  36. runAsUser: 1000
  37. additionalScrapeConfigs:
  38. name: additional-config
  39. key: prometheus-additional.yaml
  40. serviceAccountName: prometheus-k8s
  41. serviceMonitorNamespaceSelector: {}
  42. serviceMonitorSelector: {}
  43. version: v2.11.0

然后就可以正常使用持久化了,建议在部署之初就做更改。