01 引言
为了在Kubernetes能够方便的管理和部署Prometheus,我们使用ConfigMap管理Prometheus配置文件。
如果每次对
Prometheus配置文件进行升级时,我们需要手动移除已经运行的Pod实例,从而让Kubernetes可以使用最新的配置文件创建Prometheus,当应用实例的数量更多时,通过手动的方式部署和升级Prometheus过程繁琐并且效率低下。
问题:从本质上来讲Prometheus属于是典型的有状态应用,而其有包含了一些自身特有的运维管理和配置管理方式,而这些都无法通过Kubernetes原生提供的应用管理概念实现自动化。
解决方案:为了简化这类应用程序的管理复杂度,CoreOS率先引入了Operator的概念,并且首先推出了针对在Kubernetes下运行和管理Etcd的Etcd Operator,并随后推出了Prometheus Operator。
02 初识Prometheus Operator
2.1 什么是Prometheus Operator?
Operator:就是针对管理特定应用程序的,在Kubernetes基本的Resource和Controller的概念上,以扩展Kubernetes api的形式,帮助用户创建,配置和管理复杂的有状态应用程序,从而实现特定应用程序的常见操作以及运维自动化。
在Kubernetes中我们使用:
Deployment、DamenSet,StatefulSet来管理应用Workload;- 使用
Service,Ingress来管理应用的访问方式; - 使用
ConfigMap和Secret来管理应用配置; - 在集群中对这些资源的创建,更新,删除的动作都会被转换为事件(
Event),Kubernetes的Controller Manager负责监听这些事件并触发相应的任务来满足用户的期望。这种方式我们成为声明式,用户只需要关心应用程序的最终状态,其它的都通过Kubernetes来帮助我们完成,通过这种方式可以大大简化应用的配置管理复杂度。
实现核心点:除了这些原生的Resource资源以外,Kubernetes还允许用户添加自己的自定义资源(Custom Resource),并且通过实现自定义Controller来实现对Kubernetes的扩展。
如下所示,是Prometheus Operator的架构示意图:
上图有两个概念:
- Prometheus:本质就是一组用户自定义的
CRD资源以及Controller的实现。 - Prometheus Operator负责监听这些自定义资源的变化,并且根据这些资源的定义自动化的完成如
Prometheus Server自身以及配置的自动化管理工作。
2.2 Prometheus Operator能做什么?
要了解Prometheus Operator能做什么,其实就是要了解Prometheus Operator为我们提供了哪些自定义的Kubernetes资源,列出了Prometheus Operator目前提供的️4类资源:
- Prometheus:声明式创建和管理
Prometheus Server实例; - ServiceMonitor:负责声明式的管理监控配置;
- PrometheusRule:负责声明式的管理告警配置;
- Alertmanager:声明式的创建和管理
Alertmanager实例。
简言之,Prometheus Operator能够帮助用户自动化的创建以及管理Prometheus Server以及其相应的配置。
03 在Kubernetes集群中部署Prometheus Operator
3.1 下载
在Kubernetes中安装Prometheus Operator非常简单,用户可以从以下地址中过去Prometheus Operator的源码:
git clone https://github.com/coreos/prometheus-operator.git
3.2 配置
这里,我们为Promethues Operator创建一个单独的命名空间monitoring:
kubectl create namespace monitoring
由于需要对Prometheus Operator进行RBAC授权,而默认的bundle.yaml中使用了default命名空间,因此,在安装Prometheus Operator之前需要先替换一下bundle.yaml文件中所有namespace定义,由default修改为monitoring,通过运行以下命令安装Prometheus Operator的Deployment实例:
$ kubectl -n monitoring apply -f bundle.yaml clusterrolebinding.rbac.authorization.k8s.io/prometheus-operator created clusterrole.rbac.authorization.k8s.io/prometheus-operator created deployment.apps/prometheus-operator created serviceaccount/prometheus-operator created service/prometheus-operator created
Prometheus Operator通过Deployment的形式进行部署,目的是让Prometheus Operator能够监听和管理Kubernetes资源同时也创建了单独的ServiceAccount以及相关的授权动作。
查看Prometheus Operator部署状态,以确保已正常运行:
$ kubectl -n monitoring get pods NAME READY STATUS RESTARTS AGE prometheus-operator-6db8dbb7dd-2hz55 1/1 Running 0
04 Prometheus Operator的使用
4.1 Operator管理Prometheus
4.1.1 创建Prometheus实例
当集群中已经安装Prometheus Operator之后,对于部署Prometheus Server实例就变成了声明一个Prometheus资源,如下所示,我们在Monitoring命名空间下创建一个Prometheus实例:
apiVersion: monitoring.coreos.com/v1 kind: Prometheus metadata: name: inst namespace: monitoring spec: resources: requests: memory: 400Mi
将以上内容保存到prometheus-inst.yaml文件,并通过kubectl进行创建:
$ kubectl create -f prometheus-inst.yaml prometheus.monitoring.coreos.com/inst-1 created
此时,查看monitoring命名空间下的statefulsets资源,可以看到Prometheus Operator自动通过Statefulset创建的Prometheus实例:
$ kubectl -n monitoring get statefulsets NAME DESIRED CURRENT AGE prometheus-inst 1 1 1m
查看Pod实例:
$ kubectl -n monitoring get pods NAME READY STATUS RESTARTS AGE prometheus-inst-0 3/3 Running 1 1m prometheus-operator-6db8dbb7dd-2hz55 1/1 Running 0
通过port-forward访问Prometheus实例:
$ kubectl -n monitoring port-forward statefulsets/prometheus-inst 9090:9090
通过http://localhost:9090可以在本地直接打开Prometheus Operator创建的Prometheus实例,查看配置信息,可以看到目前Operator创建了只包含基本配置的Prometheus实例:
4.1.2 使用ServiceMonitor管理监控配置
修改监控配置项也是Prometheus下常用的运维操作之一,为了能够自动化的管理Prometheus的配置,Prometheus Operator使用了 自定义资源类型ServiceMonitor 来描述监控对象的信息。
这里我们首先在集群中部署一个示例应用,将以下内容保存到example-app.yaml,并使用kubectl命令行工具创建:
apiVersion: extensions/v1beta1 kind: Deployment metadata: name: example-app spec: replicas: 3 template: metadata: labels: app: example-app spec: containers: - name: example-app image: fabxc/instrumented_app ports: - name: web containerPort: 8080
示例应用会通过Deployment创建3个Pod实例:
$ kubectl get pods NAME READY STATUS RESTARTS AGE example-app-94c8bc8-l27vx 2/2 Running 0 1m example-app-94c8bc8-lcsrm 2/2 Running 0 1m example-app-94c8bc8-n6wp5 2/2 Running 0 1m
实例对象通过Service暴露应用访问信息
kind: Service apiVersion: v1 metadata: name: example-app labels: app: example-app spec: selector: app: example-app ports: - name: web port: 8080
在本地同样通过port-forward访问任意Pod实例:
$ kubectl port-forward deployments/example-app 8080:8080
访问本地的http://localhost:8080/metrics实例应用程序会返回以下样本数据:
# TYPE codelab_api_http_requests_in_progress gauge codelab_api_http_requests_in_progress 3 # HELP codelab_api_request_duration_seconds A histogram of the API HTTP request durations in seconds. # TYPE codelab_api_request_duration_seconds histogram codelab_api_request_duration_seconds_bucket{method="GET",path="/api/bar",status="200",le="0.0001"} 0
为了能够让
Prometheus能够采集部署在Kubernetes下应用的监控数据,在原生的Prometheus配置方式中,我们在Prometheus配置文件中定义单独的Job,同时使用kubernetes_sd定义整个服务发现过程。
而在Prometheus Operator中,则可以直接声明一个ServiceMonitor对象,如下所示:
apiVersion: monitoring.coreos.com/v1 kind: ServiceMonitor metadata: name: example-app namespace: monitoring labels: team: frontend spec: namespaceSelector: matchNames: - default selector: matchLabels: app: example-app endpoints: - port: web
通过定义selector中的标签定义选择监控目标的Pod对象,同时在endpoints中指定port名称为web的端口。默认情况下ServiceMonitor和监控对象必须是在相同Namespace下的。
在本示例中由于Prometheus是部署在Monitoring命名空间下,因此为了能够关联default命名空间下的example对象,需要使用namespaceSelector定义让其可以跨命名空间关联ServiceMonitor资源。
保存以上内容到example-app-service-monitor.yaml文件中,并通过kubectl创建:
$ kubectl create -f example-app-service-monitor.yaml servicemonitor.monitoring.coreos.com/example-app created
如果希望ServiceMonitor可以关联任意命名空间下的标签,则通过以下方式定义:
spec: namespaceSelector: any: true
如果监控的Target对象启用了BasicAuth认证,那在定义ServiceMonitor对象时,可以使用endpoints配置中定义basicAuth如下所示:
apiVersion: monitoring.coreos.com/v1 kind: ServiceMonitor metadata: name: example-app namespace: monitoring labels: team: frontend spec: namespaceSelector: matchNames: - default selector: matchLabels: app: example-app endpoints: - basicAuth: password: name: basic-auth key: password username: name: basic-auth key: user port: web
其中basicAuth中关联了名为basic-auth的Secret对象,用户需要手动将认证信息保存到Secret中:
apiVersion: v1 kind: Secret metadata: name: basic-auth data: password: dG9vcg== # base64编码后的密码 user: YWRtaW4= # base64编码后的用户名 type: Opaque

