11 - Metrics - 观察系统的健康指标 (5/6) - 使用 Metricbeat 掌握 Infrastructure 的健康状态 Kubernetes 篇

Metrics - 观察系统的健康指标 系列文章


本篇学习重点

  • Metricbeat 能够收集 Kubernetes 哪些 Metrics
  • 如何使用 Metricbeat 来收集 Kubernetes 的 Metrics
  • 在 Kibana 上有提供哪些方式,能查看 Metricbeats 所收集的 Metrics

前一篇文章介绍了如何使用 Metricbeat 来掌握 Docker 环境 Infrastructure 的健康状态,这一篇将来说明 Kubernetes 的环境,我们要如何使用 Metricbeat 来掌握各种健康状态的 Metrics。

Metricbeat 在 Kubernetes 环境中,能收集哪些 Metrics

这边我们分成以下三个部份来说明:

  • System Metrics: 我们在 Kubernetes 环境中的每个 Node,我们都应该要收集这些 Nodes 的系统 Metrics,所以这边就会要使用 Metricbeat 的 system module 来收集。
  • Kubernetes Metrics: 在 Kubernetes 的环境之中,Kubernetes 本身有许多运作的功能与机制,这部份 Metricbeat 有特别针对 Kubernetes 开发 kubernetes module 里面有收集非常丰富的 Metrics,下面会针对这个 module 独立介绍。
  • 其他运作在 Kubernetes 上的服务的 Metrics: 这部份就会使用 Metricbeat 所支援的各种服务的 modules,细节可以参考 官方文件 Metricbeat Modules [1]。

Metricbeat Kubernetes Module

这边我们来说明 Metricbeat 针对 Kubernetes 所开发的 Module 有哪些功能。

Kubernetes module 有收集以下 Kubernetes 元件的 Metrics:

由於这些元件之中, kubeletproxy 是运作在 Cluster 当中的每个 Node 身上,所以会是 Node 层级,而其他的元件是运作在 Cluster 层级,因此不同层级也会有不同的布署与收集方式,以下我整理一个表格,将 Kubernetes module 所支援的 metricset 进行分类说明。

Metricset 名称 收集的方式 层级 适用的布署方式
container, node, pod, system, volume kubelet endpoint (Default HTTP port: 10250) Node DaemonSet
state_node, state_daemonset, state_deployment, state_replicaset, state_statefulset, state_pod, state_container, state_cronjob, state_resourcequota, state_service, state_persistentvolume, state_persistentvolumeclaim, state_storageclass, event kibe-state-metrics 需另外安装的 Service (Standard Example HTTP port: 8080) Cluster DaemonSet 之中的 Leader Pod
apiserver Kubernetes /metrics API Cluster DaemonSet 之中的 Leader Pod
proxy proxy endpoint (Default HTTP port: 10249) Node DaemonSet
scheduler scheduler endpoint 需另外 create kube-scheduler service (Default HTTP port: 10259) Cluster DaemonSet 之中的 Leader Pod
controller-manager controller-manager endpoint 需另外 create kube-controller-manager service (Default HTTP port: 10257) Cluster DaemonSet 之中的 Leader Pod

使用 Metricbeat 监控 Kubernetes 的 Metrics

接下来,我们要来实际说明布署的方式,在进行实作之前,先介绍在 Kubernetes 上部署 Metricbeat 的方法。

在 Kubernetes 上部署 Metricbeat 的方法

首先,要在 Kubernetes 里布署 Metricbeat 的方式有两种,这边先简介这两种的概念,接下来的实例,将带大家了解如何实作。

DaemonSet

由於 Kubernetes DaemonSet 的设计,让我们能够轻易的确保 Metricbeat 能运作且常驻在 Kubernetes Cluster 中的每一个 Node 身上,并且可以在这个 Node 上只启动一个 Instance (一个 Pod),让这个 Metricbeat 负责收集这个 Node 的 System Metrics 以及运作在这个 Node 身上其他 Pods 的各种服务的 Metrics。

因此在使用 Metricbeat 来监控 Kubernetes Cluster 的基本配置方式,就是将 Metricbeat 布署成 DaemonSet。

另外 Metricbeat 有实作 Leader Election [2],在 Cluster DaemonSet 中只有一个 Metricbeat Pod,会被选为 leader,我们就可以使用这个 leader pod 来负责收集 Cluster 层级的 Metrics,避免 Cluster 中若是有多个 Metricbeat 都在收集 Cluster 层集的 Metrics,会收集到重覆的资料。

Deployment

除了使用 DaemonSet 的方式来布署,我们当然也可以使用 Deployment 的方式来布署 Metricbeat,但是什麽时候会用到这种方法呢?

主要是当 Cluster 规模愈大时,上面所提到 leader pod 很可能会因为资源不足,无法处理这样大量级的资料,这时就应该考虑使用独立的 Instance 来布署 Metricbeat,以专门收集 Cluster 层级的 Metrics。

实际的布署

我们这边使用官方提供的一个 Metricbeat-Kubernetes 范例 [3] 来进行拆解说明。

ConfigMap metricbeat-deamonset-config

在这个 ConfigMap 当中,定义了主要运作成为 DaemonSet 的 Metricbeat 的主要设定,也就是 metricbeat.yml 的配置。

apiVersion: v1
kind: ConfigMap
metadata:
  name: metricbeat-daemonset-config
  namespace: kube-system
  labels:
    k8s-app: metricbeat
data:
  metricbeat.yml: |-
    metricbeat.config.modules:
      # Mounted `metricbeat-daemonset-modules` configmap:
      path: ${path.config}/modules.d/*.yml
      # Reload module configs as they change:
      reload.enabled: false

    metricbeat.autodiscover:
      providers:
        - type: kubernetes
          scope: cluster
          node: ${NODE_NAME}
          unique: true
          templates:
            - config:
                - module: kubernetes
                  hosts: ["kube-state-metrics:8080"]
                  period: 10s
                  add_metadata: true
                  metricsets:
                    - state_node
                    - state_deployment
                    - state_daemonset
                    - state_replicaset
                    - state_pod
                    - state_container
                    - state_cronjob
                    - state_resourcequota
                    - state_statefulset
                    - state_service
                - module: kubernetes
                  metricsets:
                    - apiserver
                  hosts: ["https://${KUBERNETES_SERVICE_HOST}:${KUBERNETES_SERVICE_PORT}"]
                  bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token
                  ssl.certificate_authorities:
                    - /var/run/secrets/kubernetes.io/serviceaccount/ca.crt
                  period: 30s
                # Uncomment this to get k8s events:
                #- module: kubernetes
                #  metricsets:
                #    - event
        # To enable hints based autodiscover uncomment this:
        #- type: kubernetes
        #  node: ${NODE_NAME}
        #  hints.enabled: true

    processors:
      - add_cloud_metadata:

    cloud.id: ${ELASTIC_CLOUD_ID}
    cloud.auth: ${ELASTIC_CLOUD_AUTH}

    output.elasticsearch:
      hosts: ['${ELASTICSEARCH_HOST:elasticsearch}:${ELASTICSEARCH_PORT:9200}']
      username: ${ELASTICSEARCH_USERNAME}
      password: ${ELASTICSEARCH_PASSWORD}

这里面的配置我们分成以下来说明:

  • 有定义下面另一组 ConfigMap metricbeat-daemonset-modules 要载入到 modules.d 目录底的设定。
  • 定义 autodiscover 的设定,这里指定到 scope: cluster 以及 unique: true,代表这是在整个 DaemonSet 当中,只有 leader 这个唯一的 Pod 会运行,也因此里面所描述的 Metricset 会是 Cluster 等级的,像是 state_* 以及 event 这样的 Metricsets。

ConfigMap metricbeat-daemonset-modules

在这个 ConfigMap 里,定义了主要的 DaemonSet 要执行的 Metricbeat 的模组有哪些

apiVersion: v1
kind: ConfigMap
metadata:
  name: metricbeat-daemonset-modules
  namespace: kube-system
  labels:
    k8s-app: metricbeat
data:
  system.yml: |-
    - module: system
      period: 10s
      metricsets:
        - cpu
        - load
        - memory
        - network
        - process
        - process_summary
        #- core
        #- diskio
        #- socket
      processes: ['.*']
      process.include_top_n:
        by_cpu: 5      # include top 5 processes by CPU
        by_memory: 5   # include top 5 processes by memory

    - module: system
      period: 1m
      metricsets:
        - filesystem
        - fsstat
      processors:
      - drop_event.when.regexp:
          system.filesystem.mount_point: '^/(sys|cgroup|proc|dev|etc|host|lib|snap)($|/)'
  kubernetes.yml: |-
    - module: kubernetes
      metricsets:
        - node
        - system
        - pod
        - container
        - volume
      period: 10s
      host: ${NODE_NAME}
      hosts: ["https://${NODE_NAME}:10250"]
      bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token
      ssl.verification_mode: "none"
      # If there is a CA bundle that contains the issuer of the certificate used in the Kubelet API,
      # remove ssl.verification_mode entry and use the CA, for instance:
      #ssl.certificate_authorities:
        #- /var/run/secrets/kubernetes.io/serviceaccount/service-ca.crt
    # Currently `proxy` metricset is not supported on Openshift, comment out section
    - module: kubernetes
      metricsets:
        - proxy
      period: 10s
      host: ${NODE_NAME}
      hosts: ["localhost:10249"]

这里面的配置我们分成以下来说明:

  • 由於这会是每个 Node 都会运行一组的 DaemonSet,所以会要收集系统的 Metrics,这边有定义了 system.yml 的 System module。
  • 同样的每个 Node 也都要收集 Node 层级的 Kubernetes Metrics,所以这边有定义 kuebernetes.yml 使用 Kubernetes module,并且宣告 nodesystempodcontainervolumeproxy 这些 Metricsets。
  • 另外针对不同的 metricset 的来源,会从 kubelet 的 port 10250proxy 的 port 10249 取得 Metrics。

DaemoneSet metricbeat

接下来就是主要的 DaemonSet - metricbeat

# Deploy a Metricbeat instance per node for node metrics retrieval
apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: metricbeat
  namespace: kube-system
  labels:
    k8s-app: metricbeat
spec:
  selector:
    matchLabels:
      k8s-app: metricbeat
  template:
    metadata:
      labels:
        k8s-app: metricbeat
    spec:
      serviceAccountName: metricbeat
      terminationGracePeriodSeconds: 30
      hostNetwork: true
      dnsPolicy: ClusterFirstWithHostNet
      containers:
      - name: metricbeat
        image: docker.elastic.co/beats/metricbeat:7.14.2
        args: [
          "-c", "/etc/metricbeat.yml",
          "-e",
          "-system.hostfs=/hostfs",
        ]
        env:
        - name: ELASTICSEARCH_HOST
          value: elasticsearch
        - name: ELASTICSEARCH_PORT
          value: "9200"
        - name: ELASTICSEARCH_USERNAME
          value: elastic
        - name: ELASTICSEARCH_PASSWORD
          value: changeme
        - name: ELASTIC_CLOUD_ID
          value:
        - name: ELASTIC_CLOUD_AUTH
          value:
        - name: NODE_NAME
          valueFrom:
            fieldRef:
              fieldPath: spec.nodeName
        securityContext:
          runAsUser: 0
          # If using Red Hat OpenShift uncomment this:
          #privileged: true
        resources:
          limits:
            memory: 200Mi
          requests:
            cpu: 100m
            memory: 100Mi
        volumeMounts:
        - name: config
          mountPath: /etc/metricbeat.yml
          readOnly: true
          subPath: metricbeat.yml
        - name: data
          mountPath: /usr/share/metricbeat/data
        - name: modules
          mountPath: /usr/share/metricbeat/modules.d
          readOnly: true
        - name: proc
          mountPath: /hostfs/proc
          readOnly: true
        - name: cgroup
          mountPath: /hostfs/sys/fs/cgroup
          readOnly: true
      volumes:
      - name: proc
        hostPath:
          path: /proc
      - name: cgroup
        hostPath:
          path: /sys/fs/cgroup
      - name: config
        configMap:
          defaultMode: 0640
          name: metricbeat-daemonset-config
      - name: modules
        configMap:
          defaultMode: 0640
          name: metricbeat-daemonset-modules
      - name: data
        hostPath:
          # When metricbeat runs as non-root user, this directory needs to be writable by group (g+w)
          path: /var/lib/metricbeat-data
          type: DirectoryOrCreate

这里面的配置我们分成以下来说明:

  • 这边有使用到 DaemonSet 的 selectortemplate ,并指定 Label k8s-app: metricbeat
  • 使用 serviceAccountName: metricbeat
  • /proc/sys/fs/cgroup 给 mount 到 /hostfs 底下,并且在启动时,指定给 metricbeat: -system.hostfs=/hostfs
  • 将 Elasticsearch 相关的环境变数指定预设定。
  • mount 前面指定好的 ConfigMap metricbeat-daemonset-configmetricbeat-daemonset-modules

ServiceAccount 与相关的权限设定

这部份就不多解释,请大家自己从设定来参考。

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: metricbeat
subjects:
- kind: ServiceAccount
  name: metricbeat
  namespace: kube-system
roleRef:
  kind: ClusterRole
  name: metricbeat
  apiGroup: rbac.authorization.k8s.io
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: metricbeat
  namespace: kube-system
subjects:
  - kind: ServiceAccount
    name: metricbeat
    namespace: kube-system
roleRef:
  kind: Role
  name: metricbeat
  apiGroup: rbac.authorization.k8s.io
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: metricbeat-kubeadm-config
  namespace: kube-system
subjects:
  - kind: ServiceAccount
    name: metricbeat
    namespace: kube-system
roleRef:
  kind: Role
  name: metricbeat-kubeadm-config
  apiGroup: rbac.authorization.k8s.io
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: metricbeat
  labels:
    k8s-app: metricbeat
rules:
- apiGroups: [""]
  resources:
  - nodes
  - namespaces
  - events
  - pods
  - services
  verbs: ["get", "list", "watch"]
# Enable this rule only if planing to use Kubernetes keystore
#- apiGroups: [""]
#  resources:
#  - secrets
#  verbs: ["get"]
- apiGroups: ["extensions"]
  resources:
  - replicasets
  verbs: ["get", "list", "watch"]
- apiGroups: ["apps"]
  resources:
  - statefulsets
  - deployments
  - replicasets
  verbs: ["get", "list", "watch"]
- apiGroups:
  - ""
  resources:
  - nodes/stats
  verbs:
  - get
- nonResourceURLs:
  - "/metrics"
  verbs:
  - get
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: metricbeat
  # should be the namespace where metricbeat is running
  namespace: kube-system
  labels:
    k8s-app: metricbeat
rules:
  - apiGroups:
      - coordination.k8s.io
    resources:
      - leases
    verbs: ["get", "create", "update"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: metricbeat-kubeadm-config
  namespace: kube-system
  labels:
    k8s-app: metricbeat
rules:
  - apiGroups: [""]
    resources:
      - configmaps
    resourceNames:
      - kubeadm-config
    verbs: ["get"]
---
apiVersion: v1
kind: ServiceAccount
metadata:
  name: metricbeat
  namespace: kube-system
  labels:
    k8s-app: metricbeat

安装 Kube-state-metrics 以提供 Metricbeat 所需要的 Metrics

由於前面所提到的 kube-state-metrics 并非是 Kubernetes Cluster 预设启用的功能,这部份会需要透过另外安装才能启用这个服务。

以下使用最基本的简易安装方式,细节请参考 GitHub kube-state-metrics [4]。

先抓下 GitHub 上专案中建立好的 examples 配置:

git clone https://github.com/kubernetes/kube-state-metrics.git

使用 examples 中的 standard 配置来建立服务:

cd kube-state-metrics
kubectl apply -f examples/standard

成功建立之後,就可以在 kube-system 的 namespace 中看到 kube-state-metricspod 以及对外开启 8080 port 的 service

11-k9s-kube-state-metrics

这边使用的工具是 k9s,蛮好用的 Kubernetes 管理工具。

在图中我们可以看到,由於 kube-state-metrics 是指定给 leader 才会执行,所以我们在 leader 这台 pod 的 logs 才会看到这资讯。

使用 Autodiscovery 透过 Annotation 自动找寻需监控的 Pods

其他运作在 Kubernetes 上的 Service,若是要使用 Metricbeat 的其他 modules 来取得 Metrics,建议可以使用 Autodiscovery 针对 Kubernetes Annotation 所支援的自动监控的功能。

metricbeat.autodiscover:
  providers:
    - type: kubernetes
      templates:
        - condition:
            contains:
              kubernetes.labels.app: "redis"
          config:
            - module: redis
              metricsets: ["info", "keyspace"]
              hosts: "${data.host}:6379"
              password: "${REDIS_PASSWORD}"

例如我们可以针对 kubernetes.labels.appredis 的 pod,设定使用 redis module 来取得 Redis 的 Metrics , 并且套用上面所定义的 config 配置。

在 Kibana 检视 Kubernetes 的 Metrics

在以上设定安装完成之後,我们可以透过 Kibana 来查看 Metricbeat 所针对 Kubernetes 收集到的 Metrics。

Kibana Observability Metrics

在 Kibana > Observability > Metrics 里的 Inventory 中,我们可以针对 Show 指定为 Kubernetes Pods ,并且可以透过 Group by 的方式进行分类,结果如下图。

11-kibana-observability-metrics-k8s

其他 Inventory 的使用方式,可以参考先前的文章 09 - Metrics - 观察系统的健康指标 (3) - 使用 Metricbeat 掌握 Infrastructure 的健康状态 Host 篇 的介绍。

Metricbeat 内建的 Dashboard

由於 Inventory 的检视方式较为是 Infrastructure 整体的健康度,而 Metricbeat 也有为 Kubernetes 建立了四种 Dashboard,可以让我们直接使用。

(由於我的测试环境有些资讯没有呈现出来,所以有几张图我直接以官方网站的图来呈现)

Cluster Overview

11-kibana-dashboard-k8s-overview

Controller Manager

11-metricbeat-kubernetes-controllermanager

Scheduler

11-metricbeat_kubernetes_scheduler

Proxy

11-metricbeat-kubernetes-proxy


Metricbeat 针对 Kubernetes 所收集的资讯相当详细,相信可以对於我们监控管理 Kubernetes Cluster 有很大的帮助,特别是这些资料进入 Elasticsearch 之後,还能和其他 Obersevability 的资讯进行整合使用,应用的空间还很大呢!

参考资讯

  1. 官方文件 - Metricbeat Modules
  2. Kubernetes client-go - Leader Election
  3. Metricbeat-Kubernetes 范例
  4. GitHub kube-state-metrics

查看最新 Elasticsearch 或是 Elastic Stack 教育训练资讯: https://training.onedoggo.com
欢迎追踪我的 FB 粉丝页: 乔叔 - Elastic Stack 技术交流
不论是技术分享的文章、公开线上分享、或是实体课程资讯,都会在粉丝页通知大家哦!


<<:  [Day16] 再战SAT

>>:  [DAY 11] RDS 之 multi AZ 和 security 相关

电子书阅读器上的浏览器 [Day11] 移植 Firefox 阅读模式

这一篇的技术成份稍微高一点点。要谈到的功能,从一开始开发浏览器就有想要做,但是一直找不到比较好的实作...

【30天Lua重拾笔记】系列目录

最全面的Lua入门学习…笔记草稿?No, No, No, No, No 在30天要所有东西提到貌似是...

System Design: 读书心得2

原文在这: Title: From a Side Project to a Startup - th...

每秒几十万上下 - 1分K 当冲策略是否有搞头 ?!

最近股市只有一个字 怕.jpg 今天研究了大多的回测策略,大多都是以日计算,想想可不可以用 1分K ...

Day 8 jinja (3)

前言 今天一样是 jinja 的内容,会讲到模板的继承。这个在网页有固定排版或是格式的时候很好用,不...