前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Kubernetes 集群监控 kube-prometheus 自动发现

Kubernetes 集群监控 kube-prometheus 自动发现

作者头像
高楼Zee
发布2021-03-16 16:13:40
5.9K0
发布2021-03-16 16:13:40
举报
文章被收录于专栏:7DGroup7DGroup

一、背景介绍

前面我们一起配置了如何在 kube-prometheus 下面新增一个监控项 Kubernetes 集群监控 ETCD 组件。如果我们在 Kubernetes 集群中有了很多的 Service 和 Pod,那么我们都得一个一个的去建立一个对应的 ServiceMonitor 对象来进行监控吗?这样岂不是又变得很繁琐起来了?

答案「否定的」,我们可以通过 prometheus 的自动发现功能轻松解决这个问题。

二、什么是服务发现?

我们在每个节点上面都运行了 node-exporter,如果我们通过一个 Service 来将数据收集到一起用静态配置的方式配置到 Prometheus 去中,就只会显示一条数据,我们得自己在指标数据中去过滤每个节点的数据,当然我们也可以手动的把所有节点用静态的方式配置到 Prometheus 中去,但是以后要新增或者去掉节点的时候就还得手动去配置,那么有没有一种方式可以让 Prometheus 去自动发现我们节点的 node-exporter 程序,并且按节点进行分组呢?这就是 Prometheus 里面非常重要的「服务发现」功能。

Prometheus支持多种服务发现机制:文件、DNS、Consul、Kubernetes、OpenStack、EC2等。基于服务发现的过程并不复杂,通过第三方提供的接口,Prometheus查询到需要监控的Target列表,然后轮训这些Target获取监控数据,下面主要介绍Kubernetes服务发现机制。

目前,在Kubernetes下,Prometheus 通过与 Kubernetes API 集成主要支持5种服务发现模式:Node、Service、Pod、Endpoints、Ingress。不同的服务发现模式适用于不同的场景,例如:node适用于与主机相关的监控资源,如节点中运行的Kubernetes 组件状态、节点上运行的容器状态等;service 和 ingress 适用于通过黑盒监控的场景,如对服务的可用性以及服务质量的监控;endpoints 和 pod 均可用于获取 Pod 实例的监控数据,如监控用户或者管理员部署的支持 Prometheus 的应用。

三、规则解析

为解决服务发现的问题,kube-prometheus 为我们提供了一个额外的抓取配置来解决这个问题,我们可以通过添加额外的配置来进行服务发现进行自动监控。我们可以在 kube-prometheus 当中去自动发现并监控具有 prometheus.io/scrape=true 这个 annotations 的 Service。

配置项规则参考链接:https://prometheus.io/docs/prometheus/latest/configuration/configuration/

其中通过 kubernetes_sd_configs 支持监控其各种资源。kubernetes SD 配置允许从 kubernetes REST API 接受搜集指标,且总是和集群保持同步状态,任何一种 role 类型都能够配置来发现我们想要的对象。

规则配置使用 yaml 格式,下面是文件中一级配置项。自动发现 k8s Metrics 接口是通过 scrape_configs 来实现的:

#全局配置
global:

#规则配置主要是配置报警规则
rule_files:

#抓取配置,主要配置抓取客户端相关
scrape_configs:

#报警配置
alerting:

#用于远程存储写配置
remote_write:

#用于远程读配置
remote_read:

举例说明:

# Kubernetes的API SERVER会暴露API服务,Promethues集成了对Kubernetes的自动发现,它有5种模式:Node、Service
# 、Pod、Endpoints、ingress,下面是Prometheus官方给出的对Kubernetes服务发现的实例。这里你会看到大量的relabel_configs,
# 其实你就是把所有的relabel_configs去掉一样可以对kubernetes做服务发现。relabel_configs仅仅是对采集过来的指标做二次处理,比如
# 要什么不要什么以及替换什么等等。而以__meta_开头的这些元数据标签都是实例中包含的,而relabel则是动态的修改、覆盖、添加删除这些标签
# 或者这些标签对应的值。而且以__开头的标签通常是系统内部使用的,因此这些标签不会被写入样本数据中,如果我们要收集这些东西那么则要进行
# relabel操作。当然reabel操作也不仅限于操作__开头的标签。
#
# action的行为:
# replace:默认行为,不配置action的话就采用这种行为,它会根据regex来去匹配source_labels标签上的值,并将并将匹配到的值写入target_label中
# labelmap:它会根据regex去匹配标签名称,并将匹配到的内容作为新标签的名称,其值作为新标签的值
# keep:仅收集匹配到regex的源标签,而会丢弃没有匹配到的所有标签,用于选择
# drop:丢弃匹配到regex的源标签,而会收集没有匹配到的所有标签,用于排除
# labeldrop:使用regex匹配标签,符合regex规则的标签将从target实例中移除,其实也就是不收集不保存
# labelkeep:使用regex匹配标签,仅收集符合regex规则的标签,不符合的不收集

global:
  # 间隔时间
  scrape_interval: 30s
  # 超时时间
  scrape_timeout: 10s
  # 另一个独立的规则周期,对告警规则做定期计算
  evaluation_interval: 30s
  # 外部系统标签
  external_labels:
    prometheus: monitoring/k8s
    prometheus_replica: prometheus-k8s-1

# 抓取服务端点,整个这个任务都是用来发现node-exporter和kube-state-metrics-service的,这里用的是endpoints角色,这是通过这两者的service来发现
# 的后端endpoints。另外需要说明的是如果满足采集条件,那么在service、POD中定义的labels也会被采集进去
scrape_configs: 
  # 定义job名称,是一个拉取单元 
- job_name: "kubernetes-endpoints"
  # 发现endpoints,它是从列出的服务端点发现目标,这个endpoints来自于Kubernetes中的service,每一个service都有对应的endpoints,这里是一个列表
  # 可以是一个IP:PORT也可以是多个,这些IP:PORT就是service通过标签选择器选择的POD的IP和端口。所以endpoints角色就是用来发现server对应的pod的IP的
  # kubernetes会有一个默认的service,通过找到这个service的endpoints就找到了api server的IP:PORT,那endpoints有很多,我怎么知道哪个是api server呢
  # 这个就靠source_labels指定的标签名称了。
  kubernetes_sd_configs:
    # 角色为 endpoints
    - role: endpoints

  # 下面的含义是源标签__meta_kubernetes_namespace等如果其值为default;kubernetes;https标签顺序和值要对应。换句话说就是
  # 当__meta_kubernetes_namespace, __meta_kubernetes_service_name, __meta_kubernetes_endpoint_port_name三者对应的
  # 值为default、kubernetes、https则进行保留,而且该endpoints对应的地址为api server的地址。
  #
  # __meta_kubernetes_namespace 端点对象的命名空间,在不同对象上这个标签的含义不同,在角色是endpoints中这个是端点对象的名称空间
  # __meta_kubernetes_service_name 端点对象的服务名称
  # __meta_kubernetes_endpoint_port_name 端点的端口名称
  #
  # kubernetes默认在default名称空间有一个叫做kubernetes的service,所以这个service的有3个设置对应的就是下面三个标签
  # __meta_kubernetes_namespace 值为default
  # __meta_kubernetes_service_name 值为kubernetes
  # __meta_kubernetes_endpoint_port_name 值为https
  relabel_configs:
    # 重新打标仅抓取到的具有 "prometheus.io/scrape: true" 的annotation的端点,意思是说如果某个service具有prometheus.io/scrape = true annotation声明则抓取
 # annotation本身也是键值结构,所以这里的源标签设置为键,而regex设置值,当值匹配到regex设定的内容时则执行keep动作也就是保留,其余则丢弃.
 # node-exporter这个POD的service里面就有一个叫做prometheus.io/scrape = true的annotations所以就找到了node-exporter这个POD
    - source_labels: [__meta_kubernetes_service_annotation_prometheus_io_scrape]
      # 动作 删除 regex 与串联不匹配的目标 source_labels
      action: keep
      # 通过正式表达式匹配 true
      regex: true
    # 重新设置scheme
 # 匹配源标签__meta_kubernetes_service_annotation_prometheus_io_scheme也就是prometheus.io/scheme annotation
 # 如果源标签的值匹配到regex则把值替换为__scheme__对应的值
    - source_labels: [__meta_kubernetes_service_annotation_prometheus_io_scheme]
      action: replace
      target_label: __scheme__
      regex: (https?)
    # 匹配来自 pod annotationname prometheus.io/path 字段
    - source_labels: [__meta_kubernetes_service_annotation_prometheus_io_path]
      # 获取POD的 annotation 中定义的"prometheus.io/path: XXX"定义的值,这个值就是你的程序暴露符合prometheus规范的metrics的地址
   # 如果你的metrics的地址不是 /metrics 的话,通过这个标签说,那么这里就会把这个值赋值给 __metrics_path__这个变量,因为prometheus
      # 是通过这个变量获取路径然后进行拼接出来一个完整的URL,并通过这个URL来获取metrics值的,因为prometheus默认使用的就是 http(s)://X.X.X.X/metrics
      # 这样一个路径来获取的。
      action: replace
      # 匹配目标指标路径
      target_label: __metrics_path__
      # 匹配全路径
      regex: (.+)
    # 匹配出 Pod ip地址和 Port
    - source_labels:
        [__address__, __meta_kubernetes_service_annotation_prometheus_io_port]
      action: replace
      target_label: __address__
      regex: ([^:]+)(?::\d+)?;(\d+)
      replacement: $1:$2
    # 下面主要是为了给样本添加额外信息
    - action: labelmap
      regex: __meta_kubernetes_service_label_(.+)
    # 元标签 服务对象的名称空间
    - source_labels: [__meta_kubernetes_namespace]
      action: replace
      target_label: kubernetes_namespace
    # service 对象的名称
    - source_labels: [__meta_kubernetes_service_name]
      action: replace
      target_label: kubernetes_name
    # pod对象的名称
    - source_labels: [__meta_kubernetes_pod_name]
      action: replace
      target_label: kubernetes_pod_name

四、如何实现?

1、创建发现规则

我们定义的 Prometheus 的配置如下:「prometheus-additional.yaml:」

- job_name: 'kubernetes-endpoints'
  kubernetes_sd_configs:
  - role: endpoints
  relabel_configs:
  - source_labels: [__meta_kubernetes_service_annotation_prometheus_io_scrape]
    action: keep
    regex: true
  - source_labels: [__meta_kubernetes_service_annotation_prometheus_io_scheme]
    action: replace
    target_label: __scheme__
    regex: (https?)
  - source_labels: [__meta_kubernetes_service_annotation_prometheus_io_path]
    action: replace
    target_label: __metrics_path__
    regex: (.+)
  - source_labels: [__address__, __meta_kubernetes_service_annotation_prometheus_io_port]
    action: replace
    target_label: __address__
    regex: ([^:]+)(?::\d+)?;(\d+)
    replacement: $1:$2
  - action: labelmap
    regex: __meta_kubernetes_service_label_(.+)
  - source_labels: [__meta_kubernetes_namespace]
    action: replace
    target_label: kubernetes_namespace
  - source_labels: [__meta_kubernetes_service_name]
    action: replace
    target_label: kubernetes_name
  - source_labels: [__meta_kubernetes_pod_name]
    action: replace
    target_label: kubernetes_pod_name

endpoints role 从每个服务监听的 endpoints 发现,每个 endpoint 都会发现一个port,如果 endpoint 是一个pod,所有包含的容器不被绑定到一个 endpoint port,也会被 targets 被发现。如果你对上面这个配置还不是很熟悉的话,建议去查看下前面关于 Kubernetes 常用资源对象监控的介绍,要想自动发现集群中的 Service,就需要我们在 Service 的 annotation 区域添加 prometheus.io/scrape=true 的声明

2、创建Secret 对象

将上面文件直接保存为 prometheus-additional.yaml,然后通过这个文件创建一个对应的 Secret 对象:

$ kubectl create secret generic additional-configs --from-file=prometheus-additional.yaml -n monitoring
secret "additional-configs" created

3、创建资源对象

然后我们需要在声明 prometheus 的资源对象文件中通过 additionalScrapeConfigs 属性添加上这个额外的配置:

「prometheus-prometheus.yaml」

apiVersion: monitoring.coreos.com/v1
kind: Prometheus
metadata:
  labels:
    prometheus: k8s
  name: k8s
  namespace: monitoring
spec:
  alerting:
    alertmanagers:
      - name: alertmanager-main
        namespace: monitoring
        port: web
  image: quay.io/prometheus/prometheus:v2.20.0
  nodeSelector:
    kubernetes.io/os: linux
  podMonitorNamespaceSelector: {}
  podMonitorSelector: {}
  replicas: 2
  resources:
    requests:
      memory: 400Mi
  ruleSelector:
    matchLabels:
      prometheus: k8s
      role: alert-rules
  securityContext:
    fsGroup: 2000
    runAsNonRoot: true
    runAsUser: 1000
  serviceAccountName: prometheus-k8s
  serviceMonitorNamespaceSelector: {}
  serviceMonitorSelector: {}
  version: v2.20.0
  storage:        #----添加持久化配置,指定StorageClass
    volumeClaimTemplate:
      spec:
        storageClassName: nfs-storage-new #---指定name
        resources:
          requests:
            storage: 10Gi
  additionalScrapeConfigs:
    name: additional-configs
    key: prometheus-additional.yaml

关于 additionalScrapeConfigs 属性的具体介绍,我们可以使用 kubectl explain 命令来了解详细信息:

$ kubectl explain prometheus.spec.additionalScrapeConfigs
KIND:     Prometheus
VERSION:  monitoring.coreos.com/v1

RESOURCE: additionalScrapeConfigs <Object>

DESCRIPTION:
     AdditionalScrapeConfigs allows specifying a key of a Secret containing
     additional Prometheus scrape configurations. Scrape configurations
     specified are appended to the configurations generated by the Prometheus
     Operator. Job configurations specified must have the form as specified in
     the official Prometheus documentation:
     https://prometheus.io/docs/prometheus/latest/configuration/configuration/#scrape_config.
     As scrape configs are appended, the user is responsible to make sure it is
     valid. Note that using this feature may expose the possibility to break
     upgrades of Prometheus. It is advised to review Prometheus release notes to
     ensure that no incompatible scrape configs are going to break Prometheus
     after the upgrade.

FIELDS:
   key <string> -required-
     The key of the secret to select from. Must be a valid secret key.

   name <string>
     Name of the referent. More info:
     https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
     TODO: Add other useful fields. apiVersion, kind, uid?

   optional <boolean>
     Specify whether the Secret or its key must be defined

添加完成后,直接更新 prometheus 这个 CRD 资源对象即可:

kubectl apply -f prometheus-prometheus.yaml

4、查看配置

过一段时间,刷新 promethues 上的 config,将会查看配置已经生效:

5、创建 RBAC 权限

我们切换到 targets 页面下面却并没有发现对应的监控任务,查看 Prometheus 的 Pod 日志,发现很多错误日志出现,都是 xxx is forbidden,这说明是 RBAC 权限的问题。

通过 prometheus 资源对象的配置可以知道 Prometheus 绑定了一个名为 prometheus-k8s 的 ServiceAccount 对象,而这个对象绑定的是一个名为 prometheus-k8s 的 ClusterRole:

创建 prometheus-clusterRole.yaml:

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: prometheus-k8s
rules:
- apiGroups:
  - ""
  resources:
  - nodes/metrics
  verbs:
  - get
- nonResourceURLs:
  - /metrics
  verbs:
  - get

上面的权限规则中我们可以看到明显没有对 Service 或者 Pod 的 list 权限,所以报错了,要解决这个问题,我们只需要添加上需要的权限即可:

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: prometheus-k8s
rules:
  - apiGroups:
      - ""
    resources:
      - nodes
      - services
      - endpoints
      - pods
      - nodes/proxy
    verbs:
      - get
      - list
      - watch
  - apiGroups:
      - ""
    resources:
      - configmaps
      - nodes/metrics
    verbs:
      - get
  - nonResourceURLs:
      - /metrics
    verbs:
      - get

更新上面的 ClusterRole 这个资源对象,然后重建下 Prometheus 的所有 Pod,正常就可以看到 targets 页面下面有 kubernetes-endpoints 这个监控任务了:

这里抓取目标是因为 Service 中都有 prometheus.io/scrape=true 这个 annotation。至此,一个自动发现 pod 的配置就完成了,其他资源(service、endpoint、ingress、node同样也可以通过自动发现的方式实现。

五、常用中间件如何落地 ?

1、Redis

1.1、原理

Prometheus 的数据指标是通过一个公开的 HTTP(S) 数据接口获取到的,我们不需要单独安装监控的 agent,只需要暴露一个 metrics 接口,Prometheus 就会定期去拉取数据;对于一些普通的 HTTP 服务,我们完全可以直接重用这个服务,添加一个 /metrics 接口暴露给 Prometheus;而且获取到的指标数据格式是非常易懂的,不需要太高的学习成本。同时现在很多服务从一开始就内置了一个/metrics 接口,比如 Kubernetes 的各个组件、istio 服务网格都直接提供了数据指标接口。有一些服务即使没有原生集成该接口,也完全可以使用一些 exporter 来获取到指标数据,比如今天介绍的 redis_exporter,而 exporter 就有点类似于传统监控服务中的 agent,作为服务一直存在,用来收集目标服务的指标数据然后直接暴露给 Prometheus。

1.2、redis_exporter

redis 没有自带 /metrics 接口供 Prometheus 使用,在这种情况下,我们就需要利用 exporter 服务来为 Prometheus 提供指标数据了。Prometheus 官方为许多应用就提供了对应的 exporter 应用,也有许多第三方的实现,我们可以前往官方网站进行查看:https://prometheus.io/docs/instrumenting/exporters/

这里我们选择官方的 redis_exporter:https://github.com/oliver006/redis_exporter

1.3、构建 sidecar

这里通过 redis_exporter 的服务来监控 redis 服务,我们以 sidecar 的形式和主应用部署在同一个 Pod 中,比如我们这里来部署一个 redis,并用 redis_exporter 的方式来采集监控数据供 Prometheus 使用,如下资源清单文件:promethues-redis-deploy.yaml这里通过 redis_exporter 的服务来监控 redis 服务,我们以 sidecar 的形式和主应用部署在同一个 Pod 中,比如我们这里来部署一个 redis,并用 redis_exporter 的方式来采集监控数据供 Prometheus 使用。

如下资源清单文件:promethues-redis-deploy.yaml:

## Service
apiVersion: v1
kind: Service
metadata:
  name: cloud-redis
  labels:
    app: redis
spec:
  selector:
    app: redis
  ports:
    - name: redis
      port: 6379
      targetPort: 6379
    - name: prom
      port: 9121
      targetPort: 9121
---
## Deployment
apiVersion: apps/v1
kind: Deployment
metadata:
  name: cloud-redis
  labels:
    app: redis
spec:
  replicas: 1
  selector:
    matchLabels:
      app: redis
  template:
    metadata:
      annotations:
        prometheus.io/scrape: "true"
        prometheus.io/port: "9121"
      labels:
        app: redis
    spec:
      initContainers:
        - name: system-init
          image: busybox:1.32
          imagePullPolicy: IfNotPresent
          command:
            - "sh"
            - "-c"
            - "echo 2000 > /proc/sys/net/core/somaxconn && echo never > /sys/kernel/mm/transparent_hugepage/enabled"
          securityContext:
            privileged: true
            runAsUser: 0
          volumeMounts:
            - name: sys
              mountPath: /sys
      containers:
        - name: redis-exporter
          image: oliver006/redis_exporter:latest
          resources:
            requests:
              cpu: 100m
              memory: 100Mi
          ports:
            - containerPort: 9121
        - name: redis
          image: redis:5.0.8
          command:
            - "sh"
            - "-c"
            - "redis-server /usr/local/etc/redis/redis.conf"
          ports:
            - containerPort: 6379
          resources:
            limits:
              cpu: 1000m
              memory: 1024Mi
            requests:
              cpu: 1000m
              memory: 1024Mi
          volumeMounts:
            - name: data
              mountPath: /data
            - name: config
              mountPath: /usr/local/etc/redis/redis.conf
              subPath: redis.conf
      volumes:
        - name: data
          persistentVolumeClaim:
            claimName: redis
        - name: config
          configMap:
            name: redis-config
        - name: sys
          hostPath:
            path: /sys
1.4、测试

创建完成后,我们可以看到 redis 的 Pod 里面包含有两个容器:

$ kubectl get pods -n mall
NAME                                    READY   STATUS    RESTARTS   AGE
cloud-redis-79b69db657-vjh8r            2/2     Running   0          5d4h

$ kubectl get svc -n mall
NAME                   TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)                               AGE
cloud-redis            ClusterIP   10.96.243.202   <none>        6379/TCP,9121/TCP                     5d4h

我们可以通过 9121 端口来校验是否能够采集到数据:

$ curl 10.96.243.202:9121/metrics
# HELP go_gc_duration_seconds A summary of the pause duration of garbage collection cycles.
# TYPE go_gc_duration_seconds summary
go_gc_duration_seconds{quantile="0"} 4.6144e-05
go_gc_duration_seconds{quantile="0.25"} 9.4462e-05
go_gc_duration_seconds{quantile="0.5"} 0.000122258
go_gc_duration_seconds{quantile="0.75"} 0.000168729
go_gc_duration_seconds{quantile="1"} 0.009149671
go_gc_duration_seconds_sum 1.531426455
go_gc_duration_seconds_count 6342
# HELP go_goroutines Number of goroutines that currently exist.
# TYPE go_goroutines gauge
go_goroutines 10
# HELP go_info Information about the Go environment.
# TYPE go_info gauge
go_info{version="go1.15"} 1
# HELP go_memstats_alloc_bytes Number of bytes allocated and still in use.
# TYPE go_memstats_alloc_bytes gauge
go_memstats_alloc_bytes 4.304504e+06
# HELP go_memstats_alloc_bytes_total Total number of bytes allocated, even if freed.
# TYPE go_memstats_alloc_bytes_total counter
go_memstats_alloc_bytes_total 1.6514546264e+10
# HELP go_memstats_buck_hash_sys_bytes Number of bytes used by the profiling bucket hash table.
# TYPE go_memstats_buck_hash_sys_bytes gauge
go_memstats_buck_hash_sys_bytes 1.581302e+06
# HELP go_memstats_frees_total Total number of frees.
# TYPE go_memstats_frees_total counter
go_memstats_frees_total 1.45861236e+08

......
1.5、Prometheus 规则配置

创建的发现规则如下:

- job_name: "kubernetes-pod"
  kubernetes_sd_configs:
    - role: pod
  relabel_configs:
    - source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_scrape]
      action: keep
      regex: true
    - source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_path]
      action: replace
      target_label: __metrics_path__
      regex: (.+)
    - source_labels:
        [__address__, __meta_kubernetes_pod_annotation_prometheus_io_port]
      action: replace
      target_label: __address__
      regex: ([^:]+)(?::\d+)?;(\d+)
      replacement: $1:$2
    - action: labelmap
      regex: __meta_kubernetes_service_label_(.+)
    - source_labels: [__meta_kubernetes_namespace]
      action: replace
      target_label: kubernetes_namespace
    - source_labels: [__meta_kubernetes_pod_name]
      action: replace
      target_label: kubernetes_pod_name

重新更新 secret 配置:

kubectl apply -f secret generic additional-configs --from-file=prometheus-additional.yaml -n monitoring

过一会儿我们再去看 Prometheus 的 targets 中查看采集的目标数据:

可以看到配置的 自动发现这个 job 已经生效了。切换到 Graph 下面可以看到很多关于 redis 的指标数据,我们选择任意一个指标,比如 redis_allocator_allocated_bytes,然后点击执行就可以看到对应的数据图表了:

1.6、Dashboard

选择导入ID为 「2751」 的模版。效果如下:

2、MySQL

1.1、mysqld_exporter

MySQL 没有自带 /metrics 接口供 Prometheus 使用,在这种情况下,我们也需要利用 exporter 服务来为 Prometheus 提供指标数据了。Prometheus 官方为许多应用就提供了对应的 exporter 应用,也有许多第三方的实现,我们可以前往官方网站进行查看:https://prometheus.io/docs/instrumenting/exporters/。

这里我们选择官方的 mysqld_exporter:https://github.com/prometheus/mysqld_exporter

mysqld_exporter 其支持的版本:

  • MySQL >= 5.6.
  • MariaDB >= 10.1
1.2、构建 sidecar

这里通过 mysqld_exporter 的服务来监控 MySQL 服务,我们以 sidecar 的形式和主应用部署在同一个 Pod 中,比如我们这里来部署一个 MySQL,并用 mysqld_exporter 的方式来采集监控数据供 Prometheus 使用。

如下资源清单文件:「promethues-mysql-deploy.yaml」

## Deployment
apiVersion: apps/v1
kind: Deployment
metadata:
  name: db-mall-mysql
  labels:
    app: mysql
spec:
  replicas: 1
  selector:
    matchLabels:
      app: mysql
  template:
    metadata:
      annotations:
        prometheus.io/scrape: "true"
        prometheus.io/port: "9104"
      labels:
        app: mysql
    spec:     
      containers:
      - name: mysql
        image: centos/mysql-57-centos7:latest
        ports:
        - containerPort: 3306
        env:
        - name: MYSQL_ROOT_PASSWORD    ## 配置Root用户默认密码
          value: "123456"
        resources:
          limits:
            cpu: 2000m
            memory: 512Mi
          requests:
            cpu: 2000m
            memory: 512Mi
        volumeMounts:
        - name: data
          mountPath: /var/lib/mysql
        - name: config
          mountPath: /etc/mysql/conf.d/my.cnf
          subPath: my.cnf
        - name: localtime
          readOnly: true
          mountPath: /etc/localtime
      - name: mysql-exporter
        image: prom/mysqld-exporter:latest
        env:
        - name: DATA_SOURCE_NAME
          value: "root:123456@(db-mall-mysql:3306)/"
        resources:
          requests:
            cpu: 100m
            memory: 100Mi
        ports:
        - containerPort: 9104
      volumes:
      - name: data
        persistentVolumeClaim:
          claimName: mysql
      - name: config      
        configMap:
          name: mysql-config
      - name: localtime
        hostPath:
          type: File
          path: /etc/localtime
---
## Service
apiVersion: v1
kind: Service
metadata:
  name: db-mall-mysql
  labels:
    app: mysql
spec:
  type: NodePort
  ports:
  - name: mysql
    port: 3306
    targetPort: 3306
    nodePort: 30336
  - name: prom
    port: 9104
    targetPort: 9104
  selector:
    app: mysql
1.3、测试

创建完成后,我们可以看到 MySQL 的 Pod 里面包含有两个容器:

$ kubectl get pods -n mall
NAME                                    READY   STATUS    RESTARTS   AGE
db-mall-mysql-6b69bdddd6-7crqg          2/2     Running   0          4d20h

$ kubectl get svc -n mall
NAME                   TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)                               AGE
db-mall-mysql          NodePort    10.96.106.73    <none>        3306:30336/TCP,9104:30602/TCP         4d20h

我们可以通过 9104 端口来校验是否能够采集到数据:

$ curl 10.96.106.73:9104/metrics
 TYPE mysql_global_variables_ft_query_expansion_limit gauge
mysql_global_variables_ft_query_expansion_limit 20
# HELP mysql_global_variables_general_log Generic gauge metric from SHOW GLOBAL VARIABLES.
# TYPE mysql_global_variables_general_log gauge
mysql_global_variables_general_log 0
# HELP mysql_global_variables_group_concat_max_len Generic gauge metric from SHOW GLOBAL VARIABLES.
# TYPE mysql_global_variables_group_concat_max_len gauge
mysql_global_variables_group_concat_max_len 1024
# HELP mysql_global_variables_gtid_executed_compression_period Generic gauge metric from SHOW GLOBAL VARIABLES.
# TYPE mysql_global_variables_gtid_executed_compression_period gauge
mysql_global_variables_gtid_executed_compression_period 1000
# HELP mysql_global_variables_gtid_mode Generic gauge metric from SHOW GLOBAL VARIABLES.
# TYPE mysql_global_variables_gtid_mode gauge

......

过一会儿我们再去看 Prometheus 的 targets 中查看采集的目标数据:

可以看到配置的 自动发现这个 job 已经生效了。切换到 Graph 下面可以看到很多关于 MySQL 的指标数据,我们选择任意一个指标,比如 mysql_exporter_collector_duration_seconds,然后点击执行就可以看到对应的数据图表了:

1.4、配置 Dashboard

选择导入ID为 「7362」 的模版。效果如下:

选择导入ID为 「6239」 的模版。效果如下:

3、Mongo

1.1、mongo_exporter

mongodb 没有自带 /metrics 接口供 Prometheus 使用,在这种情况下,我们就需要利用 exporter 服务来为 Prometheus 提供指标数据了,我们可以前往官方网站进行查看:https://prometheus.io/docs/instrumenting/exporters/。

这里我们选择 mongodb_exporter:https://hub.docker.com/r/noenv/mongo-exporter

1.2、构建 sidecar

这里通过 mongodb_exporter 的服务来监控 mongodb 服务,我们以 sidecar 的形式和主应用部署在同一个 Pod 中,比如我们这里来部署一个 mongodb ,并用 mongodb _exporter 的方式来采集监控数据供 Prometheus 使用。

如下资源清单文件:「promethues-mongo-deploy.yaml」

## Service
apiVersion: v1
kind: Service
metadata:
  name: db-mongo
  labels:
    app: mongo
spec:
  ports:
    - name: mongo
      port: 27017
      targetPort: 27017
    - name: prom
      port: 9104
      targetPort: 9104
  selector:
    app: mongo
---
## Deployment
apiVersion: apps/v1
kind: Deployment
metadata:
  name: db-mongo
  labels:
    app: mongo
spec:
  replicas: 1
  selector:
    matchLabels:
      app: mongo
  template:
    metadata:
      annotations:
        prometheus.io/scrape: "true"
        prometheus.io/port: "9104"
      labels:
        app: mongo
    spec:
      containers:
        - name: mongo
          image: mongo:4.2.5
          command:
            - sh
            - -c
            - "exec mongod -f /etc/mongod.conf"
          ports:
            - containerPort: 27017
          resources:
            limits:
              cpu: 1000m
              memory: 512Mi
            requests:
              cpu: 1000m
              memory: 512Mi
          livenessProbe:
            initialDelaySeconds: 30
            periodSeconds: 10
            timeoutSeconds: 5
            successThreshold: 1
            failureThreshold: 3
            tcpSocket:
              port: 27017
          readinessProbe:
            initialDelaySeconds: 10
            periodSeconds: 10
            timeoutSeconds: 5
            successThreshold: 1
            failureThreshold: 3
            tcpSocket:
              port: 27017
          volumeMounts:
            - name: data
              mountPath: /data/middleware-data/mongodb/
            - name: config
              mountPath: /etc/mongod.conf
              subPath: mongodb.conf
            - name: localtime
              readOnly: true
              mountPath: /etc/localtime
        - name: mongo-exporter
          image: noenv/mongo-exporter:latest
          args:
            [
              "--web.listen-address=:9104",
              "--mongodb.uri",
              "mongodb://db-mongo:27017",
            ]
          resources:
            requests:
              cpu: 100m
              memory: 100Mi
          ports:
            - containerPort: 9104
      volumes:
        - name: data
          persistentVolumeClaim:
            claimName: mongo
        - name: config
          configMap:
            name: mongo-config
        - name: localtime
          hostPath:
            type: File
            path: /etc/localtime

可以看到上面我们在 mongodb 这个 Pod 中包含了两个容器,一个就是 mongodb 本身的主应用,另外一个容器就是 mongodb _exporter。

1.3、测试

创建完成后,我们可以看到 mongodb 的 Pod 里面包含有两个容器:

$ kubectl get pods -n mall
NAME                                    READY   STATUS    RESTARTS   AGE
db-mongo-5596947577-7bspt               2/2     Running   4          4d5h

$ kubectl get svc -n mall
NAME                   TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)                               AGE
db-mongo               ClusterIP   10.96.239.99    <none>        27017/TCP,9104/TCP                    4d5h

我们可以通过 9104 端口来校验是否能够采集到数据:

$ curl 10.96.239.99:9104/metrics
# HELP go_gc_duration_seconds A summary of the pause duration of garbage collection cycles.
# TYPE go_gc_duration_seconds summary
go_gc_duration_seconds{quantile="0"} 7.2981e-05
go_gc_duration_seconds{quantile="0.25"} 0.000132539
go_gc_duration_seconds{quantile="0.5"} 0.000185705
go_gc_duration_seconds{quantile="0.75"} 0.000327893
go_gc_duration_seconds{quantile="1"} 0.002464757
go_gc_duration_seconds_sum 1.023320185
go_gc_duration_seconds_count 3033
# HELP go_goroutines Number of goroutines that currently exist.
# TYPE go_goroutines gauge
go_goroutines 12

......

过一会儿我们再去看 Prometheus 的 targets 中查看采集的目标数据:

可以看到配置的 自动发现这个 job 已经生效了。切换到 Graph 下面可以看到很多关于 mongodb 的指标数据,我们选择任意一个指标,比如 mongodb_instance_local_time,然后点击执行就可以看到对应的数据图表了:

1.4、配置 Dashboard

选择导入ID为 「2583」 的模版。效果如下:

选择导入ID为 「7353」 的模版。效果如下:

4、RabbitMQ

1.1、rabbitmq_exporter

rabbitmq 没有自带 /metrics 接口供 Prometheus 使用,在这种情况下,我们就需要利用 exporter 服务来为 Prometheus 提供指标数据了。Prometheus 官方为许多应用就提供了对应的 exporter 应用,也有许多第三方的实现,我们可以前往官方网站进行查看:https://prometheus.io/docs/instrumenting/exporters/。

这里我们选择官方的 rabbitmq_exporter:https://github.com/kbudde/rabbitmq_exporter

1.2、构建 sidecar

这里通过 rabbitmq_exporter 的服务来监控 rabbitmq 服务,我们以 sidecar 的形式和主应用部署在同一个 Pod 中,比如我们这里来部署一个 rabbitmq,并用 rabbitmq_exporter 的方式来采集监控数据供 Prometheus 使用。

如下资源清单文件:「promethues-rabbitmq-deploy.yaml」

## Service
apiVersion: v1
kind: Service
metadata:
  name: cloud-rabbitmq
  labels:
    app: rabbitmq
spec:
  selector:
    app: rabbitmq
  ports:
    - name: rabbitmq
      port: 5672
      targetPort: 5672
    - name: rabbitmq-management
      port: 15672
      targetPort: 15672
    - name: prom
      port: 9419
      targetPort: 9419
---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: cloud-rabbitmq
spec:
  rules:
    - host: cloud-rabbitmq.mall.demo.7d.com
      http:
        paths:
          - backend:
              serviceName: cloud-rabbitmq
              servicePort: 15672
---
## Deployment
apiVersion: apps/v1
kind: Deployment
metadata:
  name: cloud-rabbitmq
  labels:
    app: rabbitmq
spec:
  replicas: 1
  selector:
    matchLabels:
      app: rabbitmq
  template:
    metadata:
      annotations:
        prometheus.io/scrape: "true"
        prometheus.io/port: "9419"
      labels:
        app: rabbitmq
    spec:
      containers:
        - name: rabbitmq
          image: rabbitmq:3.7.15-management
          ports:
            - containerPort: 5672
          resources:
            limits:
              cpu: 500m
              memory: 512Mi
            requests:
              cpu: 500m
              memory: 512Mi
          livenessProbe:
            initialDelaySeconds: 30
            periodSeconds: 10
            timeoutSeconds: 5
            successThreshold: 1
            failureThreshold: 3
            tcpSocket:
              port: 5672
          readinessProbe:
            initialDelaySeconds: 10
            periodSeconds: 10
            timeoutSeconds: 5
            successThreshold: 1
            failureThreshold: 3
            tcpSocket:
              port: 5672
          volumeMounts:
            - name: data
              mountPath: /var/lib/rabbitmq/
            - name: localtime
              readOnly: true
              mountPath: /etc/localtime
        - name: rabbitmq-exporter
          image: kbudde/rabbitmq-exporter:latest
          env:
            - name: RABBIT_URL
              value: "http://cloud-rabbitmq:15672" 
            - name: RABBIT_USER
              value: "guest"  
            - name: RABBIT_PASSWORD
              value: "guest"  
            - name: PUBLISH_PORT
              value: "9419"         
          resources:
            requests:
              cpu: 100m
              memory: 100Mi
          ports:
            - containerPort: 9419
      volumes:
        - name: data
          persistentVolumeClaim:
            claimName: rabbitmq
        - name: localtime
          hostPath:
            type: File
            path: /etc/localtime

可以看到上面我们在 rabbitmq这个 Pod 中包含了两个容器,一个就是 edis 本身的主应用,另外一个容器就是 r_exporter。

1.3、测试

创建完成后,我们可以看到 rabbitmq 的 Pod 里面包含有两个容器:

$ kubectl get pods -n mall
NAME                                    READY   STATUS    RESTARTS   AGE
cloud-rabbitmq-559c99cffd-22m67         2/2     Running   2          42h

$ kubectl get svc -n mall
NAME                   TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)                               AGE
cloud-rabbitmq         ClusterIP   10.96.67.143    <none>        5672/TCP,15672/TCP,9419/TCP           3d7h

我们可以通过 9121 端口来校验是否能够采集到数据:

$ curl 10.96.67.143:9419/metrics
# HELP go_gc_duration_seconds A summary of the pause duration of garbage collection cycles.
# TYPE go_gc_duration_seconds summary
go_gc_duration_seconds{quantile="0"} 1.938e-05
go_gc_duration_seconds{quantile="0.25"} 3.0385e-05
go_gc_duration_seconds{quantile="0.5"} 5.2105e-05
go_gc_duration_seconds{quantile="0.75"} 8.8354e-05
go_gc_duration_seconds{quantile="1"} 0.00257348
go_gc_duration_seconds_sum 0.139414322
go_gc_duration_seconds_count 1358
# HELP go_goroutines Number of goroutines that currently exist.
# TYPE go_goroutines gauge
go_goroutines 14
# HELP go_info Information about the Go environment.
# TYPE go_info gauge
go_info{version="go1.14.3"} 1

......

过一会儿我们再去看 Prometheus 的 targets 中查看采集的目标数据:

可以看到配置的 自动发现这个 job 已经生效了。切换到 Graph 下面可以看到很多关于 rabbitmq 的指标数据,我们选择任意一个指标,比如 rabbitmq_fd_used,然后点击执行就可以看到对应的数据图表了:

1.4、配置 Dashboard

选择导入ID为 「4279」 的模版。效果如下:

六、小结

Kubernetes 与 Prometheus 有着十分相似的历程,均是源自Google内部多年的运维经验,并且相继从CNCF基金会正式毕业。它们分别代表了云原生模式下容器编排以及监控的事实标准。

本文首先介绍了Kubernetes 下 Prometheus 自动发现的基本原理。然后介绍了几个常见中间件服务发现和监控对象是如何配置。最后通过Grafana可视化展示监控界面。

本文源码:

  • https://github.com/zuozewei/blog-example/tree/master/Kubernetes/k8s-kube-promethues-auto-discover
本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2021-02-27,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 7DGroup 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、背景介绍
  • 二、什么是服务发现?
  • 三、规则解析
  • 四、如何实现?
    • 1、创建发现规则
      • 2、创建Secret 对象
        • 3、创建资源对象
          • 4、查看配置
            • 5、创建 RBAC 权限
            • 五、常用中间件如何落地 ?
              • 1、Redis
                • 1.1、原理
                • 1.2、redis_exporter
                • 1.3、构建 sidecar
                • 1.4、测试
                • 1.5、Prometheus 规则配置
                • 1.6、Dashboard
              • 2、MySQL
                • 1.1、mysqld_exporter
                • 1.2、构建 sidecar
                • 1.3、测试
                • 1.4、配置 Dashboard
              • 3、Mongo
                • 1.1、mongo_exporter
                • 1.2、构建 sidecar
                • 1.3、测试
                • 1.4、配置 Dashboard
              • 4、RabbitMQ
                • 1.1、rabbitmq_exporter
                • 1.2、构建 sidecar
                • 1.3、测试
                • 1.4、配置 Dashboard
            • 六、小结
            相关产品与服务
            容器服务
            腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
            领券
            问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档