Kubernetes 监控
Jun 20, 2021 15:30 · 2509 words · 6 minute read
监控任何应用程序,都要能回答上两个问题:正在发生什么?为什么会发生这个?从应用程序中获取数据来定位这些问题,可以确保迅速发现问题并采取应对措施。这些数据以两种形式呈现:计量指标和日志。
时间序列的计量指标告诉我们正在发生什么,比如当前系统的负载或资源消耗。就像飞机上的各种仪表,为我们提供对系统当前状态数据化的展示,有时也是问题发生的警告信号。
日志告诉我们状况发生的原因,提供了应用程序中事件发生的记录。它们可以是信息性的,提供了应用程序作业的上下文;也可以是错误性的,表明为什么出问题。日志就像机械师插入诊断工具后的结果,确定为什么检查引擎的灯亮了。
监控的类型
-
资源监控
CPU、内存、网络等资源类的指标
-
性能监控
应用的内部监控,通常是通过 Hook 的机制在虚拟机层、字节码执行层隐式回调,或者在应用层显式注入,获取更深层的监控指标,常用来应用诊断与调优。
-
安全监控
针对安全进行的一系列监控策略,例如越权管理、安全漏洞扫码
-
事件监控
Kubernetes 中一种另类的监控方式,紧密贴合 Kubernetes 的设计理念,补充常规监控方案的缺欠与弊端。
通用计量指标
Kubernetes 是用 Golang 写的,有一些关于 Go 运行时的基本指标,它们对于关注 Go 程序中正在发生的事情是必要的;还有 etcd 方面的关键指标,多个组件与 etcd 交互,关注这些交互可以了解到 etcd 潜在的问题。下面是大多数 Kubernetes 组件暴露出来的一些顶级 Golang 数据和常见的 etcd 指标:
计量指标 | 组件 | 描述 |
---|---|---|
go_gc_duration_seconds | 所有 | GC 持续时间摘要 |
go_threads | 所有 | 创建的 OS 线程数量 |
go_goroutines | 所有 | 当前存在的 goroutine 数量 |
etcd_helper_cache_hit_count | API Server Controller Manager |
etcd 缓存命中计数 |
etcd_helper_cache_miss_count | API Server Controller Manager |
etcd 缓存未命中计数 |
etcd_request_cache_add_latencies_summary | API Server Controller Manager |
向 etcd 缓存添加对象的延迟 |
etcd_request_cache_get_latencies_summary | API Server Controller Manager |
从 etcd 缓存获取对象的延迟 |
etcd_request_latencies_summary | API Server Controller Manager |
etcd 每次操作的请求延迟 |
Kubernetes 控制面
控制面是驱动 Kubernetes 的引擎,由多个组件构成。每个组件都有特定的功能并暴露出自己的计量指标,以监测它的健康状况。
API Server
API Server 为 Kubernetes 集群提供前端,是所有组件交互的中心点。
计量指标 | 描述 |
---|---|
apiserver_request_count | API Server 请求计数 |
apiserver_request_latencies | 响应延迟(微秒级) |
etcd
etcd 是 Kubernetes 的数据后端,是一个强一致性且高可用的键值存储,容纳 Kubernetes 集群所有数据。
计量指标 | 描述 |
---|---|
etcd_server_has_leader | 1 表示存在领袖,反之则是 0 |
etcd_server_leader_changes_seen_total | 领袖变更次数量 |
etcd_server_proposals_applied_total | 已落实的提议数量 |
etcd_server_proposals_committed_total | 已提交的提议数量 |
etcd_server_proposals_pending | 待决的提议数量 |
etcd_server_proposals_failed_total | 失败的提议数量 |
etcd_debugging_mvcc_db_total_size_in_bytes | 压缩后的数据库真实大小 |
etcd_disk_backend_commit_duration_seconds | 后端提交的延迟 |
etcd_disk_wal_fsync_duration_seconds | WAL 落盘的延迟 |
etcd_network_client_grpc_received_bytes_total | gRPC 客户端接收的字节总数 |
etcd_network_client_grpc_sent_bytes_total | gRPC 客户端发送的字节总数 |
grpc_server_started_total | 服务器发起的 gRPC 总数 |
grpc_server_handled_total | 服务器处理的 gRPC 总数 |
Scheduler(调度器)
调度器观察 Kubernetes 中新创建的 Pod,并决定这些 Pod 在哪个节点上运行。它根据现有的数据来决策,包括集群资源的可用性和 Pod 本身的资源需求。
计量指标 | 描述 |
---|---|
scheduler_e2e_scheduling_latency_microseconds | 端到端调度延迟,是调度 & 绑定的延迟之和 |
Controller Manager
Controller Manager 是通过控制循环将集群调谐至理想状态的守护进程。它会监视 API Server 并根据当前状态与理想状态的差距采取措施。下面这些计量指标仅对 AWS、GCE 和 OpenStack 这些云商可用。
计量指标 | 描述 |
---|---|
cloudprovider_*_api_request_duration_seconds | 云商的 API 调用延迟 |
cloudprovider_*_api_request_errors | 云商 API 请求错误 |
Kube State Metrics
Kube State Metrics 是一个提供 Kubernetes 状态的插件。它会监视 Kubernetes API 并生成各种计量指标,我们就能知道当前正在跑什么。几乎所有的 Kubernetes 资源都会产生计量数据(Pod、Deployment、DaemonSet 和 Node)。
计量指标 | 描述 |
---|---|
kube_pod_status_phase | Pod 当前所处的阶段 |
kube_pod_container_resource_limits_cpu_cores | 容器可使用的 CPU 核心数量限制 |
kube_pod_container_resource_limits_memory_bytes | 容器可使用的内存大小限制 |
kube_pod_container_resource_requests_cpu_cores | 容器所要求的 CPU 核心数量 |
kube_pod_container_resource_requests_memory_bytes | 容器所要求的内存大小 |
kube_pod_container_status_ready | 1 表示容器已就绪,反之不然 |
kube_pod_container_status_restarts_total | 容器重启总次数 |
kube_pod_container_status_terminated_reason | 容器处于终止状态的原因 |
kube_daemonset_status_desired_number_scheduled | 应当运行 Pod 的节点数量 |
kube_daemonset_status_number_unavailable | 应当但并没有运行 Pod 的节点数量 |
kube_deployment_spec_replicas | Deployment 期望的 Pod 副本数量 |
kube_deployment_status_replicas_unavailable | Deployment 不可用的 Pod 副本数量 |
kube_node_spec_unschedulable | 某个节点是否可以调度新的 Pod |
kube_node_status_capacity_cpu_cores | 节点上可用的 CPU 核心数 |
kube_node_status_capacity_memory_bytes | 节点上可用的内存大小 |
kube_node_status_capacity_pods | 节点可调度的 Pod 数量 |
kube_node_status_condition | 节点当前状态 |
节点组件
Kubelet
我们还要密切关注 Kubelet,确保控制面始终能够与运行 Kubelet 的节点进行通讯。除了通用的 Go 运行时计量指标,Kubelet 还暴露了一些内部的行为,很适合追踪。
计量指标 | 描述 |
---|---|
kubelet_running_container_count | 当前运行的容器数量 |
kubelet_runtime_operations | 不同操作类型提供的运行时操作累计数量 |
kubelet_runtime_operations_latency_microseconds | 按类型划分的每个操作的延迟(毫秒级) |
节点资源计量指标
检测集群中每个节点的健康状况,避免因节点问题导致的宕机,我们需要看到节点的方方面面,包括 CPU 和内存消耗、系统负载、文件系统和网络活动。
容器资源计量指标
对所有 Kubernetes 计量指标的监控只是拼图的一部分,我们还要保持对 Kubernetes 正在编排的容器化应用程序的可见性。最起码也要知道这些容器的资源消耗。Kubelet 从 cAdvisor 访问容器计量数据,这是一个可以分析容器的资源使用情况的工具,和节点资源计量指标差不多:CPU、内存、文件系统和网络。
Kubernetes 的监控接口标准
通过 API Server Aggregated API 注册了三种不同的 metrics 接口,将监控的消费能力进行标准化和解耦。
API | 注释 | |
---|---|---|
Resource Metrics | metrics.k8s.io | 主要的实现为 Metrics-Server 提供资源监控 |
Custom Metrics | custom.metrics.k8s.io | 主要的实现为 Prometheus 提供资源监控和自定义监控 |
External Metrics | external.metrics.k8s.io | 主要的实现为云商的 Provider 提供云资源的监控指标 |
计量指标采集方案
Kubernetes 各组件都以 Prometheus 数据格式暴露计量指标,通过 HTTP 服务将计量指标以 URL 给出。标准规定服务以 /metrics 路径来访问。只需要抓取不同服务的相同路径即可获取这些指标。
日志
Kubernetes 为其每个组件提供了大量日志,使得我们能够深入了解对应组件正在进行的决策。我们的容器化应用程序也在生成日志,提供详细的信息。对这些日志的访问确保我们可以监控和排除应用程序故障。
-
主机内核的日志
- 可以协助开发者诊断例如
- 网络栈异常
- 驱动异常
- 文件系统异常
- 影响节点稳定的异常
-
Runtime 的日志
最常见的运行时是 Docker,通过 Docker 的日志排查例如删除 Pod Hang 等问题
-
核心组件的日志
- APIServer 日志可以用来审计
- Scheduler 日志可以诊断调度
- etcd 日志可以查看存储状态
- Ingress 日志可以分析接入层流量
-
部署应用的日志
通过应用日志分析业务层的状态,诊断异常(500请求)
日志的采集
当容器在 Kubernetes 集群中运行,其产生的日志文件将被写入容器所在节点的磁盘,所以每个节点上都有在本节点上运行的所有容器的日志。
-
宿主机文件
容器内通过挂载卷将日志写在宿主机中,通过宿主机日志轮转的策略进行日志的轮转,再通过宿主机上的代理进行采集
-
容器内文件
通过 SideCar Streaming 容器转写到 stdout,再写到相应的日志文件,通过本地的轮转和外部的代理进行采集
-
容器标准/错误输出
直接写到 stdout
日志采集方案
在每个节点以 DaemonSet 上起一个 fluentd 进程,将数据汇集到 Fluentd Server,再将数据离线到相应的例如 ElasticSearch(Kibana 作为展现)或 influxdb(grafana 作为展现)数据库中。