4.1.3 关联Promethues与ServiceMonitor
为了能够让Prometheus
关联到ServiceMonitor
,需要在Pormtheus
定义中使用serviceMonitorSelector
,我们可以通过标签选择当前Prometheus
需要监控的ServiceMonitor
对象,修改prometheus-inst.yaml
中Prometheus
的定义如下所示:
apiVersion: monitoring.coreos.com/v1 kind: Prometheus metadata: name: inst namespace: monitoring spec: serviceMonitorSelector: matchLabels: team: frontend resources: requests: memory: 400Mi
将对Prometheus
的变更应用到集群中:
$ kubectl -n monitoring apply -f prometheus-inst.yaml
此时,如果查看Prometheus
配置信息,我们会惊喜的发现Prometheus
中配置文件自动包含了一条名为monitoring/example-app/0
的Job
配置:
global: scrape_interval: 30s scrape_timeout: 10s evaluation_interval: 30s external_labels: prometheus: monitoring/inst prometheus_replica: prometheus-inst-0 alerting: alert_relabel_configs: - separator: ; regex: prometheus_replica replacement: $1 action: labeldrop rule_files: - /etc/prometheus/rules/prometheus-inst-rulefiles-0/*.yaml scrape_configs: - job_name: monitoring/example-app/0 scrape_interval: 30s scrape_timeout: 10s metrics_path: /metrics scheme: http kubernetes_sd_configs: - role: endpoints namespaces: names: - default relabel_configs: - source_labels: [__meta_kubernetes_service_label_app] separator: ; regex: example-app replacement: $1 action: keep - source_labels: [__meta_kubernetes_endpoint_port_name] separator: ; regex: web replacement: $1 action: keep - source_labels: [__meta_kubernetes_endpoint_address_target_kind, __meta_kubernetes_endpoint_address_target_name] separator: ; regex: Node;(.*) target_label: node replacement: ${1} action: replace - source_labels: [__meta_kubernetes_endpoint_address_target_kind, __meta_kubernetes_endpoint_address_target_name] separator: ; regex: Pod;(.*) target_label: pod replacement: ${1} action: replace - source_labels: [__meta_kubernetes_namespace] separator: ; regex: (.*) target_label: namespace replacement: $1 action: replace - source_labels: [__meta_kubernetes_service_name] separator: ; regex: (.*) target_label: service replacement: $1 action: replace - source_labels: [__meta_kubernetes_pod_name] separator: ; regex: (.*) target_label: pod replacement: $1 action: replace - source_labels: [__meta_kubernetes_service_name] separator: ; regex: (.*) target_label: job replacement: ${1} action: replace - separator: ; regex: (.*) target_label: endpoint replacement: web action: replace
不过,如果细心的读者可能会发现,虽然Job
配置有了,但是Prometheus
的Target
中并没包含任何的监控对象。查看Prometheus
的Pod
实例日志,可以看到如下信息:
level=error ts=2018-12-15T12:52:48.452108433Z caller=main.go:240 component=k8s_client_runtime err="github.com/prometheus/prometheus/discovery/kubernetes/kubernetes.go:300: Failed to list *v1.Endpoints: endpoints is forbidden: User \"system:serviceaccount:monitoring:default\" cannot list endpoints in the namespace \"default\""
4.1.4 自定义ServiceAccount
由于默认创建的Prometheus
实例使用的是monitoring
命名空间下的default
账号,该账号并没有权限能够获取default
命名空间下的任何资源信息。
为了修复这个问题,我们需要在Monitoring
命名空间下为创建一个名为Prometheus
的ServiceAccount
,并且为该账号赋予相应的集群访问权限。
apiVersion: v1 kind: ServiceAccount metadata: name: prometheus namespace: monitoring --- apiVersion: rbac.authorization.k8s.io/v1beta1 kind: ClusterRole metadata: name: prometheus rules: - apiGroups: [""] resources: - nodes - services - endpoints - pods verbs: ["get", "list", "watch"] - apiGroups: [""] resources: - configmaps verbs: ["get"] - nonResourceURLs: ["/metrics"] verbs: ["get"] --- apiVersion: rbac.authorization.k8s.io/v1beta1 kind: ClusterRoleBinding metadata: name: prometheus roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: prometheus subjects: - kind: ServiceAccount name: prometheus namespace: monitoring
将以上内容保存到prometheus-rbac.yaml
文件中,并且通过kubectl
创建相应资源:
$ kubectl -n monitoring create -f prometheus-rbac.yaml serviceaccount/prometheus created clusterrole.rbac.authorization.k8s.io/prometheus created clusterrolebinding.rbac.authorization.k8s.io/prometheus created
在完成ServiceAccount
创建后,修改prometheus-inst.yaml
,并添加ServiceAccount
如下所示:
apiVersion: monitoring.coreos.com/v1 kind: Prometheus metadata: name: inst namespace: monitoring spec: serviceAccountName: prometheus serviceMonitorSelector: matchLabels: team: frontend resources: requests: memory: 400Mi
保存Prometheus
变更到集群中:
$ kubectl -n monitoring apply -f prometheus-inst.yaml prometheus.monitoring.coreos.com/inst configured
等待Prometheus Operator
完成相关配置变更后,此时查看Prometheus
,我们就能看到当前Prometheus
已经能够正常的采集实例应用的相关监控数据了。
4.2 Operator管理监控配置
4.2.1 使用Prometheus Rule定义告警规则
对于
Prometheus
而言,在原生的管理方式上,我们需要手动创建Prometheus
的告警文件,并且通过在Prometheus
配置中声明式的加载。
而在Prometheus Operator
模式中,告警规则也编程一个通过Kubernetes API
声明式创建的一个资源,如下所示:
apiVersion: monitoring.coreos.com/v1 kind: PrometheusRule metadata: labels: prometheus: example role: alert-rules name: prometheus-example-rules spec: groups: - name: ./example.rules rules: - alert: ExampleAlert expr: vector(1)
将以上内容保存为example-rule.yaml
文件,并且通过kubectl
命令创建相应的资源:
$ kubectl -n monitoring create -f example-rule.yaml prometheusrule "prometheus-example-rules" created
告警规则创建成功后,通过在Prometheus
中使用ruleSelector
通过选择需要关联的PrometheusRule
即可:
apiVersion: monitoring.coreos.com/v1 kind: Prometheus metadata: name: inst namespace: monitoring spec: serviceAccountName: prometheus serviceMonitorSelector: matchLabels: team: frontend ruleSelector: matchLabels: role: alert-rules prometheus: example resources: requests: memory: 400Mi
Prometheus
重新加载配置后,从UI
中我们可以查看到通过PrometheusRule
自动创建的告警规则配置:
如果查看Alerts
页面,我们会看到告警已经处于触发状态。
4.2.2 使用Operator管理Alertmanager实例
到目前为止,我们已经通过Prometheus Operator
的自定义资源类型管理了Promtheus
的实例,监控配置以及告警规则等资源;通过Prometheus Operator
将原本手动管理的工作全部变成声明式的管理模式,大大简化了Kubernetes
下的Prometheus
运维管理的复杂度。
接下来,我们将继续使用Promtheus Operator
定义和管理Alertmanager
相关的内容。为了通过Prometheus Operator
管理Alertmanager
实例,用户可以通过自定义资源Alertmanager
进行定义,如下所示,通过replicas
可以控制Alertmanager
的实例数:
apiVersion: monitoring.coreos.com/v1 kind: Alertmanager metadata: name: inst namespace: monitoring spec: replicas: 3
当replicas
大于1时,Prometheus Operator
会自动通过集群的方式创建Alertmanager
。将以上内容保存为文件alertmanager-inst.yaml
,并通过以下命令创建:
$ kubectl -n monitoring create -f alertmanager-inst.yaml alertmanager.monitoring.coreos.com/inst created
查看Pod的情况如下所示,我们会发现Alertmanager
的Pod
实例一直处于ContainerCreating
的状态中:
$ kubectl -n monitoring get pods NAME READY STATUS RESTARTS AGE alertmanager-inst-0 0/2 ContainerCreating 0 32s
通过kubectl describe
命令查看该Alertmanager
的Pod
实例状态,可以看到类似于以下内容的告警信息:
MountVolume.SetUp failed for volume "config-volume" : secrets "alertmanager-inst" not found
这是由于Prometheus Operator
通过Statefulset
的方式创建的Alertmanager
实例,在默认情况下,会通过alertmanager-{ALERTMANAGER_NAME}
的命名规则去查找Secret
配置并以文件挂载的方式,将Secret
的内容作为配置文件挂载到Alertmanager
实例当中。
因此,这里还需要为Alertmanager
创建相应的配置内容,如下所示,是Alertmanager
的配置文件:
global: resolve_timeout: 5m route: group_by: ['job'] group_wait: 30s group_interval: 5m repeat_interval: 12h receiver: 'webhook' receivers: - name: 'webhook' webhook_configs: - url: 'http://alertmanagerwh:30500/'
将以上内容保存为文件alertmanager.yaml
,并且通过以下命令创建名为alrtmanager-inst
的Secret
资源:
$ kubectl -n monitoring create secret generic alertmanager-inst --from-file=alertmanager.yaml secret/alertmanager-inst created
在Secret
创建成功后,查看当前Alertmanager Pod
实例状态。如下所示:
$ kubectl -n monitoring get pods NAME READY STATUS RESTARTS AGE alertmanager-inst-0 2/2 Running 0 5m alertmanager-inst-1 2/2 Running 0 52s alertmanager-inst-2 2/2 Running 0
使用port-forward
将Alertmanager
映射到本地:
$ kubectl -n monitoring port-forward statefulsets/alertmanager-inst 9093:9093
访问http://localhost:9093/#/status,并查看当前集群状态:
接下来,我们只需要修改我们的Prometheus
资源定义,通过alerting
指定使用的Alertmanager
资源即可:
apiVersion: monitoring.coreos.com/v1 kind: Prometheus metadata: name: inst namespace: monitoring spec: serviceAccountName: prometheus serviceMonitorSelector: matchLabels: team: frontend ruleSelector: matchLabels: role: alert-rules prometheus: example alerting: alertmanagers: - name: alertmanager-example namespace: monitoring port: web resources: requests: memory: 400Mi
等待Prometheus
重新加载后,我们可以看到Prometheus Operator
在配置文件中添加了以下配置:
alertmanagers: - kubernetes_sd_configs: - role: endpoints namespaces: names: - monitoring scheme: http path_prefix: / timeout: 10s relabel_configs: - source_labels: [__meta_kubernetes_service_name] separator: ; regex: alertmanager-example replacement: $1 action: keep - source_labels: [__meta_kubernetes_endpoint_port_name] separator: ; regex: web replacement: $1 action: keep
通过服务发现规则将Prometheus
与Alertmanager
进行了自动关联。
4.3 在Operator中使用自定义配置
在Prometheus Operator
我们通过声明式的创建如Prometheus, ServiceMonitor
这些自定义的资源类型来自动化部署和管理Prometheus
的相关组件以及配置。
而在一些特殊的情况下,对于用户而言,可能还是希望能够手动管理Prometheus
配置文件,而非通过Prometheus Operator
自动完成。 为什么?
- 实际上
Prometheus Operator
对于Job
的配置只适用于在Kubernetes
中部署和管理的应用程序。如果你希望使用Prometheus
监控一些其他的资源,例如AWS
或者其他平台中的基础设施或者应用,这些并不在Prometheus Operator
的能力范围之内。
为了能够在通过Prometheus Operator
创建的Prometheus
实例中使用自定义配置文件,我们只能创建一个不包含任何与配置文件内容相关的Prometheus
实例:
apiVersion: monitoring.coreos.com/v1 kind: Prometheus metadata: name: inst-cc namespace: monitoring spec: serviceAccountName: prometheus resources: requests: memory: 400Mi
将以上内容保存到prometheus-inst-cc.yaml
文件中,并且通过kubectl
创建:
$ kubectl -n monitoring create -f prometheus-inst-cc.yaml prometheus.monitoring.coreos.com/inst-cc created
如果查看新建Prometheus
的Pod
实例YAML
定义,我们可以看到Pod
中会包含一个volume
配置:
volumes: - name: config secret: defaultMode: 420 secretName: prometheus-inst-cc
Prometheus
的配置文件实际上是保存在名为prometheus-<name-of-prometheus-object>
的Secret
中,当用户创建的Prometheus
中关联ServiceMonitor
这类会影响配置文件内容的定义时,Promethues Operator
会自动管理。
而如果Prometheus
定义中不包含任何与配置相关的定义,那么Secret
的管理权限就落到了用户自己手中。通过修改prometheus-inst-cc
的内容,从而可以让用户可以使用自定义的Prometheus
配置文件,作为示例,我们创建一个prometheus.yaml
文件并添加以下内容:
global: scrape_interval: 10s scrape_timeout: 10s evaluation_interval: 10s
生成文件内容的base64
编码后的内容:
$ cat prometheus.yaml | base64 Z2xvYmFsOgogIHNjcmFwZV9pbnRlcnZhbDogMTBzCiAgc2NyYXBlX3RpbWVvdXQ6IDEwcwogIGV2YWx1YXRpb25faW50ZXJ2YWw6IDEwcw==
修改名为prometheus-inst-cc
的Secret
内容,如下所示:
$ kubectl -n monitoring edit secret prometheus-inst-cc # 省略其它内容 data: prometheus.yaml: "Z2xvYmFsOgogIHNjcmFwZV9pbnRlcnZhbDogMTBzCiAgc2NyYXBlX3RpbWVvdXQ6IDEwcwogIGV2YWx1YXRpb25faW50ZXJ2YWw6IDEwcw=="
通过port-forward
在本地访问新建的Prometheus
实例,观察配置文件变化即可:
kubectl -n monitoring port-forward statefulsets/prometheus-inst-cc 9091:9090
05 文末
本文主要讲解了在Kubernetes
下如何使用Operator
来有状态的运维和管理Prometheus
以及Alertmanager
等组件,希望能对大家有所启发,谢谢大家的阅读。
参考文献:https://yunlzheng.gitbook.io/prometheus-book/part-iii-prometheus-shi-zhan/operator/what-is-prometheus-operator