一文读懂如何在 Kubernetes 上轻松实现自动化部署 Prometheus

简介

Prometheus 是当下火热的监控解决方案,尤其是容器微服务架构,Kubernetes 的首选监控方案。关于为什么要用 Prometheus,我这里就不多讲,相关的文章太多了,大家也可以看看官方的说法。本文就讲讲如何自动化的搭建一套基于 Kubernetes 集群的 Prometheus 监控系统。

我这里使用 Prometheus Operator 以及 helm 工具在 Kubernetes 集群上部署,后面给大家提供一个全自动运维 (http://t.cn/Ai8t4jLw) 的例子参考,这里直接看代码。

关于什么是 Prometheus Operator 以及为什么要用 Prometheus Operator

Operator 是以软件的方式定义运维过程,是一系列打包、部署和管理 Kubernetes 应用的方法。简单来说就是将运维过程中的手动操作转换为自动化流程,通过 Kubernetes 的 CRD(Custom Resource Definition)将部署前后的相关操作自动化,同时以参数的方式提供了灵活性。而 Prometheus Operator 是 CoreOS 提供的一整套 Prometheus 的 Operator,方便了 Prometheus 的部署。

下面我们先简单讲讲 Prometheus 的架构。

Prometheus 核心

下图是 Promtheus 官方的架构图

Prometheus Server

Prometheus Server 是监控系统的服务端,服务端通过服务发现的方式,抓取被监控服务的指标,或者通过 pushgateway 的间接抓取,抓取到指标数据后,通过特定的存储引擎进行存储,同时暴露一个 HTTP 服务,提供用 PromQL 来进行数据查询。注意,Prometheus 是定时采样数据,而不是全量数据。

Exporter

Prometheus 需要服务暴露 http 接口,如果服务本身没有,我们不需要改造服务,可以通过 exporter 来间接获取。Exporter 就充当了 Prometheus 采集的目标,而由各个 exporter 去直接获取指标。目前大多数的服务都有现成的 exporter,我们不需要重复造轮子,拿来用即可,如 MySQL,MongoDB 等,可以参考这里。

Push Gateway

Prometheus 采集指标的方式主要有两种,一种是服务端暴露接口(Exporter),由 Prometheus 主动去抓取指标,称为 pull 模式。另一种是服务端主动上报,服务端将指标主动上报至 Push Gateway,Prometheus 再从 Push Gateway 中获取,称为 push 模式。而 Push Gateway 就是 push 模式中重要的中介角色,用于暂存服务端上报的指标,等待 Prometheus 收集。

为什么要有两种模式呢?我们来比较一下这两种模式的特点。

Pull 模式:Prometheus 主动抓取的方式,可以由 Prometheus 服务端控制抓取的频率,简单清晰,控制权在 Prometheus 服务端。通过服务发现机制,可以自动接入新服务,去掉下线的服务,无需任何人工干预。对于各种常见的服务,官方或社区有大量 Exporter 来提供指标采集接口,基本无需开发。是官方推荐的方式。

Push 模式:由服务端主动上报至 Push Gateway,采集最小粒度由服务端决定,等于 Push Gateway 充当了中介的角色,收集各个服务主动上报的指标,然后再由 Prometheus 来采集。但是这样就存在了 Push Gateway 这个性能单点,而且 Push Gateway 也要处理持久化问题,不然宕机也会丢失部分数据。同时需要服务端提供主动上报的功能,可能涉及一些开发改动。不是首选的方式,但是在一些场景下很适用。例如,一些临时性的任务,存在时间可能非常短,如果采用 Pull 模式,可能抓取不到数据。

Alert Manager

Alert Manager 是 Prometheus 的报警组件,当 Prometheus 服务端发现报警时,推送 alert 到 Alert Manager,再由 Alert Manager 发送到通知端,如 Email,Slack,微信,钉钉等。Alert Manager 根据相关规则提供了报警的分组、聚合、抑制、沉默等功能。

Web UI/Grafana

Prometheus 提供了一个简单的 web UI 界面,用于查询数据,查看告警、配置等,官方推荐使用另一个开源项目 grafana 来做指标的可视化展示,制作仪表盘等。

部署

下面详细讲讲如何自动化部署 Promethues,自动化监控以及遇到的一些坑。

部署这块 Prometheus Operator 已经帮我们做的非常好了,我们只需要调整一些参数即可实现部署。我们使用 helm 来部署 Prometheus,只需要一个命令。

helm install --name my-release stable/prometheus-operator

不过这不可能满足我们的需求,我们需要的不是演示,而是实战。

下面是详细讲解,完整的项目可以参考这里:http://t.cn/Ai8tzUaR 。

我们首先要确定的是如何持久化存储 Prometheus 的指标数据,默认的方式是以文件的方式保存在服务端的磁盘上,但这样不利于服务端的横向扩展以及数据的备份恢复。Prometheus 还提供了其他存储后端的整合,详见这里。目前比较流行的做法是使用 InfluxDB 作为存储后端,InfluxDB 是一款强大的时序数据库,就是为监控指标等时序数据而生的。

首先,我们来部署 InfluxDB,为了持久化 InfluxDB 的数据,我们先创建一个 PVC 来持久化数据。

pvc.yaml

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: influxdb-pvc
  namespace: monitoring
  labels:
    app: influxdb
    release: influxdb
spec:
  accessModes:
    - ReadWriteOnce
  storageClassName: monitor-ebs  # 选择合适的存储类
  resources:
    requests:
      storage: 200Gi  # 设置合适的存储空间

然后我们创建 InfluxDB 的配置文件

influxdb.yaml

# 持久化存储配置
persistence:
  enabled: true
  useExisting: true
  name: "influxdb-pvc"  # 使用我们刚才创建的 PVC
  accessMode: "ReadWriteOnce"
  size: 200Gi

# 创建 Prometheus 的数据库
env:
  - name: INFLUXDB_DB
    value: "prometheus"

# influxdb 配置
config:
  data:
    # 这两个配置默认限制了数据的上限,建议设置为 0 变成无限制,不然在达到上限后插入数据会返回错误
    max_series_per_database: 0
    max_values_per_tag: 0
  http:
    enabled: true  # 启动 http
initScripts:
  enabled: true
  scripts:
    # 设置数据保留策略,默认是永不失效,需要人工清理
    # 保留 180 天数据
    retention.iql: |+
      CREATE RETENTION POLICY "default_retention_policy" on "prometheus" DURATION 180d REPLICATION 1 DEFAULT

InfluxDB 的全部配置可以参考文档,我讲一下上面的两个主要的配置。

max-series-per-database

内存中每个数据库最大的序列数量,默认是 1000000,设置为 0 改成无限制。如果新来的数据增加了序列数量并超过了这个上限,那么数据就会被丢弃就并返回一个 500 错误:

{"error":"max series per database exceeded: <series>"}

max-values-per-tag

内存中每个标签的最大数据量,默认是 100000,设置为 0 改成无限制。如果新来的数据超过了这个限制,也会被丢弃并返回写入失败的错误。

我们使用如下命令来部署 InfluxDB:

helm install --name=influxdb --namespace=monitoring -f influxdb.yaml stable/influxdb

存储后端部署成功后,我们就来部署 Prometheus-operator 了,首先创建如下的配置文件

prometheus.yaml

# prometheus 服务端
prometheus:
  prometheusSpec:
    # 远端存储配置
    remoteWrite:
    - url: "http://influxdb:8086/api/v1/prom/write?db=prometheus"
    remoteRead:
    - url: "http://influxdb:8086/api/v1/prom/read?db=prometheus"

  # ingress 配置,暴露 web 界面
  ingress:
    enabled: true
    annotations:
      kubernetes.io/ingress.class: traefik  # ingress class
    hosts:
    - "prometheus.mydomain.io"  # 配置域名

alertmanager:
  # alertmanager 配置
  config:
    global:
      # SMTP 配置
      smtp_smarthost: 'xxx'
      smtp_from: 'xxx'
      smtp_auth_username: 'xxx'
      smtp_auth_password: 'xxx'
      # 全局 opsgenie 配置
      # opsgenie_api_key: ""
    # 报警路由
    route:
      receiver: 'monitoring-warning'
      group_by: ['alertname']
      group_wait: 30s
      group_interval: 3m
      repeat_interval: 8h
      routes:
      - match:
          severity: critical
        receiver: monitoring-critical
        group_by: ['alertname']
      - match:
          severity: warning
        receiver: monitoring-warning
        group_by: ['alertname']
    # 报警抑制规则
    inhibit_rules:
    - source_match:
        severity: 'critical'
      target_match:
        severity: 'warning'
      # 抑制相同的报警
      equal: ['alertname']
    # 接收者配置
    receivers:
    - name: 'monitoring-critical'
      email_configs:
      - to: 'monitor@mydomain.com'
      # 发送到钉钉的 webhook,需要部署一个转发服务,详见项目代码
      webhook_configs:
      - send_resolved: true
        url: http://prometheus-webhook-dingtalk/dingtalk/monitoring/send
    - name: 'monitoring-warning'
      email_configs:
      - to: 'monitor@mydomain.com'
  alertmanagerSpec:
    # alertmanager 存储配置,alertmanager 会以文件形式存储报警静默等配置
    storage:
      volumeClaimTemplate:
        spec:
          accessModes:
          - ReadWriteOnce
          storageClassName: monitor-ebs  # 选择合适的存储类
          resources:
            requests:
              storage: 20Gi  # 选择合适的大小
  # ingress 配置,暴露 alert 的界面
  ingress:
    enabled: true
    annotations:
      kubernetes.io/ingress.class: traefik  # ingress class
    hosts:
    - "alert.mydomain.io"  # 配置域名

# grafana 配置
grafana:
  replicas: 1
  adminPassword: "admin"  # 管理员账户 admin,密码 admin
  env:
    # GF_SERVER_DOMAIN: ""  # 域名
    GF_SERVER_ROOT_URL: "%(protocol)s://%(domain)s/"
    # GF_DATABASE_URL: "mysql://user:secret@host:port/database"  # SQL 数据库
  # ingress 配置,暴露界面
  ingress:
    enabled: true
    annotations:
      kubernetes.io/ingress.class: traefik  # ingress class
    hosts:
    - "grafana.mydomain.io"  # 设置域名

# exporter 设置,自建集群需要开启,如果是云服务商托管集群,则获取不到这些信息,可以关闭
kubeControllerManager:
  enabled: true
kubeEtcd:
  enabled: true
kubeScheduler:
  enabled: true

然后我们使用如下命令来部署 Prometheus-Operator

helm install --name=prometheus --namespace=monitoring -f prometheus.yam stable/prometheus-operator

如果需要 Prometheus-Pushgateway 的话,创建如下配置

prometheus-pushgateway.yaml

replicaCount: 1
# 自动在 Prometheus 中添加 target
serviceMonitor:
  enabled: true
  namespace: monitoring
  selector:
    app: prometheus-pushgateway
    release: prometheus
# ingress 配置,暴露界面
ingress:
  enabled: true
  annotations:
    kubernetes.io/ingress.class: traefik  # ingress class
  hosts:
  - "pushgateway.mydomain.io"  # 设置域名

同样的方式部署

helm install --name=prometheus-pushgateway --namespace=monitoring -f prometheus-pushgateway.yaml stable/prometheus-pushgateway

这样 Prometheus 的核心组件都部署完成了,查看集群中的 Pod,有类似如下图所示的 Pod

这里有个注意点,如果通过 Prometheus 收集 kube-proxy 的指标,需要 kube-proxy 开通访问,默认 kube-proxy 只允许本机访问。 需要修改 kube-proxy 的 ConfigMap 中的 metricsBindAddress 值为 0.0.0.0:10249

kubectl -n kube-system edit cm kube-proxy

会看到如下内容,将 metricsBindAddress: 127.0.0.1:10249 这行修改为 metricsBindAddress: 0.0.0.0:10249 保存即可。

apiVersion: v1
data:
  config.conf: |-
    apiVersion: kubeproxy.config.k8s.io/v1alpha1
    kind: KubeProxyConfiguration
    # ...
    # metricsBindAddress: 127.0.0.1:10249
    metricsBindAddress: 0.0.0.0:10249
    # ...
  kubeconfig.conf: |-
    # ...
kind: ConfigMap
metadata:
  labels:
    app: kube-proxy
  name: kube-proxy
  namespace: kube-system

然后删除 kube-proxy 的 Pod,让它重启即可看到已正常抓取。

应用

至此,Prometheus 的服务端就全部部署完成了。接下来就是根据实际业务部署相应的 Exporter,ServiceMonitor 和 PrometheusRule 了。官方和社区有大量现成的 Exporters 可供使用,如果有特殊需求的也可以参考这里自行开发。

接下来我们讲讲如何快速集成 Prometheus 监控和报警。

我们之前提到过 Operator 通过 CRD 的方式提供了很多部署方面的自动化,Prometheus-Operator 就提供了四个 CRD,分别是

  • Prometheus,定义了 Prometheus 服务端,用来生成服务端控制器,保证了服务端的正常运行,我们只需要一个此 CRD 的实例
  • Alertmanager,定义了 AlertManager 服务,用来生成服务端控制器,保证了服务的正常运行,我们也只需要一个此 CRD 的实例
  • ServiceMonitor,定义了 Prometheus 抓取指标的目标,就是 Prometheus 界面 targets 页面看到的内容,此 CRD 帮助我们创建目标的配置
  • PrometheusRule,定义了 Prometheus 规则,就是 Prometheus 界面 Rules 页面看到的内容,此 CRD 帮助我们创建规则的配置

Prometheus 和 Alertmanager CRD 主要是之前部署阶段关注的,在服务应用阶段,我们主要是创建各个 ServiceMonitor 和 PrometheusRule 来配置服务端。

Prometheus-Operator 默认会帮我们注册相关组件的抓取目标,如下图所示

我们要定义其他的抓取目标,首先来创建了一个 ServiceMonitor 抓取我们部署的 InfluxDB 的指标

apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
  name: influxdb-scrape-targets
  labels:
    app.kubernetes.io/name: scrape-targets
    app.kubernetes.io/instance: influxdb-target
    release: prometheus
spec:
  # 用标签选择器来选择相应的 Pod
  selector:
    matchLabels:
      app: influxdb
      release: influxdb

  # 选择命名空间
  namespaceSelector:
    matchNames:
    - monitoring

  # 定义抓取的配置,如端口、频率等
  endpoints:
    - interval: 15s
      port: api

我们在项目中创建了一个 Chart 模版(在 charts/scrape-targets/ 目录),能够快速的创建 ServiceMonitor,提供下面的配置文件

influxdb.yaml

selector:
  matchLabels:
    app: influxdb
    release: influxdb
namespaceSelector:
  matchNames:
    - monitoring
endpoints:
  - port: api
    interval: 15s

然后使用 helm 安装

helm install --name influxdb-target --namespace monitoring -f influxdb.yaml charts/scrape-targets/

创建完成后无需重启 Prometheus 服务端,服务端根据标签自动载入,过一会可以在界面上看到

Prometheus-Operator 同样会帮我们注册许多相关的规则,如下图所示

配置我们自己的 PrometheusRule 同样很简单,我们用如下配置生成报警规则,如果 5 分钟内的 HTTP 500 错误大于 5 则报警

apiVersion: monitoring.coreos.com/v1
kind: PrometheusRule
metadata:
  name: request-rules
  labels:
    app.kubernetes.io/name: rules
    app.kubernetes.io/instance: request
    app: prometheus-operator
    release: prometheus
spec:
  groups:
  - name: request-rules.rules
    rules:
      - alert: RequestStatusCode500
        annotations:
          summary: http status code 500 is high for `{{$labels.service}}`
        expr: http_request_total{statuscode="500"} > 5
        for: 5m
        labels:
          severity: critical

也可以用我们项目中的 Chart 模版(在 charts/rules/ 目录)来快速配置

request.yaml

groups:
  - rules:
    - alert: RequestStatusCode500
      expr: http_request_total{statuscode="500"} > 5
      for: "5m"
      labels:
        severity: critical
      annotations:
        summary: http status code 500 is high for `{{$labels.service}}`

然后 helm 安装

helm install --name request --namespace monitoring -f request.yaml charts/rules/

关于怎么写规则配置,可以参考官方的文档和 PromQL 语法。

以上的操作还是手动化的,如果要全自动化的话,可以参考我的项目,定义好配置文件,写好自动化脚本,接入 CI/CD 工作流,即可让监控系统实现自动部署、自动配置。

参考

  • Prometheus 官网
  • Prometheus 与其他监控系统对比
  • Kubernetes Operator
  • Prometheus Operator
  • Prometheus-Pushgateway Operator
  • Prometheus Remote Storage
  • InfluxDB
  • Kubernetes 实操手册-Helm使用
  • Prometheus Exporters
  • Writing Exporters
  • Prometheus-Operator API Docs
  • Prometheus 自动部署

来源:知乎 原文:http://t.cn/Ai8tV2yE

本文分享自微信公众号 - kubernetes中文社区(DailyDev)

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2019-10-11

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏云计算D1net

哪三个热门市场正在经历云计算带来的颠覆?

云原生计算可能是当今企业IT中最重要的趋势。从本质上讲,云原生技术将云计算的优势扩展到整个IT领域,其中包括内部部署技术和边缘计算。

7930
来自专栏DevOps时代的专栏

50个你必须了解的Kubernetes面试问题

Kubernetes一直是当今业界的流行语,也是最好的编排工具。它吸引了许多想要提升自己职业生涯的经验丰富的专业人士。HuaWei,Pokemon,Box,eB...

8210
来自专栏惨绿少年

Kubernetes V1.15 二进制部署集群

以下操作均在/data/ssl_config/etcd/目录中 etcd证书ca配置

24130
来自专栏运维之美

Kubernetes 1.16 发布,一文读懂其重磅新特性!

此次发行版源自数百名技术与非技术贡献者的共同努力,随着 Kubernetes 社区的不断发展,我们的发布过程也代表着开源软件开发协作领域的又一惊人成功。

37520
来自专栏sktj

Kubernetes(4:架构)

Master 是cluster 的大脑: 运行 kube-apiserver kube-scheduler kube-controller-manager ...

9020
来自专栏运维之美

使用 Kind 在 5 分钟内快速部署一个 Kubernetes 高可用集群

Kind(Kubernetes in Docker) 是一个 Kubernetes 孵化项目,Kind 是一套开箱即用的 Kubernetes 环境搭建方案。顾...

14820
来自专栏sktj

Kubernetes(1)

1、部署应用 kubectl run kubernetes-bootcamp --image=docker.io/kubernetes-bootcamp:v1...

7830
来自专栏MoeLove

K8S 生态周报| Kubernetes v1.16 正式发布

「K8S 生态周报」内容主要包含我所接触到的 K8S 生态相关的每周值得推荐的一些信息。欢迎订阅知乎专栏「k8s生态」。

13630
来自专栏sktj

Kubernetes(3:部署)

1 3个节点: k8s-master k8s-node1 k8s-node2 2 yum install -y docker 3 所有节点安装k...

7830
来自专栏sktj

Kubernetes(2:概念)

cluster 计算存储和网络资源的集合,利用这些资源运行各种基于容器的应用。 Master 负责调度,运行在LINUX中。 Node 负责运行容器,由MA...

7320

扫码关注云+社区

领取腾讯云代金券

年度创作总结 领取年终奖励