news 2026/9/24 19:48:54

Kubernetes 集群与应用监控实战:从 Heapster 到 Prometheus 的云原生可观测体系

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Kubernetes 集群与应用监控实战:从 Heapster 到 Prometheus 的云原生可观测体系

Kubernetes 集群与应用监控实战:从 Heapster 到 Prometheus 的云原生可观测体系

【免费下载链接】kubernetes-handbookKubernetes 架构与生态:从云原生到 AI 原生基础设施的构建指南项目地址: https://gitcode.com/gh_mirrors/ku/kubernetes-handbook

Kubernetes 将复杂的应用环境管理变得简单,但要对集群自身的各组件以及运行在其上的应用做到良好"洞察"却并不容易。本文以 Kubernetes Handbook 的监控实践为主线,完整讲解 Kubernetes 监控的三大层次(集群组件、Pod、应用)、cAdvisor 数据模型与容器命名规则、Heapster/InfluxDB/Grafana 的部署与 API 使用、应用级监控架构以及基于 Weave Scope 的应用拓扑可视化,并梳理 Prometheus 作为新一代云原生监控方案的核心组件与适用边界。读完本文,你将掌握一套可落地的 Kubernetes 监控体系搭建与数据获取方法。

Kubernetes 监控为什么比传统监控更难

Kubernetes 对应用做了大量抽象(Deployment、Service、Pod 等),在生产环境下,这些不同抽象组件的健康状态监控是迫在眉睫的事。与物理机和虚拟机的监控不同,Kubernetes 集群的监控多了一层虚拟化抽象:在 docker 容器之上,Kubernetes 又抽象出 Pod 和 Service 的概念,监控复杂度显著提升。

实践中需要关注三个方面:

  • Kubernetes 集群本身的监控:主要是 apiserver、kubelet、controller-manager、scheduler 等集群组件的健康与性能;
  • 集群中 Pod 的监控:Pod 的 CPU、内存、网络、磁盘等资源指标;
  • 集群内部应用的监控:针对应用本身的运行状态、业务指标进行监控。

在设计 Kubernetes 监控方案时,还应重点思考以下问题:

  • 应该给 Pod 打上哪些 label?这些 label 将直接成为监控的 metric 标签;
  • 应用的 Pod 漂移(重建、调度到其他节点)之后怎么办?Pod 的生命周期远比虚拟机、物理机短,如何持续追踪应用状态;
  • 监控项如何覆盖更多层次:Kubernetes 本身、容器、应用;
  • 监控指标从哪里取:是通过 Heapster 收集汇聚,还是直接从每台主机的 docker 上取原始数据。

理解数据源头:cAdvisor 与容器命名规则

要设计好监控方案,首先需要弄清楚 cAdvisor 收集的数据格式与字段含义。通过访问${NODE_IP}:4194/api/v1.3/docker获取的 JSON 结果中,某个容器包含如下字段:

"labels": { "annotation.io.kubernetes.container.hash": "f47f0602", "annotation.io.kubernetes.container.ports": "[{\"containerPort\":80,\"protocol\":\"TCP\"}]", "annotation.io.kubernetes.container.restartCount": "0", "annotation.io.kubernetes.container.terminationMessagePath": "/dev/termination-log", "annotation.io.kubernetes.container.terminationMessagePolicy": "File", "annotation.io.kubernetes.pod.terminationGracePeriod": "30", "io.kubernetes.container.logpath": "/var/log/pods/d8a2e995-3617-11e7-a4b0-ecf4bbe5d414/php-redis_0.log", "io.kubernetes.container.name": "php-redis", "io.kubernetes.docker.type": "container", "io.kubernetes.pod.name": "frontend-2337258262-771lz", "io.kubernetes.pod.namespace": "default", "io.kubernetes.pod.uid": "d8a2e995-3617-11e7-a4b0-ecf4bbe5d414", "io.kubernetes.sandbox.id": "843a0f018c0cef2a5451434713ea3f409f0debc2101d2264227e814ca0745677" }

这些信息是 Kubernetes 创建容器时给 docker container 打的Labels,使用docker inspect $container_name命令同样可以看到。问题在于:这些 label 与容器名字有什么关系?在 node 节点上执行docker ps看到的容器名,又对应哪个应用的 Pod?

在 Kubernetes 的 kubelet 代码pkg/kubelet/dockertools/docker.go中,BuildDockerName方法定义了容器的名称规范,核心代码如下:

// Creates a name which can be reversed to identify both full pod name and container name. // This function returns stable name, unique name and a unique id. // Although rand.Uint32() is not really unique, but it's enough for us because error will // only occur when instances of the same container in the same pod have the same UID. The // chance is really slim. func BuildDockerName(dockerName KubeletContainerName, container *v1.Container) (string, string, string) { containerName := dockerName.ContainerName + "." + strconv.FormatUint(kubecontainer.HashContainerLegacy(container), 16) stableName := fmt.Sprintf("%s_%s_%s_%s", containerNamePrefix, containerName, dockerName.PodFullName, dockerName.PodUID) UID := fmt.Sprintf("%08x", rand.Uint32()) return stableName, fmt.Sprintf("%s_%s", stableName, UID), UID } // Unpacks a container name, returning the pod full name and container name we would have used to // construct the docker name. If we are unable to parse the name, an error is returned. func ParseDockerName(name string) (dockerName *KubeletContainerName, hash uint64, err error) { // For some reason docker appears to be appending '/' to names. // If it's there, strip it. name = strings.TrimPrefix(name, "/") parts := strings.Split(name, "_") if len(parts) == 0 || parts[0] != containerNamePrefix { err = fmt.Errorf("failed to parse Docker container name %q into parts", name) return nil, 0, err } if len(parts) < 6 { // We have at least 5 fields. We may have more in the future. glog.Warningf("found a container with the %q prefix, but too few fields (%d): %q", containerNamePrefix, len(parts), name) err = fmt.Errorf("Docker container name %q has less parts than expected %v", name, parts) return nil, 0, err } nameParts := strings.Split(parts[1], ".") containerName := nameParts[0] if len(nameParts) > 1 { hash, err = strconv.ParseUint(nameParts[1], 16, 32) if err != nil { glog.Warningf("invalid container hash %q in container %q", nameParts[1], name) } } podFullName := parts[2] + "_" + parts[3] podUID := types.UID(parts[4]) return &KubeletContainerName{podFullName, podUID, containerName}, hash, nil }

从中可以看出容器名称的组成:字段之间用下划线隔开,至少包含 6 个字段(未来可能更多),其中四个基本字段为:

containerNamePrefix_containerName_PodFullName_PodUID

所有由 Kubernetes 启动的容器的containerNamePrefix都是k8scontainerName字段由"容器名 + 容器配置 hash"构成(如php-redis.f47f0602),PodFullName则由 Deployment/ReplicaSet 生成的 pod 名与命名空间拼合而成。

下面以官方示例 guestbook 为例。Deployment 名为frontend,其中启动了名为php-redis的容器,副本数为 3,其配置如下:

apiVersion: extensions/v1beta1 kind: Deployment metadata: name: frontend spec: template: metadata: labels: app: guestbook tier: frontend spec: containers: - name: php-redis image: harbor-001.jimmysong.io/library/gb-frontend:v4 resources: requests: cpu: 100m memory: 100Mi env: - name: GET_HOSTS_FROM value: dns ports: - containerPort: 80

选取三个实例中的一个运行 php-redis 的 docker 容器,在节点上docker ps会看到类似:

k8s_php-redis_frontend-2337258262-154p7_default_d8a2e2dd-3617-11e7-a4b0-ecf4bbe5d414_0

逐字段解析:

  • containerNamePrefix:k8s
  • containerName:php-redis
  • podFullName:frontend-2337258262-154p7
  • computeHash:154p7
  • deploymentName:frontend
  • replicaSetName:frontend-2337258262
  • namespace:default
  • podUID:d8a2e2dd-3617-11e7-a4b0-ecf4bbe5d414

理解了命名规则,就可以在监控采集时把 node 上的 docker 容器准确反查到其所属的 Pod、ReplicaSet、Deployment 与 namespace,从而把容器级原始指标与业务应用对应起来。

使用 Heapster 进行集群监控

Heapster 是 Kubernetes 官方提供的监控方案(仓库中的安装说明见 heapster 插件安装)。安装 Kubernetes 集群时默认会安装该插件,可对集群上的应用做基础监控:获取Pod 级别内存CPU网络监控信息,同时通过 API 暴露 Kubernetes 中的基本资源监控指标。完整部署清单位于仓库的 manifests/heapster 目录,包括以下文件:

  • heapster-deployment.yamlheapster-service.yaml:Heapster 主进程及其 Service;
  • influxdb-deployment.yamlinfluxdb-service.yamlinfluxdb-cm.yaml:时序数据库 InfluxDB 及配置;
  • grafana-deployment.yamlgrafana-service.yaml:可视化面板 Grafana;
  • heapster-rbac.yaml:Heapster 所需的 RBAC 权限。

从 heapster-deployment.yaml 可以看出 Heapster 的启动方式与数据链路:

apiVersion: extensions/v1beta1 kind: Deployment metadata: name: heapster namespace: kube-system spec: replicas: 1 template: metadata: labels: task: monitoring k8s-app: heapster spec: serviceAccountName: heapster containers: - name: heapster image: harbor-001.jimmysong.io/library/heapster-amd64:v1.4.3 imagePullPolicy: IfNotPresent command: - /heapster - --source=kubernetes:https://kubernetes.default - --sink=influxdb:http://monitoring-influxdb:8086

关键参数只有两个:--source指定数据源(通过 kubelet 的 cAdvisor 采集节点与容器指标),--sink指定数据输出端(本例为 InfluxDB)。Heapster 收集 Node 节点上的 cAdvisor 数据,并可按照 Kubernetes 的资源类型聚合资源,例如 Pod、Namespace 域,分别获取其 CPU、内存、网络和磁盘的 metric,默认的 metric 数据聚合时间间隔是 1 分钟。

在 Grafana 中按 label 增加 service 层分类

默认安装的 Grafana 面板只根据 Namespace 和 Pod 两层来分类展示指标,实在有些单薄。可以在不改变原有架构的基础上,通过应用的自定义 label 来区分不同应用的 Pod,从而在监控面板中增加 service 这一层分类维度。

Heapster 的部署细节:镜像替换与 InfluxDB 配置

官方镜像保存在 gcr.io 中,需要提前拷贝到私有仓库。部署时主要修改点包括:

  • grafana-deployment:将镜像替换为私有仓库地址,并把GF_SERVER_ROOT_URL设置为/api/v1/proxy/namespaces/kube-system/services/monitoring-grafana/。如果后续使用 kube-apiserver 或kubectl proxy访问 Grafana dashboard,则必须这样设置,否则访问 Grafana 时提示找不到.../api/dashboards/home页面;
  • influxdb-deployment:InfluxDB 从 v1.1.0 开始默认关闭 admin UI。开启办法是:先导出镜像内的 influxdb 配置文件,将[admin]段的enabled = false改为true,然后通过kubectl create configmap influxdb-config --from-file=config.toml -n kube-system创建 ConfigMap,最后在 Deployment 中挂载到/etc/覆盖原始配置(仓库中的 influxdb-cm.yaml 即为修改后的完整配置);
  • influxdb-service:将 Service 类型改为NodePort,并额外增加 8083(admin)端口映射,便于后续浏览器访问 admin UI。

部署时执行kubectl create -f .(或对每个文件kubectl apply)后,可通过如下命令检查结果:

$ kubectl get deployments -n kube-system | grep -E 'heapster|monitoring' heapster 1 1 1 1 2m monitoring-grafana 1 1 1 1 2m monitoring-influxdb 1 1 1 1 2m

访问 Grafana 有两种途径:通过kubectl cluster-info获取 monitoring-grafana 服务 URL 后经 kube-apiserver 代理访问(形如http://172.20.0.113:8080/api/v1/proxy/namespaces/kube-system/services/monitoring-grafana);或先运行kubectl proxy --address='172.20.0.113' --port=8086 --accept-hosts='^*$',再经代理端口访问。

注意:安装 Grafana 后默认模板中 namespace 选择里只有defaultkube-system,这并非其他 namespace 的指标没被监控,只是没有开启显示。将 Templating 中 namespace 的 Data source 设置为 influxdb-datasource、Refresh 设置为 on Dashboard Load 并保存,刷新浏览器即可看到其他 namespace 选项。

通过 Heapster API 获取集群对象的 metric

Heapster 提供 RESTful API,可用kubectl cluster-info获取其地址:

$ kubectl cluster-info Heapster is running at https://172.20.0.113:6443/api/v1/proxy/namespaces/kube-system/services/heapster ...

以获取spark-clusternamespace 的 memory usage 为例,构造完整 URL:

https://172.20.0.113:6443/api/v1/proxy/namespaces/kube-system/services/heapster/api/v1/model/namespaces/spark-cluster/metrics/memory/usage?start=2017-10-16T09:14:00Z&end=2017-10-16T09:16:00Z

URL 分为三部分:

  • API 地址https://172.20.0.113:6443/api/v1/proxy/namespaces/kube-system/services/heapster/
  • API 参数/api/v1/model/namespaces/spark-cluster/metrics/memory/usage,表示查询spark-clusternamespace 中的memory/usage指标;
  • 时间片?start=...&end=...,使用 RFC-3339 时间格式,Linux 下可用date --rfc-3339="seconds"生成,将空格替换为T、时区偏移替换为Z;也可以只指定 start,end 自动取当前时间。

返回结果示例:

{ "metrics": [ { "timestamp": "2017-10-16T09:14:00Z", "value": 322592768 }, { "timestamp": "2017-10-16T09:15:00Z", "value": 322592768 }, { "timestamp": "2017-10-16T09:16:00Z", "value": 322592768 } ], "latestTimestamp": "2017-10-16T09:16:00Z" }

注意:Heapster 中查询的所有值都以最小单位表示,例如 CPU 为 1 milicore,内存为 B(字节)。Heapster 同时被 Horizontal Pod Autoscaling 用作Resource Metrics API,在kube-controller-manager中配置指向 kube-aggregator 的--api-server,或在启动 heapster 时指定--api-server=true

版本提示:Kubernetes 1.11 起不建议使用 Heapster。SIG Instrumentation 正持续转向新的 Kubernetes 监控模型,仍使用 Heapster 做自动扩展的集群应迁移到 metrics-server 与自定义指标 API。

Prometheus:面向云原生的新一代监控方案

Heapster 解决了"能监控"的问题,但 Prometheus 的出现提供了更强大的指标模型与查询能力。Prometheus 由 SoundCloud 开源,2012 年开始编写代码,2015 年在 GitHub 上开源,2016 年成为继 Kubernetes 之后第二个加入 CNCF 的项目成员,也是第二个正式毕业的项目。作为新一代开源解决方案,其很多设计理念与 Google SRE 运维之道不谋而合。

云原生时代,监控对象随微服务和容器化呈指数级增加,监控对象的生命周期也更短暂,因此需要一款统一监控指标与数据查询语言的工具。Prometheus 主要功能包括:

  • 多维数据模型:时序由 metric 名字和 k/v 的 labels 构成;
  • 灵活的查询语句 PromQL;
  • 无依赖存储,支持 local 和 remote 不同模型;
  • 采用 http 协议、pull 模式拉取数据,简单易懂;
  • 监控目标支持服务发现或静态配置;
  • 支持多种统计数据模型,图形化友好。

其核心组件包括:

  • Prometheus Server:抓取数据、存储时序数据,并提供查询和 Alert Rule 配置管理;
  • client libraries:用于对接 Prometheus Server,查询和上报数据;
  • push gateway:批量、短期监控数据的汇总节点,主要用于业务数据汇报;
  • exporters:各类指标导出器,如机器指标 node_exporter、MongoDB exporter 等;
  • alertmanager:告警通知管理,负责聚合、去重、降噪后发送告警。

其工作逻辑是:Prometheus server 定期从静态配置或服务发现的目标拉取数据;当新拉取数据大于配置内存缓存区时将数据持久化到磁盘(remote storage 则持久化到云端);配置 rule 后定时查询数据,条件触发时将 alert 推送到 Alertmanager;最终可通过 API、Prometheus Console 或 Grafana 查询和聚合数据。

适用边界:Prometheus 的数据是基于时序的 float64 值,若你的数据还有其他类型则无法满足;它也不适合做审计计费——审计计费需要记录每个请求并长期存储数据,而 Prometheus 关注的是系统运行瞬时状态与趋势,能容忍少量数据丢失。这类场景需要专门的审计系统。

应用监控:基于 Kubernetes API 的指标采集架构

对于集群内应用的监控,可以采用如下架构:通过访问 Kubernetes API 获取应用 Pod 的 IP 和端口,将 Pod labels 作为监控 metric 的 tag,直接访问应用的 Pod IP 和端口获取应用监控数据,最后将 metrics 发送到存储与展示系统。这种方式有以下几个要点:

  • 访问 Kubernetes API 获取应用 Pod 的 IP 和端口;
  • Pod labels 作为监控 metric 的 tag;
  • 直接访问应用的 Pod 的 IP 和端口获取应用监控数据;
  • metrics 发送到存储与展示平台统一管理。

当应用 Pod 发生漂移时,由于始终通过 Kubernetes API 动态获取最新 Pod 地址,监控采集可跟随应用实例的生命周期持续工作,这正是容器化应用监控与传统监控的关键差异。

应用拓扑状态图:用 Weave Scope 一览集群全景

对于复杂的应用编排和依赖关系,我们希望能有清晰的图来一览应用状态和拓扑关系。可以使用 Weaveworks 开源的 scope。仓库提供了完整的部署清单 manifests/weave/scope.yaml,其中定义了:

  • weave-scope-app Deploymentweaveworks/scope:1.5.1--no-probe)与对应的 Service(端口 80 → 容器 4040);
  • weave-scope-agent DaemonSet:以hostNetwork: truehostPID: true方式在每个节点运行,挂载 docker socket(--probe.docker=true)并启用 Kubernetes 探针(--probe.kubernetes=true);
  • 配套的 ServiceAccount、ClusterRole 与 ClusterRoleBinding(RBAC,安装于kube-systemnamespace)。

安装方式为:

$ kubectl apply -f scope.yaml

由于服务安装在kube-systemnamespace 下,可创建一个新的 Ingress(如kube-system.yaml)暴露访问入口:

apiVersion: extensions/v1beta1 kind: Ingress metadata: name: traefik-ingress namespace: kube-system spec: rules: - host: scope.weave.io http: paths: - path: / backend: serviceName: weave-scope-app servicePort: 80

执行kubectl apply -f kube-system.yaml后,在主机/etc/hosts中添加一条记录:

172.20.0.119 scope.weave.io

浏览器访问scope.weave.io即可打开应用拓扑界面。

如上图所示,scope 可以监控 Kubernetes 集群中一系列资源的状态、资源使用情况、应用拓扑、扩缩容,还可以直接通过浏览器进入容器内部进行调试等。

小结

一套完整的 Kubernetes 监控体系通常由三层组成:集群组件监控(apiserver、kubelet 等)、Pod 资源监控(CPU、内存、网络、磁盘)和应用业务监控。数据层面需要理解 cAdvisor 的原始数据模型与容器命名规则,才能把容器指标准确反查到 Pod/Deployment 维度;采集与存储层面,Heapster + InfluxDB + Grafana 是入门最轻的官方组合,而 Prometheus 凭借多维数据模型、PromQL 与服务发现能力,成为云原生监控的主流选择;可视化和拓扑层面,Weave Scope 提供了直观的集群与依赖关系视图。

仓库中 practice/monitor.md、practice/monitoring.md、practice/using-heapster-to-get-object-metrics.md 与 manifests/heapster 目录提供了完整的部署清单与 API 使用细节,practice/prometheus.md 给出了 Prometheus 的组件与架构总览,可作为继续深入实践的入口。

【免费下载链接】kubernetes-handbookKubernetes 架构与生态:从云原生到 AI 原生基础设施的构建指南项目地址: https://gitcode.com/gh_mirrors/ku/kubernetes-handbook

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/24 19:48:49

FDF框架:数字孪生机器学习流水线的类型安全与函数复用实战

1. 项目概述与整体思路拆解先抛出一个我这两年一直在思考的问题&#xff1a;数字孪生项目里&#xff0c;机器学习流水线到底难在哪里&#xff1f;很多团队接到数字孪生项目&#xff0c;第一反应是炫酷的 3D 可视化大屏&#xff0c;Unity 场景里摆一台机器的模型&#xff0c;转起…

作者头像 李华
网站建设 2026/9/24 19:48:44

MySQL增删查改实战指南:从基础语法到索引性能优化

作为一个天天跟数据库打交道的人&#xff0c;我太清楚“增删查改”这四个字的分量了。很多人觉得MySQL的增删查改就是四条SQL语句&#xff0c;背下来就完事了。但真正上手做项目的时候才发现&#xff0c;同样的INSERT、SELECT、UPDATE、DELETE&#xff0c;有人写出来的语句稳如…

作者头像 李华
网站建设 2026/9/24 19:48:15

Oracle DBLink连接MySQL完整指南:DG4ODBC配置与踩坑总结

01. 先搞清楚一件事&#xff1a;Oracle的DBLink本身并连不上MySQL1.1 为什么默认情况下这条链路是断的很多第一次接触这个需求的同学会默认认为&#xff1a;DBLink嘛&#xff0c;连什么数据库都是DBLink&#xff0c;改了连接串不就行了。我最初也是这么想的&#xff0c;直到在L…

作者头像 李华
网站建设 2026/9/24 19:47:58

SQL Server .bak文件还原实战:从报错排查到完整恢复流程

上周同事丢过来一个OrderSystem_Full_20250314.bak&#xff0c;跟我说“帮忙看一眼这个库”。这类事情&#xff0c;干过几年数据库的人应该都懂&#xff1a;.bak这个后缀意味着它不是给你双击打开的&#xff0c;也不是导入 Excel 就能看的&#xff0c;你面对的是 SQL Server 的…

作者头像 李华
网站建设 2026/9/24 19:46:53

IDEA Debug高效调试技巧:从条件断点到远程调试实战

1. 调试的起点&#xff1a;先把Debug窗口用熟&#xff0c;再谈技巧做Java开发这么多年&#xff0c;我见过太多同事写代码时习惯用System.out.println去猜问题&#xff0c;稍微复杂一点的逻辑就来回打印日志、猜测状态、加打印再跑一遍&#xff0c;循环个五六次才找到问题点。而…

作者头像 李华
网站建设 2026/9/24 19:46:39

基于Python的爱奇艺影视数据可视化分析系统实战

1. 先搞清楚这系统到底能干什么&#xff1a;一条完整的数据流水线做这个"基于Python 爱奇艺影视数据可视化分析系统"之前&#xff0c;我建议你先别急着敲代码。很多人拿到这种项目第一反应是"我要写爬虫"&#xff0c;第二反应是"我要画图表"&…

作者头像 李华