Exporter.png

本文已经收录在 Prometheus 合集 Prometheus 都可以采集那些指标?-- 常用 Exporter 合集 中。

对于 Kubernetes 的监控其实是无法通过一个组件来完成监控的,这是一个很庞大的系统。目前来说监控一个 Kubernetes 最少需要这么几个组件:

  • Node Exporter :Prometheus 出品,监控所有的宿主机
  • cAdvisor : Google 出品,监控所有的容器
  • kube-state-metrics :Kubernetes 出品,监控 Kubernetes 自己集群这个层面的指标。

这是最精简的组合了,如果 Kubernetes 的 Master 将数据存储在了 Etcd 集群的换还需要 Etcd Exporter 。如果 Kubernetes 启用了 ingress 等网络代理也需要进行监控。如果 Kubernetes 挂载了存储集群来提供存储空间,存储集群也需要监控。

所以我们来看看 kube-state-metrics 怎么使用。话说 Kubernetes 本身其实是提供了Prometheus 数据采集接口的,但是配置起来太麻烦了。我觉得还是用 kube-state-metrics 简单一些。当然,具体生产过程中看需求。

当前 kube-state-metrics 版本是 v2.2.4 ,发布于 2021.11.11 ,在实际使用过程中 这个版本的选择很重要,因为它是和 Kubernetes 的版本有关联的,如果Kubernetes 版本太低的话,需要使用历史版本,并且 Kubernetes 升级的时候也要评估 kube-state-metrics 是否也要一起升级。

造成这个关联关系的原因是 kube-state-metrics 使用 client-go 与 Kubernetes 集群交互。受支持的 Kubernetes 集群版本由 client-go 决定。client-go 和 Kubernetes 集群的兼容性矩阵如下:

下面是 kube-state-metrics 最新 5 个版本和 Kubernetes 最新 5 个版本的兼容情况。

kube-state-metrics Kubernetes 1.18 Kubernetes 1.19 Kubernetes 1.20 Kubernetes 1.21 Kubernetes 1.22
v1.9.8 - - - - -
v2.0.0 -/✓ -/✓ -/✓
v2.1.1 -/✓ -/✓
v2.2.4 -/✓
master -/✓
  • ✓ 表示完全支持这个版本区间内的功能
    • 表示 Kubernetes 集群有一些 client-go 库无法使用的特性(比如额外的API对象、弃用的API等)。

当前的 kube-state-metrics v2.0.0+ 版本在 Kubernetes v1.17 和 v1.18 上工作,不包括 Ingress 或 CertificateSigningRequest 资源指标。如果在较旧的 Kubernetes 版本上需要这些度量,请使用 kube-state-metrics v1.9.8 版本。

Kubernetes 在同一个版本的从 alpha 到 beta 到 最后 GA,其中的一些插件的版本可能会有变化,kube-state-metrics 可以在该版本的里最老的 API 版本使用。

举例:版本是随便写的,比如在 Kubernetes 1.20.0 的 alph 、Beta、GA 版本中,某个接口从 1.0 变化到了 1.5 ,那么,kube-state-metrics 是支持该接口的 1.0 版本的。就是这个意思。

指标

kube-state-metrics 因为导出了 Kubernetes 集群里集群级别的所有指标,所以指标数量巨多,详细的指标可以参考这个文档 https://github.com/kubernetes/kube-state-metrics/tree/master/docs ,划分的话有以下类型的指标可以

CertificateSigningRequest Metrics
ConfigMap Metrics
CronJob Metrics
DaemonSet Metrics
Deployment Metrics
Endpoint Metrics
Horizontal Pod Autoscaler Metrics
Ingress Metrics
Job Metrics
Lease Metrics
LimitRange Metrics
MutatingWebhookConfiguration Metrics
Namespace Metrics
NetworkPolicy Metrics
Node Metrics
PersistentVolume Metrics
PersistentVolumeClaim Metrics
Pod Disruption Budget Metrics
Pod Metrics
ReplicaSet Metrics
ReplicationController Metrics
ResourceQuota Metrics
Secret Metrics
Service Metrics
StatefulSet Metrics
StorageClass Metrics
ValidatingWebhookConfiguration Metrics
VerticalPodAutoscaler Metrics
VolumeAttachment Metrics

这些指标的阶段分成 3 类,分别是 EXPERIMENTAL 、STABLE 、DEPRECATED 三个阶段。

  • EXPERIMENTAL 是一些处于实验性质的指标,在后边的版本中有可能还有,有可能就没有了。
  • STABLE 是稳定的指标,在每个主板的更新中都有。
  • DEPRECATED 是到了既定的时间会废弃的指标。

当需要一个额外的,默认没有提供的标签时,可以使用 Prometheus 匹配操作符来扩展单个度量输出。

下边这个例子将 label_release 添加到 kube_pod_status_ready 指标的默认标签集合,并允许您通过 Helm 发布 label 或分组指标:

kube_pod_status_ready * on (namespace, pod) group_left(label_release) kube_pod_labels

另一个有用的例子是按阶段查询 pod 的内存使用情况,例如 Running :

sum(kube_pod_container_resource_requests{resource="memory"}) by (namespace, pod, node)
  * on (namespace, pod) group_left() (sum(kube_pod_status_phase{phase="Running"}) by (pod, namespace) == 1)

启动参数

kube-state-metrics 启动的时候有一些功能可以通过参数去控制,这些参数可以在本地运行时的启动过程中传递:

kube-state-metrics --telemetry-port=8081 --kubeconfig=<KUBE-CONFIG> --apiserver=<APISERVER> 

除了基本的指定端口和配置文件,还有其他很多参数可以使用,具体如下,我们根据实际情况来进行选择。

$ kube-state-metrics -h
Usage of ./kube-state-metrics:
      --add_dir_header                        If true, adds the file directory to the header of the log messages
      --alsologtostderr                       log to standard error as well as files
      --apiserver string                      The URL of the apiserver to use as a master
      --enable-gzip-encoding                  Gzip responses when requested by clients via 'Accept-Encoding: gzip' header.
  -h, --help                                  Print Help text
      --host string                           Host to expose metrics on. (default "::")
      --kubeconfig string                     Absolute path to the kubeconfig file
      --log_backtrace_at traceLocation        when logging hits line file:N, emit a stack trace (default :0)
      --log_dir string                        If non-empty, write log files in this directory
      --log_file string                       If non-empty, use this log file
      --log_file_max_size uint                Defines the maximum size a log file can grow to. Unit is megabytes. If the value is 0, the maximum file size is unlimited. (default 1800)
      --logtostderr                           log to standard error instead of files (default true)
      --metric-allowlist string               Comma-separated list of metrics to be exposed. This list comprises of exact metric names and/or regex patterns. The allowlist and denylist are mutually exclusive.
      --metric-annotations-allowlist string   Comma-separated list of Kubernetes annotations keys that will be used in the resource' labels metric. By default the metric contains only name and namespace labels. To include additional annotations provide a list of resource names in their plural form and Kubernetes annotation keys you would like to allow for them (Example: '=namespaces=[kubernetes.io/team,...],pods=[kubernetes.io/team],...)'. A single '*' can be provided per resource instead to allow any annotations, but that has severe performance implications (Example: '=pods=[*]').
      --metric-denylist string                Comma-separated list of metrics not to be enabled. This list comprises of exact metric names and/or regex patterns. The allowlist and denylist are mutually exclusive.
      --metric-labels-allowlist string        Comma-separated list of additional Kubernetes label keys that will be used in the resource' labels metric. By default the metric contains only name and namespace labels. To include additional labels provide a list of resource names in their plural form and Kubernetes label keys you would like to allow for them (Example: '=namespaces=[k8s-label-1,k8s-label-n,...],pods=[app],...)'. A single '*' can be provided per resource instead to allow any labels, but that has severe performance implications (Example: '=pods=[*]').
      --namespaces string                     Comma-separated list of namespaces to be enabled. Defaults to ""
      --namespaces-denylist string            Comma-separated list of namespaces not to be enabled. If namespaces and namespaces-denylist are both set, only namespaces that are excluded in namespaces-denylist will be used.
      --one_output                            If true, only write logs to their native severity level (vs also writing to each lower severity level)
      --pod string                            Name of the pod that contains the kube-state-metrics container. When set, it is expected that --pod and --pod-namespace are both set. Most likely this should be passed via the downward API. This is used for auto-detecting sharding. If set, this has preference over statically configured sharding. This is experimental, it may be removed without notice.
      --pod-namespace string                  Name of the namespace of the pod specified by --pod. When set, it is expected that --pod and --pod-namespace are both set. Most likely this should be passed via the downward API. This is used for auto-detecting sharding. If set, this has preference over statically configured sharding. This is experimental, it may be removed without notice.
      --port int                              Port to expose metrics on. (default 8080)
      --resources string                      Comma-separated list of Resources to be enabled. Defaults to "certificatesigningrequests,configmaps,cronjobs,daemonsets,deployments,endpoints,horizontalpodautoscalers,ingresses,jobs,leases,limitranges,mutatingwebhookconfigurations,namespaces,networkpolicies,nodes,persistentvolumeclaims,persistentvolumes,poddisruptionbudgets,pods,replicasets,replicationcontrollers,resourcequotas,secrets,services,statefulsets,storageclasses,validatingwebhookconfigurations,volumeattachments"
      --shard int32                           The instances shard nominal (zero indexed) within the total number of shards. (default 0)
      --skip_headers                          If true, avoid header prefixes in the log messages
      --skip_log_headers                      If true, avoid headers when opening log files
      --stderrthreshold severity              logs at or above this threshold go to stderr (default 2)
      --telemetry-host string                 Host to expose kube-state-metrics self metrics on. (default "::")
      --telemetry-port int                    Port to expose kube-state-metrics self metrics on. (default 8081)
      --tls-config string                     Path to the TLS configuration file
      --total-shards int                      The total number of shards. Sharding is disabled when total shards is set to 1. (default 1)
      --use-apiserver-cache                   Sets resourceVersion=0 for ListWatch requests, using cached resources from the apiserver instead of an etcd quorum read.
  -v, --v Level                               number for the log level verbosity
      --version                               kube-state-metrics build version information
      --vmodule moduleSpec                    comma-separated list of pattern=N settings for file-filtered logging

自身监控

基于云原生和 Prometheus 的监控设计思想,一个组件是要能提供自己的运行状态。Kube-state-metrics 也是能停自己的运行情况的,它在 -—telemetry-host-—telemetry-port(默认8081)下公开自己的通用进程指标。

Kube-state-metrics 会公开查看成功和错误指标的列表,这些可以用来计算监视资源的错误率。如果在 Metric 中遇到这些错误,很可能是配置或权限问题,接下来要查看的是 kube-state-metrics 的日志来进行定位问题原因。

采集指标的例子如下:

kube_state_metrics_list_total{resource="*v1.Node",result="success"} 1
kube_state_metrics_list_total{resource="*v1.Node",result="error"} 52
kube_state_metrics_watch_total{resource="*v1beta1.Ingress",result="success"} 1

资源建议

Kubernetes 集群中 Pods/Nodes/Deployments/Secrets 等等的数量决定了 Kubernetes 集群的规模。在某种程度上,集群中的 Kubernetes 规模与集群的节点数量成正比。

一般来说 kube-state-metrics 应该最少分配 256 MiB 的内存和 0.1 Core 的 CPU 。这个配置一般来说在 Kubernetes 集群 work 节点小于 100 的时候没有什么问题,大于 100 小于 1000 的时候请适量放开这个限制,当大于 1000 节点时,请先进行压测。

注意,如果CPU限制设置得太低,kube-state-metrics的内部队列将无法足够快地完成工作,从而导致随着队列长度的增长而增加内存消耗。如果遇到由高内存分配或CPU节流导致的问题,请尝试提高CPU限制。

kube-state-metrics 官方进行了延迟的测试,在 100 个节点的 Kubernetes 集群中测试结果如下:

"Perc50": 259615384 ns,
"Perc90": 475000000 ns,
"Perc99": 906666666 ns.

小结

先就这些吧,和 Kubernetes 一样,里边的指标选取,还有监控画图都是大头,有时间了再聊。