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

2023-10-23 20:00:06 浏览数 (3)

什么是Prometheus Operator?

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

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

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

Prometheus Operator能做什么?

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

代码语言:javascript复制
spec:  namespaceSelector:    any: true

更多关于企业级监控平台系列的学习文章,请参阅:构建企业级监控平台,本系列持续更新中。

PodMonitor

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

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

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

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

代码语言:javascript复制
spec:  namespaceSelector:    any: true

PodMonitorServieMonitor 最大的区别就是不需要有对应的 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以及其相应的配置。

在k8s集群中部署Prometheus Operator

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

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

代码语言:javascript复制
git clone https://github.com/coreos/prometheus-operator.git

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

代码语言:javascript复制
kubectl create namespace monitoring

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

代码语言:javascript复制
cd prometheus-operator/
 
kubectl -n monitoring apply -f bundle.yaml

注:如果报错ImagePullBackOff,表示不能拉取prometheus-operator镜像,可以把prometheus-operator.tar.gz压缩包上传到k8s的node节点,手动解压即可。

代码语言:javascript复制
docker load -i prometheus-operator.tar.gz

然后再执行如下即可

代码语言:javascript复制
kubectl -n monitoring delete -f bundle.yaml
kubectl -n monitoring apply -f bundle.yaml
[root@master prometheus-operator]# kubectl -n monitoring apply -f bundle.yaml
customresourcedefinition.apiextensions.k8s.io/alertmanagers.monitoring.coreos.com configured
customresourcedefinition.apiextensions.k8s.io/podmonitors.monitoring.coreos.com configured
customresourcedefinition.apiextensions.k8s.io/prometheuses.monitoring.coreos.com created
customresourcedefinition.apiextensions.k8s.io/prometheusrules.monitoring.coreos.com configured
customresourcedefinition.apiextensions.k8s.io/servicemonitors.monitoring.coreos.com configured
customresourcedefinition.apiextensions.k8s.io/thanosrulers.monitoring.coreos.com configured
clusterrolebinding.rbac.authorization.k8s.io/prometheus-operator configured
clusterrole.rbac.authorization.k8s.io/prometheus-operator configured
deployment.apps/prometheus-operator created
serviceaccount/prometheus-operator created
service/prometheus-operator created
代码语言:javascript复制
[root@master prometheus-operator]# kubectl get pod -n monitoring
NAME                                   READY   STATUS    RESTARTS   AGE
prometheus-operator-7d6496d74b-vrjcj   1/1     Running   0          48s

可以看到prometheus-operator就部署成功了。更多关于企业级监控平台系列的学习文章,请参阅:构建企业级监控平台,本系列持续更新中。

创建Prometheus实例

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

代码语言:javascript复制
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进行创建:

代码语言:javascript复制
kubectl apply -f  prometheus-inst.yaml

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

代码语言:javascript复制
kubectl -n monitoring get statefulset

显示如下,说明部署成功了:

代码语言:javascript复制
NAME              READY   AGE
prometheus-inst   1/1     56s      50m

查看pod实例:

代码语言:javascript复制
kubectl -n monitoring get pods

显示如下,说明部署成功了:

代码语言:javascript复制
NAME                                   READY   STATUS    RESTARTS   AGE
prometheus-inst-0                      3/3     Running   1          2m
prometheus-operator-5974fc7c56-7zr88   1/1     Running   0          50m

注:如果报错ErrImagePull,表示不能拉取prometheus镜像,可以把镜像压缩包prometheus-v2_17_2.tar.gz、prometheus-config-reloader_v0_39_0.tar.gz、configmap-reload_v0_3_0.tar.gz上传到k8s的node节点,手动解压:

代码语言:javascript复制
docker load -i prometheus-v2_17_2.tar.gz
docker load -i prometheus-config-reloader_v0_39_0.tar.gz 
docker load -i configmap-reload_v0_3_0.tar.gz

然后再执行如下即可

代码语言:javascript复制
kubectl delete  -f  prometheus-inst.yaml
 
kubectl apply  -f  prometheus-inst.yaml

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

代码语言:javascript复制
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:
    app: prometheus
    prometheus: inst
  sessionAffinity: None
  type: NodePort

更新yaml文件:

代码语言:javascript复制
kubectl apply -f prometheus-service.yaml

查看service详细信息:

代码语言:javascript复制
kubectl get svc -n monitoring

显示如下:

代码语言:javascript复制
NAME                      TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)          AGE
prometheus-operated       ClusterIP   None            <none>        9090/TCP         77m
prometheus-operator       ClusterIP   None            <none>        8080/TCP         126m
prometheus-operator-svc   NodePort    10.108.151.60   <none>        9090:31535/TCP   35s

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

自己测试
代码语言:javascript复制
[root@master prometheus-operator]# kubectl get Prometheus -n monitoring
NAME   VERSION   REPLICAS   AGE
k8s                         13h
 
[root@master prometheus-operator]# kubectl describe  servicemonitor example-app  -n monitoring
Name:         example-app
Namespace:    monitoring
Labels:       team=frontend
Annotations:  <none>
API Version:  monitoring.coreos.com/v1
Kind:         ServiceMonitor
Metadata:
  Creation Timestamp:  2022-01-05T02:32:51Z
  Generation:          1
  Managed Fields:
    API Version:  monitoring.coreos.com/v1
    Fields Type:  FieldsV1
    fieldsV1:
      f:metadata:
        f:annotations:
          .:
          f:kubectl.kubernetes.io/last-applied-configuration:
        f:labels:
          .:
          f:team:
      f:spec:
        .:
        f:endpoints:
        f:namespaceSelector:
          .:
          f:matchNames:
        f:selector:
          .:
          f:matchLabels:
            .:
            f:app:
    Manager:         kubectl-client-side-apply
    Operation:       Update
    Time:            2022-01-05T02:32:51Z
  Resource Version:  521996
  Self Link:         /apis/monitoring.coreos.com/v1/namespaces/monitoring/servicemonitors/example-app
  UID:               cc1460d4-e720-4c47-8258-8f5d4a72bcd1
Spec:
  Endpoints:
    Port:  web
  Namespace Selector:
    Match Names:
      default
  Selector:
    Match Labels:
      App:  example-app
Events:     <none>

更多关于企业级监控平台系列的学习文章,请参阅:构建企业级监控平台,本系列持续更新中。

参考链接:https://blog.csdn.net/qq_34556414/ article/details/122266132 https://blog.csdn.net/ qq_34556414/article/details/125763346

0 人点赞