4-Prometheus Operator原理与实践

熊 0 阅读 监控平台

1. Prometheus介绍

为了在Kubernetes中能够方便管理和部署Prometheus , 我们使用ConfigMap管理Prometheus配置文件。每次对Prometheus配置文件进行升级时 , 我们需要手动移除已经运行的Pod实例 , 从而让Kubernetes可以使用最新的配置文件创建Prometheus。而如果当应用实例的数量更多时 , 通过手动的方式部署和升级Prometheus过程繁琐并且效率低下。

从本质上来讲Prometheus属于是典型的有状态应用 , 而其有包含了一些自身特有的运维管理和配置管理方式。而这些都无法通过Kubernetes原生提供的应用管理概念实现自动化。为了简化这类应用程序的管理复杂度 , CoreOS率先引入了Operator的概念 , 并且首先推出了针对在Kubernetes下运行和管理Etcd的Etcd Operator。并随后推出了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的架构示意图 :

kubernetes-prometheus-operator-introduce-1

Prometheus的本职就是一组用户自定义的CRD资源以及Controller的实现 , Prometheus Operator负责监听这些自定义资源的变化 , 并且根据这些资源的定义自动化的完成如Prometheus Server自身以及配置的自动化管理工作。

要了解Prometheus Operator能做什么 , 其实就是要了解Prometheus Operator为我们提供了哪些自定义的Kubernetes资源 , 在最新版本的 Operator 中提供了一下几个 CRD 资源对象 :

  • Prometheus ( 和我们之前的Prometheus不一样 , 之前的Prometheus是deployment部署的应用 , 这个地方是对象 )

  • Alertmanager

  • ServiceMonitor ( 关联一些对应的service , service后面就是endpoint , 它会将具有监控服务的关联到servicemonitor这边来 , 当你去创建 , 修改 , 删除的时候 , operator就会watch到 , watch到之后就会将目标重新更新到Prometheus里面去 , 这样就可以对数据抓取 , 监控 )

  • PodMonitor ( 有些pod未必有对应的service , 比如Job和cronjob这些 , 如果你想监控job管理的pod那么你可以使用这个 )

  • Probe ( 黑盒监控 )

  • ThanosRuler

  • PrometheusRule ( 报警规则 )

  • AlertmanagerConfig

Prometheus

该 CRD 声明定义了 Prometheus 期望在 Kubernetes 集群中运行的配置 , 提供了配置选项来配置副本、持久化、报警实例等。

对于每个 Prometheus CRD 资源 , Operator 都会以 StatefulSet 形式在相同的命名空间下部署对应配置的资源 , Prometheus Pod 的配置是通过一个包含 Prometheus 配置的名为 <prometheus-name> 的 Secret 对象声明挂载的。 ( 它的配置是以secret形式自动生成挂载进去的 ) 。

该 CRD 根据标签选择来指定部署的 Prometheus 实例应该覆盖哪些 ServiceMonitors ( 能够监听哪些servicemonitor ) , 然后 Operator 会根据包含的 ServiceMonitors 生成配置 , 并在包含配置的 Secret 中进行更新。 ( 如果没有生效 , 那么很有可能Prometheus没有和servicemonitor关联上 ) 。

如果未提供对 ServiceMonitor 的选择 , 则 Operator 会将 Secret 的管理留给用户 , 这样就可以提供自定义配置 , 同时还能享受 Operator 管理 Operator 的设置能力。

Alertmanager

该 CRD 定义了在 Kubernetes 集群中运行的 Alertmanager 的配置 , 同样提供了多种配置 , 包括持久化存储。

对于每个 Alertmanager 资源 , Operator 都会在相同的命名空间中部署一个对应配置的 StatefulSet , Alertmanager Pods 被配置为包含一个名为 <alertmanager-name> 的 Secret , 该 Secret 以 alertmanager.yaml 为 key 的方式保存使用的配置文件。

当有两个或更多配置的副本时 , Operator 会在高可用模式下运行 Alertmanager 实例。

ThanosRuler

该 CRD 定义了一个 Thanos Ruler 组件的配置 , 以方便在 Kubernetes 集群中运行。通过 Thanos Ruler , 可以跨多个 Prometheus 实例处理记录和警报规则。

一个 ThanosRuler 实例至少需要一个 queryEndpoint , 它指向 Thanos Queriers 或 Prometheus 实例的位置。queryEndpoints 用于配置 Thanos 运行时的 --query 参数 , 更多信息也可以在 Thanos 文档中找到。

ServiceMonitor

该 CRD 定义了如何监控一组动态的服务 , 使用标签选择来定义哪些 Service 被选择进行监控。这可以让团队制定一个如何暴露监控指标的规范 , 然后按照这些规范自动发现新的服务 , 而无需重新配置。

为了让 Prometheus 监控 Kubernetes 内的任何应用 , 需要存在一个 Endpoints 对象 , Endpoints 对象本质上是 IP 地址的列表 , 通常 Endpoints 对象是由 Service 对象来自动填充的 , Service 对象通过标签选择器匹配 Pod , 并将其添加到 Endpoints 对象中。一个 Service 可以暴露一个或多个端口 , 这些端口由多个 Endpoints 列表支持 , 这些端点一般情况下都是指向一个 Pod。

Prometheus Operator 引入的这个 ServiceMonitor 对象就会发现这些 Endpoints 对象 , 并配置 Prometheus 监控这些 Pod。ServiceMonitorSpec 的 endpoints 部分就是用于配置这些 Endpoints 的哪些端口将被 scrape 指标的。

注意 : endpoints ( 小写 ) 是 ServiceMonitor CRD 中的字段 , 而 Endpoints ( 大写 ) 是 Kubernetes 的一种对象。

ServiceMonitors 以及被发现的目标都可以来自任何命名空间 , 这对于允许跨命名空间监控的场景非常重要。使用 PrometheusSpec 的 ServiceMonitorNamespaceSelector , 可以限制各自的 Prometheus 服务器选择的 ServiceMonitors 的命名空间。使用 ServiceMonitorSpec 的 namespaceSelector , 可以限制 Endpoints 对象被允许从哪些命名空间中发现 , 要在所有命名空间中发现目标 , namespaceSelector 必须为空 :

spec:  namespaceSelector:    any: true

PodMonitor

该 CRD 用于定义如何监控一组动态 pods , 使用标签选择来定义哪些 pods 被选择进行监控。同样团队中可以制定一些规范来暴露监控的指标。

Pod 是一个或多个容器的集合 , 可以在一些端口上暴露 Prometheus 指标。由 Prometheus Operator 引入的 PodMonitor 对象会发现这些 Pod , 并为 Prometheus 服务器生成相关配置 , 以便监控它们。

PodMonitorSpec 中的 PodMetricsEndpoints 部分 , 用于配置 Pod 的哪些端口将被 scrape 指标 , 以及使用哪些参数。

PodMonitors 和发现的目标可以来自任何命名空间 , 这同样对于允许跨命名空间的监控用例是很重要的。使用 PodMonitorSpec 的 namespaceSelector , 可以限制 Pod 被允许发现的命名空间 , 要在所有命名空间中发现目标 , namespaceSelector 必须为空 :

spec:  namespaceSelector:    any: true

PodMonitor 和 ServieMonitor 最大的区别就是不需要有对应的 Service。

Probe

该 CRD 用于定义如何监控一组 Ingress 和静态目标。除了 target 之外 , Probe 对象还需要一个 prober , 它是监控的目标并为 Prometheus 提供指标的服务。例如可以通过使用 blackbox-exporter来提供这个服务。

PrometheusRule

用于配置 Prometheus 的 Rule 规则文件 , 包括 recording rules 和 alerting , 可以自动被 Prometheus 加载。 ( 以前我们创建了之后 , 需要重新加载Prometheus , 现在直接使用这个对象就可以 )

AlertmanagerConfig

在以前的版本中要配置 Alertmanager 都是通过 Configmap 来完成的 , 在 v0.43 版本后新增该 CRD , 可以将 Alertmanager 的配置分割成不同的子对象进行配置 , 允许将报警路由到自定义 Receiver 上 , 并配置抑制规则。

AlertmanagerConfig 可以在命名空间级别上定义 , 为 Alertmanager 提供一个聚合的配置。不过需要注意这个 CRD 还不稳定。

这样我们要在集群中监控什么数据 , 就变成了直接去操作 Kubernetes 集群的资源对象了 , 是这样比之前手动的方式就方便很多了。 ( 之前都是去管理configmap , 管理我们配置 , 现在直接管理我们的crd对象 )

简言之 , Prometheus Operator 能够帮助用户自动化的创建以及管理Prometheus Server以及其相应的配置。

2. 部署Prometheus Operator

以下步骤均在k8s的master节点操作

在Kubernetes中安装Prometheus Operator非常简单 , 用户可以从以下地址中过去Prometheus Operator的源码 :

git clone https://github.com/prometheus-operator/prometheus-operator.git

这里 , 我们为Promethues Operator创建一个单独的命名空间monitoring :

kubectl create namespace monitoring

由于需要对Prometheus Operator进行RBAC授权 , 而默认的bundle.yaml中使用了default命名空间 , 因此 , 在安装Prometheus Operator之前需要先替换一下bundle.yaml文件中所有namespace定义 , 由default修改为monitoring。通过运行一下命令安装Prometheus Operator的Deployment实例 :

cd prometheus-operator/
sed -i.bak -E  's/(namespace: )default/\1monitoring/' bundle.yaml 
kubectl create -f bundle.yaml

这里如果使用kubectl apply -f bundle.yaml时, 可能会出现如下错误, 这里直接替换为上面命令中的kubectl create -f bundle.yaml即可

Error from server (Invalid): error when creating "bundle.yaml": CustomResourceDefinition.apiextensions.k8s.io "alertmanagers.monitoring.coreos.com" is invalid: metadata.annotations: Too long: must have at most 262144 bytes
Error from server (Invalid): error when creating "bundle.yaml": CustomResourceDefinition.apiextensions.k8s.io "prometheusagents.monitoring.coreos.com" is invalid: metadata.annotations: Too long: must have at most 262144 bytes
Error from server (Invalid): error when creating "bundle.yaml": CustomResourceDefinition.apiextensions.k8s.io "prometheuses.monitoring.coreos.com" is invalid: metadata.annotations: Too long: must have at most 262144 bytes
Error from server (Invalid): error when creating "bundle.yaml": CustomResourceDefinition.apiextensions.k8s.io "thanosrulers.monitoring.coreos.com" is invalid: metadata.annotations: Too long: must have at most 262144 bytes
​

使用以下命令查看

root@k8s-master01:/opt/k8s-data/yaml/cbear/promethues/prometheus-operator/prometheus-operator# kubectl get pods -n monitoring 
NAME                                   READY   STATUS    RESTARTS   AGE
prometheus-operator-69cbc6f76c-qfgkw   1/1     Running   0          12s
root@k8s-master01:/opt/k8s-data/yaml/cbear/promethues/prometheus-operator/prometheus-operator# kubectl get all -n monitoring 
NAME                                       READY   STATUS    RESTARTS   AGE
pod/prometheus-operator-69cbc6f76c-qfgkw   1/1     Running   0          5m31s
​
NAME                          TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)    AGE
service/prometheus-operator   ClusterIP   None         <none>        8080/TCP   5m31s
​
NAME                                  READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/prometheus-operator   1/1     1            1           5m31s
​
NAME                                             DESIRED   CURRENT   READY   AGE
replicaset.apps/prometheus-operator-69cbc6f76c   1         1         1       5m31s
​

可以看到prometheus-operator就部署成功了。

3.创建Prometheus实例

当集群中已经安装Prometheus Operator之后 , 对于部署Prometheus Server实例就变成了声明一个Prometheus资源 , 如下所示 , 我们在Monitoring命名空间下创建一个Prometheus实例 :

root@k8s-master01:/opt/k8s-data/yaml/cbear/promethues/prometheus-operator/prometheus-operator# cat prometheus-inst.yaml 
apiVersion: monitoring.coreos.com/v1
kind: Prometheus
metadata:
  name: inst
  namespace: monitoring
spec:
  resources:
    requests:
      memory: 400Mi

将以上内容保存到prometheus-inst.yaml文件 , 并通过kubectl进行创建 :

root@k8s-master01:/opt/k8s-data/yaml/cbear/promethues/prometheus-operator/prometheus-operator# kubectl apply -f prometheus-inst.yaml 
prometheus.monitoring.coreos.com/inst created

此时 , 查看monitoring命名空间下的statefulsets资源 , 可以看到Prometheus Operator自动通过Statefulset创建的Prometheus实例 :

root@k8s-master01:/opt/k8s-data/yaml/cbear/promethues/prometheus-operator/prometheus-operator# kubectl -n monitoring get statefulset
NAME              READY   AGE
prometheus-inst   1/1     3m27s

查看pod实例 :

root@k8s-master01:/opt/k8s-data/yaml/cbear/promethues/prometheus-operator/prometheus-operator# kubectl -n monitoring get pods 
NAME                                   READY   STATUS    RESTARTS   AGE
prometheus-inst-0                      2/2     Running   0          4m9s
prometheus-operator-69cbc6f76c-qfgkw   1/1     Running   0          13m

为prometheus实例创建service , 以便在浏览器访问 : cat prometheus-service.yaml

root@k8s-master01:/opt/k8s-data/yaml/cbear/promethues/prometheus-operator/prometheus-operator# cat prometheus-service.yaml 
apiVersion: v1
kind: Service
metadata:
  labels:
    app: prometheus-operator
  name: prometheus-operator-svc
  namespace: monitoring
spec:
  ports:
  - name: operator
    port: 9090
    protocol: TCP
    targetPort: 9090
  selector:
    prometheus: inst
  sessionAffinity: None
  type: NodePort

更新yaml文件 :

kubectl apply -f prometheus-service.yaml

查看service详细信息 :

root@k8s-master01:/opt/k8s-data/yaml/cbear/promethues/prometheus-operator/prometheus-operator# kubectl get svc -n monitoring 
NAME                      TYPE        CLUSTER-IP    EXTERNAL-IP   PORT(S)          AGE
prometheus-operated       ClusterIP   None          <none>        9090/TCP         20m
prometheus-operator       ClusterIP   None          <none>        8080/TCP         29m
prometheus-operator-svc   NodePort    10.68.38.46   <none>        9090:32714/TCP   4m55s

看到最后一行prometheus-operator-svc的type类型是NodePort , 在宿主机暴露的端口是32714 , 我们通过浏览器访问k8s的master ip:32714即可访问到prometheus ui界面 , 我这里k8s的master节点ip是192.168.71.35 , 所以在浏览器访问http://192.168.71.35:32714/config , 可以看到目前Operator创建了只包含基本配置的Prometheus实例 :

image-20240624184217848

参考链接

构建企业级监控平台系列(十四) : Prometheus Operator 原理与实践 (qq.com)