本篇學習重點
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 獨立介紹。
Metricbeat Kubernetes Module
這邊我們來說明 Metricbeat 針對 Kubernetes 所開發的 Module 有哪些功能。
Kubernetes module 有收集以下 Kubernetes 元件的 Metrics:
由於這些元件之中, kubelet
和 proxy
是運作在 Cluster 當中的每個 Node 身上,所以會是 Node 層級,而其他的元件是運作在 Cluster 層級,因此不同層級也會有不同的佈署與收集方式,以下我整理一個表格,將 Kubernetes module 所支援的 metricset 進行分類說明。
Metricset 名稱 收集的方式 層級 適用的佈署方式 container
, node
, pod
, system
, volume
kubelet endpoint (Default HTTP port: 10250
)
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
)
proxy endpoint (Default HTTP port: 10249
)
scheduler endpoint 需另外 create kube-scheduler
service (Default HTTP port: 10259
)
controller-manager endpoint 需另外 create kube-controller-manager
service (Default HTTP port: 10257
)
使用 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
的配置。
Copy 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 的模組有哪些
Copy 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,並且宣告 node
、system
、pod
、container
、volume
、proxy
這些 Metricsets。
另外針對不同的 metricset 的來源,會從 kubelet
的 port 10250
及 proxy
的 port 10249
取得 Metrics。
DaemoneSet metricbeat
接下來就是主要的 DaemonSet - metricbeat
Copy # 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 的 selector
與 template
,並指定 Label k8s-app: metricbeat
。
使用 serviceAccountName: metricbeat
。
將 /proc
、/sys/fs/cgroup
給 mount 到 /hostfs
底下,並且在啟動時,指定給 metricbeat: -system.hostfs=/hostfs
。
將 Elasticsearch 相關的環境變數指定預設定。
mount 前面指定好的 ConfigMap metricbeat-daemonset-config
與 metricbeat-daemonset-modules
。
ServiceAccount 與相關的權限設定
這部份就不多解釋,請大家自己從設定來參考。
Copy 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 配置:
Copy git clone https://github.com/kubernetes/kube-state-metrics.git
使用 examples 中的 standard
配置來建立服務:
Copy cd kube-state-metrics
kubectl apply -f examples/standard
成功建立之後,就可以在 kube-system
的 namespace 中看到 kube-state-metrics
的 pod
以及對外開啟 8080
port 的 service
。
這邊使用的工具是 k9s ,蠻好用的 Kubernetes 視覺化管理工具。
在圖中我們可以看到,由於 kube-state-metrics
是指定給 leader 才會執行,所以我們在 leader 這台 pod 的 logs 才會看到這資訊。
使用 Autodiscovery 透過 Annotation 自動找尋需監控的 Pods
其他運作在 Kubernetes 上的 Service,若是要使用 Metricbeat 的其他 modules 來取得 Metrics,建議可以使用 Autodiscovery 針對 Kubernetes Annotation 所支援的自動監控的功能。
Copy 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.app
為 redis
的 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 的方式進行分類,結果如下圖。
其他 Inventory 的使用方式,可以參考先前的文章 09 - Metrics - 觀察系統的健康指標 (3) - 使用 Metricbeat 掌握 Infrastructure 的健康狀態 Host 篇 的介紹。
Metricbeat 內建的 Dashboard
由於 Inventory 的檢視方式較為是 Infrastructure 整體的健康度,而 Metricbeat 也有為 Kubernetes 建立了四種 Dashboard,可以讓我們直接使用。
(由於我的測試環境有些資訊沒有呈現出來,所以有幾張圖我直接以官方網站 的圖來呈現)
Cluster Overview
Controller Manager
Scheduler
Proxy
Metricbeat 針對 Kubernetes 所收集的資訊相當詳細,相信可以對於我們監控管理 Kubernetes Cluster 有很大的幫助,特別是這些資料進入 Elasticsearch 之後,還能和其他 Obersevability 的資訊進行整合使用,應用的空間還很大呢!
參考資訊