在 Kubernetes 中管理 Prometheus:从静态配置到动态操作

清理测试环境

测试完成后,确保你处于 chapter05/ 路径下,执行以下命令清理环境:

vagrant destroy -f

不用担心,若后续需要,你可以轻松重新启动环境。

Kubernetes 中 Prometheus 的管理背景

Kubernetes 是首个从云原生计算基金会(CNCF)毕业的项目,目前已成为容器编排的事实标准。早期,Heapster 作为 Kubernetes 自带的监控解决方案被广泛使用,它最初是将监控数据发送到外部系统的工具,后来逐渐发展成为一个监控系统。然而,不久之后,Prometheus 成为了 Kubernetes 集群的事实标准监控系统。如今,构成 Kubernetes 集群的大多数组件都具有原生的 Prometheus 检测功能。

集成所需准备

要在 Kubernetes 环境中集成 Prometheus,可参考 Kubernetes 项目和 Prometheus Operator 项目的示例。你可以在以下地址分别找到这两个项目的完整源代码:
- Kubernetes 项目:https://github.com/kubernetes/kubernetes
- Prometheus Operator 项目:https://github.com/coreos/prometheus-operator

同时,要确保你拥有在测试环境设置中定义的所有软件,且版本符合要求,特别是以下软件:
- Minikube
- kubectl

静态配置 Prometheus

虽然静态配置方法不太推荐,但它有助于我们更好地理解和排查在 Kubernetes 中运行的 Prometheus 服务器的问题。以下是使用 ConfigMap 定义服务器配置来创建 Prometheus 部署的详细步骤:

搭建 Kubernetes 环境
  1. 确保没有正在运行的 Minikube 实例,依次执行以下命令:
minikube status
minikube delete

注意, minikube delete 是一个具有破坏性的指令,执行前请确保保存好工作。
2. 启动一个新的 Minikube 实例,使用以下配置:

minikube start \
  --cpus=2 \
  --memory=2048 \
  --kubernetes-version="v1.14.0" \
  --vm-driver=virtualbox
  1. 启动完成后,可通过以下命令打开 Kubernetes 仪表盘:
minikube dashboard
  1. 进入正确的仓库路径:
cd chapter05/provision/kubernetes/static
  1. 使用以下命令创建一个名为 monitoring 的新命名空间:
apiVersion: v1
kind: Namespace
metadata:
  name: monitoring
kubectl apply -f monitoring-namespace.yaml

你可以在 Kubernetes 仪表盘上验证命名空间是否创建成功。

部署 Prometheus 服务器
  1. 创建一个简单的 Prometheus 配置,并将其保存到 ConfigMap 中:
apiVersion: v1
kind: ConfigMap
metadata:
  name: prometheus-config
  namespace: monitoring 
data:
  prometheus.yml: |
    scrape_configs:
    - job_name: prometheus
      static_configs:
      - targets:
        - localhost:9090
kubectl apply -f prometheus-configmap.yaml
  1. 启动一个新的 Prometheus 部署,将之前配置的 ConfigMap 挂载到部署的 Pod 中:
apiVersion: apps/v1
kind: Deployment
metadata:
  name: prometheus-deployment
  namespace: monitoring
  labels:
    app: prometheus
spec:
  template:
    spec:
      containers:
      - name: prometheus
        args:
          - --config.file=/etc/config/prometheus.yml
          - --storage.tsdb.path=/data
        volumeMounts:
          - name: config-volume
            mountPath: /etc/config/prometheus.yml
            subPath: prometheus.yml
          - name: prometheus-data
            mountPath: /data
            subPath: ""
      volumes:
        - name: config-volume
          configMap:
            name: prometheus-config
        - name: prometheus-data
          emptyDir: {}
kubectl apply -f prometheus-deployment.yaml
  1. 查看部署状态:
kubectl rollout status deployment/prometheus-deployment -n monitoring
  1. 查看 Prometheus 实例的日志:
kubectl logs --tail=20 -n monitoring -l app=prometheus
  1. 部署成功后,为 Prometheus 实例分配一个新的服务,选择 NodePort 类型以便无需端口转发即可访问:
kind: Service
apiVersion: v1
metadata:
  name: prometheus-service
  namespace: monitoring
spec:
  selector:
    app: prometheus
  type: NodePort
  ports:
  - name: prometheus-port
    protocol: TCP
    port: 9090
    targetPort: 9090
kubectl apply -f prometheus-service.yaml
  1. 检查新的 Prometheus 服务:
minikube service prometheus-service -n monitoring

这将在浏览器中打开 Prometheus 服务端点,你可以通过 Prometheus 网页界面查看运行配置和目标。

为 Prometheus 添加目标

为了演示,我们将部署另一个名为 Hey 的服务,并将其添加到 Prometheus 服务器中:
1. 创建一个新的 Hey 部署:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: hey-deployment
  namespace: monitoring
  labels:
    app: hey
spec:
  template:
    spec:
      containers:
      - name: hey
        image: kintoandar/hey:v1.0.1
        ports:
        - name: http
          containerPort: 8000
kubectl apply -f hey-deployment.yaml
  1. 查看部署状态:
kubectl rollout status deployment/hey-deployment -n monitoring
  1. 查看 Hey 实例的日志:
kubectl logs --tail=20 -n monitoring -l app=hey
  1. 为 Hey 实例分配一个新的服务,选择 NodePort 类型:
kind: Service
apiVersion: v1
metadata:
  name: hey-service
  namespace: monitoring
spec:
  selector:
    app: hey
  type: NodePort
  ports:
  - name: hey-port
    protocol: TCP
    port: 8000
    targetPort: 8000
kubectl apply -f hey-service.yaml
  1. 检查新的 Hey 服务:
minikube service hey-service -n monitoring
  1. 由于 Prometheus 是静态管理的,需要更新 Prometheus ConfigMap 以添加新的 Hey 目标:
kind: ConfigMap
metadata:
  name: prometheus-config
  namespace: monitoring 
data:
  prometheus.yml: |
    scrape_configs:
    - job_name: prometheus
      static_configs:
      - targets:
        - localhost:9090
    - job_name: hey
      static_configs:
      - targets:
        - hey-service.monitoring.svc:8000
kubectl create -f prometheus-configmap-update.yaml -o yaml --dry-run | kubectl apply -f -
  1. 由于没有触发新的部署,需要更改部署定义中的版本注释并应用新的清单:
kubectl apply -f prometheus-deployment-update.yaml
  1. 查看部署状态:
kubectl rollout status deployment/prometheus-deployment -n monitoring

片刻后,新的部署将更新 Prometheus 配置,你可以在 Prometheus 网页界面中验证新目标是否添加成功。

在这个静态部署示例中,由于所有 Pod 都在同一命名空间中,且 Prometheus 尚未需要访问 Kubernetes API,因此不需要基于角色的访问控制(RBAC)配置。但在安全的 Kubernetes 设置中,RBAC 是非常重要的。

动态配置:Prometheus Operator

CoreOS 开创了 Operator 模式,它将 Kubernetes 应用程序的打包、部署和管理的复杂性进行了抽象。Operator 将应用程序运行所需的知识(如配置和部署逻辑)整合到 Kubernetes 自定义资源和自定义控制器中。自定义资源扩展了 Kubernetes API,允许自定义 API 定义;自定义控制器则努力实现用户对资源的期望状态,并持续维护该状态。

在我们的场景中,Prometheus Operator 不仅可以管理 Prometheus 服务器的部署(包括 Pod 数量和持久卷),还可以使用 ServiceMonitor 动态更新配置,ServiceMonitor 根据运行容器的标签匹配规则来定位服务。

以下是使用 Prometheus Operator 部署和配置 Prometheus 并添加目标的详细步骤:

搭建 Kubernetes 环境
  1. 确保没有正在运行的 Minikube 实例,依次执行以下命令:
minikube status
minikube delete
  1. 启动一个新的 Minikube 实例,使用以下配置:
minikube start \
  --cpus=2 \
  --memory=2048 \
  --kubernetes-version="v1.14.0" \
  --vm-driver=virtualbox
  1. 启动完成后,可通过以下命令打开 Kubernetes 仪表盘:
minikube dashboard
  1. 进入正确的仓库路径:
cd chapter05/provision/kubernetes/operator
  1. 使用以下命令创建一个名为 monitoring 的新命名空间:
kubectl apply -f monitoring-namespace.yaml
部署 Prometheus Operator
  1. 确保 Prometheus Operator 具有所有访问权限,首先定义 ClusterRole:
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: prometheus-operator
rules:
- apiGroups: [apiextensions.k8s.io]
  verbs: ['*']
  resources: [customresourcedefinitions]
- apiGroups: [monitoring.coreos.com]
  verbs: ['*']
  resources: 
  - alertmanagers
  - prometheuses
  - servicemonitors
  1. 将 ClusterRole 应用到 ClusterRoleBinding 中:
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: prometheus-operator
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: prometheus-operator
subjects:
- kind: ServiceAccount
  name: prometheus-operator
  namespace: monitoring
  1. 创建一个 ServiceAccount 用于 ClusterRoleBinding:
apiVersion: v1
kind: ServiceAccount
metadata:
  name: prometheus-operator
  namespace: monitoring
  1. 应用包含上述配置的清单:
kubectl apply -f prometheus-operator-rbac.yaml
  1. 部署 Prometheus Operator 本身:
apiVersion: apps/v1beta2
kind: Deployment
metadata:
  labels:
    k8s-app: prometheus-operator
  name: prometheus-operator
  namespace: monitoring
spec:
  replicas: 1
  selector:
    matchLabels:
      k8s-app: prometheus-operator
  template:
    spec:
      serviceAccountName: prometheus-operator
kubectl apply -f prometheus-operator-deployment.yaml
  1. 查看部署状态:
kubectl rollout status deployment/prometheus-operator -n monitoring
部署 Prometheus 服务器
  1. 为 Prometheus 实例授予正确的访问控制权限,首先创建一个允许 Prometheus 通过 GET 请求访问 /metrics 的 ClusterRole:
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: prometheus-k8s
rules:
- nonResourceURLs:
  - /metrics
  verbs:
  - get
  1. 创建一个 ClusterRoleBinding,将上述 ClusterRole 的权限授予一个 ServiceAccount:
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: prometheus-k8s
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: prometheus-k8s
subjects:
- kind: ServiceAccount
  name: prometheus-k8s
  namespace: monitoring
  1. 创建一个 Prometheus 的 ServiceAccount:
apiVersion: v1
kind: ServiceAccount
metadata:
  name: prometheus-k8s
  namespace: monitoring
  1. 应用包含上述配置的清单:
kubectl apply -f prometheus-rbac.yaml
  1. 使用 Prometheus Operator 部署 Prometheus 服务器:
apiVersion: monitoring.coreos.com/v1
kind: Prometheus
metadata:
  labels:
    prometheus: k8s
  name: k8s
  namespace: monitoring
spec:
  baseImage: quay.io/prometheus/prometheus
  version: v2.9.2
  replicas: 2
  serviceAccountName: prometheus-k8s
  serviceMonitorNamespaceSelector: {}
  serviceMonitorSelector: {}
kubectl apply -f prometheus-server.yaml
  1. 查看部署进度:
kubectl rollout status statefulset/prometheus-k8s -n monitoring
  1. 部署完成后,为 Prometheus 服务器创建一个新的服务,并打开网页界面验证当前设置:
kubectl apply -f prometheus-service.yaml
minikube service prometheus-service -n monitoring
为 Prometheus 添加目标
  1. 部署一个应用程序以增加可用目标,这里再次使用 Hey 应用程序,这次使用默认命名空间:
apiVersion: apps/v1
kind: Deployment
metadata:
  name: hey-deployment
  namespace: default
spec:
  replicas: 3
  selector:
    matchLabels:
      app: hey
  template:
    metadata:
      labels:
        app: hey
    spec:
      containers:
      - name: hey
        image: kintoandar/hey:v1.0.1
        ports:
        - name: hey-port
          containerPort: 8000
kubectl apply -f hey-deployment.yaml
  1. 查看部署状态:
kubectl rollout status deployment/hey-deployment -n default
  1. 部署完成后,创建一个新的服务:
kind: Service
metadata:
  labels:
    squad: frontend
  name: hey-service
  namespace: default
spec:
  selector:
    app: hey
  type: NodePort
  ports:
  - name: hey-port
    protocol: TCP
    port: 8000
    targetPort: hey-port
kubectl apply -f hey-service.yaml
  1. 检查新的 Hey 服务:
minikube service hey-service -n default
  1. 创建 Prometheus 实例和 Hey 应用程序的 ServiceMonitor,以指示 Operator 配置 Prometheus 并添加所需目标:
    • Prometheus 的 ServiceMonitor:
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
  labels:
    k8s-app: prometheus
  name: prometheus
  namespace: monitoring
spec:
  endpoints:
  - interval: 30s
    port: web
  selector:
    matchLabels:
      prometheus: k8s
- Hey 应用程序的 ServiceMonitor:
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
  labels:
    app: hey
  name: hey-metrics
  namespace: default
spec:
  endpoints:
  - interval: 30s
    port: hey-port
  selector:
    matchLabels:
      squad: frontend
kubectl apply -f prometheus-servicemonitor.yaml
kubectl apply -f hey-servicemonitor.yaml
  1. 验证 ServiceMonitor 是否成功部署:
kubectl get servicemonitors --all-namespaces

Operator 重新配置 Prometheus 可能需要几秒钟,之后你可以在 Prometheus 网页界面中看到添加的目标。

ServiceMonitor 是使用 Prometheus Operator 时的主要构建块,你可以配置抓取作业的各种参数,如抓取和超时间隔、要抓取的指标端点、HTTP 查询参数等。相关配置文档可参考:https://github.com/coreos/prometheus-operator/blob/master/Documentation/api.md#endpoint

总结

本文介绍了设置 Prometheus 服务器的一些重要配置概念,这些知识对于根据具体场景定制 Prometheus 非常关键。从启动标志到配置文件,我们还启动了一个实例来验证所学知识。随着越来越多的工作负载迁移到容器,特别是 Kubernetes,我们深入探讨了如何在 Kubernetes 环境中设置和管理 Prometheus。我们从静态配置开始,逐步了解更强大的 Prometheus Operator 方法。

常见问题解答
  1. 如果未明确声明 scrape_timeout 会怎样?
  2. 如何让 Prometheus 重新加载其配置文件?
  3. Prometheus 在认为时间序列过时之前会向前查找多久的数据?
  4. relabel_configs 和 metric_relabel_configs 有什么区别?
  5. 在静态部署示例中,我们将 Kubernetes 服务的 Hey 应用程序作为目标添加到 Prometheus 中。如果增加 Hey Pod 的数量会出现什么问题?
  6. 在 Kubernetes 环境中,Prometheus 静态配置是否有意义?为什么?
  7. Prometheus Operator 依赖哪些 Kubernetes 功能来实现其目标?
进一步阅读
  • Prometheus 配置:https://prometheus.io/docs/prometheus/latest/configuration/configuration/
  • Prometheus TSDB API:https://prometheus.io/docs/prometheus/latest/querying/api/#tsdb-admin-apis
  • Prometheus 安全:https://prometheus.io/docs/operating/security/
  • Kubernetes 自定义控制器:https://kubernetes.io/docs/concepts/extend-kubernetes/api-extension/custom-resources/#custom-controllers
  • Kubernetes 自定义资源:https://kubernetes.io/docs/concepts/extend-kubernetes/api-extension/custom-resources/#customresourcedefinitions
  • Prometheus Operator:https://github.com/coreos/prometheus-operator/blob/master/Documentation/design.md

在 Kubernetes 中管理 Prometheus:从静态配置到动态操作(续)

静态配置与动态配置对比

为了更清晰地了解静态配置和使用 Prometheus Operator 进行动态配置的差异,我们可以通过以下表格进行对比:

对比项 静态配置 动态配置(Prometheus Operator)
配置复杂度 较高,需要手动管理配置文件和部署更新 较低,通过自定义资源和控制器自动管理
扩展性 较差,增加目标时需要手动修改配置并触发部署更新 较好,可通过 ServiceMonitor 自动发现和添加目标
灵活性 低,难以适应动态变化的环境 高,能根据环境变化自动调整配置
安全性 示例中未使用 RBAC,实际生产中需额外配置 可利用 Kubernetes RBAC 进行细粒度权限控制

通过这个对比表格,我们可以看出,在大多数生产环境中,动态配置的 Prometheus Operator 更具优势,能够更好地适应复杂多变的 Kubernetes 环境。

静态配置的潜在问题分析

在静态部署示例中,我们将 Kubernetes 服务的 Hey 应用程序作为目标添加到 Prometheus 中。如果增加 Hey Pod 的数量,会出现以下问题:
- 手动更新配置 :由于静态配置需要手动修改 Prometheus 的 ConfigMap 来添加新的目标,当 Hey Pod 数量增加时,需要频繁更新配置文件,容易出错且效率低下。
- 负载均衡问题 :静态配置无法自动处理 Pod 的负载均衡,可能导致某些 Pod 被过度抓取,而其他 Pod 被忽略。
- 缺乏自动发现 :无法自动发现新创建的 Pod,需要人工干预才能将其添加到监控目标中。

Prometheus Operator 的工作原理深入解析

Prometheus Operator 依赖于 Kubernetes 的自定义资源和自定义控制器来实现其目标。下面是其工作原理的 mermaid 流程图:

graph LR
    classDef process fill:#E5F6FF,stroke:#73A6FF,stroke-width:2px;

    A(用户请求):::process --> B(Kubernetes API Server):::process
    B --> C(自定义资源):::process
    C --> D(自定义控制器):::process
    D --> E(管理 Prometheus 资源):::process
    E --> F(创建/更新 Prometheus 实例):::process
    F --> G(ServiceMonitor 发现目标):::process
    G --> H(自动配置 Prometheus):::process
    H --> I(监控目标):::process

从这个流程图可以看出,用户通过 Kubernetes API Server 发起请求,自定义资源和自定义控制器负责处理这些请求,并根据需求管理 Prometheus 资源。ServiceMonitor 会自动发现符合条件的目标,并将其添加到 Prometheus 的配置中,实现动态配置。

配置 Prometheus 的最佳实践

根据前面的介绍和分析,我们可以总结出一些在 Kubernetes 环境中配置 Prometheus 的最佳实践:
1. 优先使用动态配置 :如果可能,尽量使用 Prometheus Operator 进行动态配置,以提高配置的灵活性和可维护性。
2. 合理设置 ServiceMonitor :在使用 ServiceMonitor 时,要合理设置选择器和端点配置,确保准确发现和监控目标。
3. 启用 RBAC :在生产环境中,一定要启用基于角色的访问控制(RBAC),确保 Prometheus 对 Kubernetes API 的访问是安全的。
4. 定期备份数据 :Prometheus 的数据非常重要,要定期备份其数据,以防止数据丢失。
5. 监控 Prometheus 自身 :对 Prometheus 自身的性能和健康状况进行监控,及时发现和解决问题。

总结

本文全面介绍了在 Kubernetes 环境中管理 Prometheus 的方法,从静态配置到动态配置的 Prometheus Operator。我们了解了静态配置的基本步骤和存在的问题,以及 Prometheus Operator 的工作原理和优势。通过对比和分析,我们明确了在不同场景下应如何选择合适的配置方式,并总结了配置 Prometheus 的最佳实践。希望这些内容能帮助你更好地在 Kubernetes 中使用 Prometheus 进行监控。

常见问题解答回顾与解答
  1. 如果未明确声明 scrape_timeout 会怎样?
    • 如果未明确声明 scrape_timeout ,Prometheus 将使用其默认的抓取超时时间。默认情况下,这个时间通常是 10 秒。这意味着如果一个抓取操作在 10 秒内没有完成,Prometheus 将认为该操作失败,并记录相应的错误信息。
  2. 如何让 Prometheus 重新加载其配置文件?
    • 在静态配置中,需要手动修改 ConfigMap 并触发新的部署来重新加载配置文件。在使用 Prometheus Operator 时,修改相关的自定义资源(如 Prometheus 或 ServiceMonitor),Operator 会自动检测到更改并重新配置 Prometheus。
  3. Prometheus 在认为时间序列过时之前会向前查找多久的数据?
    • Prometheus 通过 stale_timeout 参数来控制在认为时间序列过时之前向前查找数据的时间。默认情况下, stale_timeout 是 5 分钟。这意味着如果一个时间序列在 5 分钟内没有新的数据点,Prometheus 将认为该序列过时。
  4. relabel_configs 和 metric_relabel_configs 有什么区别?
    • relabel_configs 用于在抓取目标之前对目标的标签进行重新标记,它可以修改或过滤目标的标签,影响哪些目标会被抓取。而 metric_relabel_configs 用于在抓取到指标后对指标的标签进行重新标记,它可以修改或过滤指标的标签,影响哪些指标会被存储和展示。
  5. 在静态部署示例中,我们将 Kubernetes 服务的 Hey 应用程序作为目标添加到 Prometheus 中。如果增加 Hey Pod 的数量会出现什么问题?
    • 如前面所述,会出现手动更新配置、负载均衡问题和缺乏自动发现等问题。
  6. 在 Kubernetes 环境中,Prometheus 静态配置是否有意义?为什么?
    • 在某些简单的测试环境或对配置灵活性要求不高的场景下,静态配置有一定的意义。它可以帮助我们快速搭建一个基本的监控环境,并且有助于理解 Prometheus 在 Kubernetes 中的工作原理。但在大多数生产环境中,由于其缺乏灵活性和可维护性,静态配置的意义不大。
  7. Prometheus Operator 依赖哪些 Kubernetes 功能来实现其目标?
    • Prometheus Operator 依赖于 Kubernetes 的自定义资源和自定义控制器来实现其目标。自定义资源扩展了 Kubernetes API,允许定义和管理 Prometheus 相关的资源;自定义控制器则负责监控这些资源的状态,并根据用户的需求进行相应的操作,如创建、更新和删除 Prometheus 实例。
进一步探索

随着云原生技术的不断发展,Prometheus 和 Kubernetes 的集成也在不断演进。未来,我们可以进一步探索以下方面:
- 与其他监控系统的集成 :如将 Prometheus 与 Grafana 等可视化工具集成,实现更强大的监控和分析功能。
- 多集群监控 :在多个 Kubernetes 集群中部署和管理 Prometheus,实现跨集群的监控。
- 自动化运维 :结合自动化工具,实现 Prometheus 的自动化部署、配置和升级。

通过不断学习和实践,我们可以更好地利用 Prometheus 和 Kubernetes 的优势,为我们的业务提供更可靠的监控和保障。

更多推荐