ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

prometheus监控k8s的metric详解(第二版)第三章 kubernetes-apiservers(第三部分)request(上):用TaoToken统一Key打通apiserver请求指标

prometheus监控k8s的metric详解(第二版)第三章 kubernetes-apiservers(第三部分)request(上):用TaoToken统一Key打通apiserver请求指标 1. 为什么 apiserver 的 request 指标总在“看得见却读不懂”之间apiserver_request_total和apiserver_request_duration_seconds是 Prometheus 监控 Kubernetes 控制面时最先被采集、也最容易被忽略的一类指标。说它“看得见”是因为只要集群里跑着 kube-prometheus-stack 或者手写的 ServiceMonitorjobkubernetes-apiservers这条时间线几乎一定会出现说它“读不懂”是因为一旦展开标签你会看到group、resource、scope、subresource、verb、version六个维度同时出现组合出来的序列数量轻松上千直接看原始值根本不知道哪条该关注。这一篇聚焦 request 类指标也就是以apiserver_request_total旧版本里叫apiserver_request_count和apiserver_request_duration_seconds为核心的请求计数与耗时分布。它适合两类人一类是正在自建 Kubernetes 集群、准备把控制面可观测性补齐的运维另一类是已经采到了指标但面对verbWATCH和verbLIST的差异、scopecluster与scopenamespace的区分一头雾水的同学。读完你应该能独立完成三件事把 apiserver 的 request 指标稳定抓进 Prometheus、用 PromQL 把关键维度拆出来、以及通过一条统一的 API 通道去校验指标字段是否和集群真实状态对得上。我试过在几个不同规模的集群里对比request 指标最有价值的地方不是“总量”而是它把 Kubernetes 内部到底在做什么操作暴露了出来。比如leases资源的PUT次数高得离谱往往意味着某个组件的租约续期频率异常configmaps的WATCH数量巨大通常和大量控制器监听配置变更有关。这些结论单看 CPU、内存是得不出来的。在进入配置之前先把这一篇要用到的统一入口说清楚。后面演示指标拉取和字段校验时会通过 TaoToken 的 API 通道完成一次请求官网地址是 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content API 基址是 https://taotoken.net/api 。它的作用是让你不用在每台机器上分别维护多套 Key用一个统一 Key 就能把校验请求发出去省掉环境变量到处同步的麻烦。2. apiserver request 指标采集前置ServiceMonitor 与抓取配置怎么落地在动手写 YAML 之前先确认你的集群里 apiserver 的 metrics 端点是否可达。自建集群通常用 kubeadm 部署apiserver 监听在 6443/metrics路径默认开启但需要认证。kube-prometheus-stack 的做法是通过一个名为kubernetes-apiservers的 Endpoints 对象把 apiserver 的地址注册进去再用 ServiceMonitor 去抓。先看 Endpoints 和 Service 的定义这是整条链路的地基apiVersion: v1 kind: Service metadata: name: kubernetes-apiservers namespace: default labels: k8s-app: apiserver spec: clusterIP: None ports: - name: https-metrics port: 6443 protocol: TCP targetPort: 6443 --- apiVersion: v1 kind: Endpoints metadata: name: kubernetes-apiservers namespace: default labels: k8s-app: apiserver subsets: - addresses: - ip: 10.0.0.10 ports: - name: https-metrics port: 6443 protocol: TCP这里的10.0.0.10要换成你控制平面节点的真实 IP。如果你有三个 master就把三个 IP 都列进addresses。注意clusterIP: None表示这是一个无头 ServicePrometheus 通过 Endpoints 直接发现目标不经过 kube-proxy。接下来是 ServiceMonitor它告诉 Prometheus Operator 去抓这个 ServiceapiVersion: monitoring.coreos.com/v1 kind: ServiceMonitor metadata: name: kubernetes-apiservers namespace: monitoring labels: release: prometheus spec: namespaceSelector: matchNames: - default selector: matchLabels: k8s-app: apiserver endpoints: - port: https-metrics scheme: https path: /metrics interval: 30s scrapeTimeout: 10s bearerTokenFile: /var/run/secrets/kubernetes.io/serviceaccount/token tlsConfig: caFile: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt serverName: kubernetes insecureSkipVerify: false relabelings: - sourceLabels: [__meta_kubernetes_service_label_k8s_app] targetLabel: component replacement: apiserver - targetLabel: job replacement: kubernetes-apiservers几个关键点值得展开。bearerTokenFile指向的是 Prometheus Pod 里挂载的 ServiceAccount token这个 SA 需要有访问 apiserver/metrics的权限。默认情况下system:monitoring这个 ClusterRole 已经包含了/metrics的访问权但如果你用的是自定义 RBAC要确认绑定关系。tlsConfig里的serverName: kubernetes是为了让证书校验通过因为 apiserver 的证书 SAN 里通常包含kubernetes这个名称。relabelings里把job强制写成kubernetes-apiservers是为了和社区仪表盘里的查询保持一致避免后面改 PromQL 时到处替换。如果你没有用 Prometheus Operator而是手写prometheus.yml那对应的 scrape_config 是这样scrape_configs: - job_name: kubernetes-apiservers scheme: https kubernetes_sd_configs: - role: endpoints bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token tls_config: ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt server_name: kubernetes relabel_configs: - source_labels: - __meta_kubernetes_namespace - __meta_kubernetes_service_name action: keep regex: default;kubernetes-apiservers - target_label: job replacement: kubernetes-apiservers这段配置依赖role: endpoints的服务发现keep规则只保留 default 命名空间下名为kubernetes-apiservers的 Endpoints。抓取间隔建议 30s因为 apiserver 的指标基数大太频繁会加重控制面负担。配置应用之后去 Prometheus 的 Targets 页面确认kubernetes-apiservers这个 job 的状态是 UP。如果显示 DOWN先看错误信息是证书问题还是 401这两类在后面的排障章节会分别处理。3. 可复制的 request 指标查询与统一 Key 校验配置指标抓进来之后第一步是确认apiserver_request_total真的存在。在 Prometheus 查询框里输入count(apiserver_request_total)如果返回一个大于 0 的数字说明采集成功。接着看它有哪些标签count by (group, resource, verb, scope) (apiserver_request_total)这条查询会把所有维度组合列出来你会看到类似groupapps, resourcedeployments, verbWATCH, scopecluster这样的行。注意不同 Kubernetes 版本里指标名可能有差异1.20 之前叫apiserver_request_count之后统一成apiserver_request_total写告警规则时要按版本区分。要按资源类型看请求速率用 rate 包一层sum by (resource, verb) ( rate(apiserver_request_total{jobkubernetes-apiservers}[5m]) )这条查询能直接告诉你过去 5 分钟里哪种资源被哪种操作访问得最频繁。实测下来leases的PUT和configmaps的WATCH通常排在最前面前者是各组件续租后者是控制器监听配置。耗时分布用直方图指标apiserver_request_duration_seconds_bucket算 P99 延迟histogram_quantile(0.99, sum by (le, resource, verb) ( rate(apiserver_request_duration_seconds_bucket{jobkubernetes-apiservers}[5m]) ) )这里要特别注意verb的取值。WATCH是长连接它的 duration 会一直累加到连接断开所以 P99 看起来会非常大这是正常的不要拿它当慢请求告警。真正要盯的是LIST、GET、POST、PUT、PATCH、DELETE这几类短请求。现在到了统一 Key 校验的部分。为了确认 Prometheus 里查到的字段和集群真实状态一致可以通过 TaoToken 的 API 通道发一次请求把指标里的resource和group拿去和kubectl api-resources的输出对照。先准备一个配置文件把 Base URL、Key、Model ID 三件套写清楚{ base_url: https://taotoken.net/api, api_key: sk-你的统一Key, model_id: claude-sonnet-4-20250514, timeout: 30 }这个 JSON 可以放在~/.taotoken/config.json也可以直接作为环境变量注入。如果你用的是 Claude Code 这类工具对应的 settings 片段是{ env: { ANTHROPIC_BASE_URL: https://taotoken.net/api, ANTHROPIC_API_KEY: sk-你的统一Key, ANTHROPIC_MODEL: claude-sonnet-4-20250514 } }注意ANTHROPIC_BASE_URL后面不要带/v1SDK 会自己拼路径。Key 的获取入口在 https://taotoken.net/api-keys 登录后生成即可。Model ID 要和你实际使用的模型对齐写错了会返回 404。配置好之后用 curl 发一次校验请求把从 Prometheus 查到的resourceleases和groupcoordination.k8s.io作为问题内容curl -s https://taotoken.net/api/v1/messages \ -H x-api-key: sk-你的统一Key \ -H anthropic-version: 2023-06-01 \ -H content-type: application/json \ -d { model: claude-sonnet-4-20250514, max_tokens: 256, messages: [ {role: user, content: 在 Kubernetes 中groupcoordination.k8s.io 且 resourceleases 的对象它的 scope 是 cluster 还是 namespace} ] }返回的 JSON 里content[0].text就是答案。这一步的意义在于当你对某个group和resource的组合拿不准时可以用统一 Key 快速问一次而不用去翻 API 文档。整个链路只依赖一个 Key不用为不同工具分别申请。4. 验证请求与成功结果从指标到字段的完整闭环配置写完不算完要验证整条链路真的通了。验证分三层Prometheus 能查到数据、查询结果和集群状态一致、统一 Key 通道能正常返回。第一层在 Prometheus 里执行apiserver_request_total{jobkubernetes-apiservers, resourcepods, verbLIST}如果返回多条时间线每条对应一个scope和version组合说明采集正常。把其中一条的完整标签复制出来应该长这样apiserver_request_total{ clustercto-k8s-pro, componentapiserver, group, instance10.0.0.10:6443, jobkubernetes-apiservers, resourcepods, scopenamespace, verbLIST, versionv1 }注意group表示这是核心 API 组scopenamespace表示命名空间级别资源。这两个字段是解读 request 指标的关键。第二层拿指标里的resource去和集群对照。执行kubectl api-resources --api-groupapps输出里会有deployments、replicasets、daemonsets、statefulsets、controllerrevisions。回到 Prometheus查count by (resource) ( apiserver_request_total{jobkubernetes-apiservers, groupapps} )返回的 resource 列表应该和 kubectl 输出一致。如果 Prometheus 里多出某个 resource说明集群里装了这个 CRD 但 kubectl 没显示如果少了可能是该资源近期没有请求时间线还没生成。第三层验证统一 Key 通道。用前面准备好的 curl 命令发一次请求成功的返回结构是{ id: msg_01Xxx, type: message, role: assistant, content: [ { type: text, text: leases 属于 coordination.k8s.io 组scope 是 namespace。 } ], model: claude-sonnet-4-20250514, stop_reason: end_turn }看到content[0].text有内容返回就说明 Base URL、Key、Model ID 三件套都正确。如果返回 401检查 Key 是否复制完整如果返回 404检查 Model ID 拼写如果连接超时检查网络出口是否放行taotoken.net。三层验证都通过后你可以把这条查询固化成一个 Grafana 面板。推荐的面板查询是topk(10, sum by (resource, verb) ( rate(apiserver_request_total{jobkubernetes-apiservers, verb!~WATCH|CONNECT}[5m]) ) )排除WATCH和CONNECT是因为这两类请求的计数增长模式和短请求完全不同混在一起看会失真。5. 本篇常见报错排查401、local proxy failed 与 reading choices这一节把实际部署中最容易撞上的几个报错列出来每个都给出定位方法和修复动作。报错一Prometheus Targets 显示 401 Unauthorized错误信息通常是server returned HTTP status 401 Unauthorized。原因是 Prometheus 用的 ServiceAccount 没有访问 apiserver/metrics的权限。先确认 SA 绑定kubectl get clusterrolebinding | grep monitoring如果没有绑定system:monitoring手动加一个kubectl create clusterrolebinding prometheus-monitoring \ --clusterrolesystem:monitoring \ --serviceaccountmonitoring:prometheus-k8s注意命名空间和 SA 名称要换成你实际的。绑定后等 30 秒Targets 页面会重新抓取。报错二local proxy failed 或 connection refused这个报错说明 Prometheus 连不上 apiserver 的 6443 端口。先确认 Endpoints 里的 IP 是否正确kubectl get endpoints kubernetes-apiservers -n default -o yaml如果subsets[].addresses[].ip是空的说明 Endpoints 没配好。另外检查控制平面节点的防火墙是否放行了 Prometheus Pod 所在网段到 6443 的流量。如果是 kubeadm 集群6443 默认只监听在控制平面节点跨节点访问要确认安全组规则。报错三reading choices 或 JSON 解析失败这个报错出现在统一 Key 校验环节通常是请求体格式不对。检查 curl 命令里的content-type是否为application/json以及 JSON 是否合法。可以用jq先验证echo {model:claude-sonnet-4-20250514,max_tokens:256,messages:[{role:user,content:test}]} | jq .如果 jq 报错说明 JSON 结构有问题。另外注意max_tokens是必填项漏了会返回 400。报错四指标名不存在查询返回空如果你查apiserver_request_total返回空但 Targets 是 UP先确认 Kubernetes 版本kubectl version --short1.20 之前的版本指标名是apiserver_request_count之后才是apiserver_request_total。用错名字会返回空结果。另外确认查询时没有加多余的标签过滤比如groupapps在核心资源上是不存在的。报错五OAuth 或 token 过期如果你用的是短期 token比如通过kubectl create token生成的默认有效期 1 小时。Prometheus 的bearerTokenFile指向的是 SA 的长期 token不会过期。但如果你手动替换成了短期 token就会出现抓取一段时间后突然 401。修复方法是改回 SA token 路径或者配置 token 自动轮换。排查完这些建议把 Prometheus 的抓取错误指标也监控起来up{jobkubernetes-apiservers} 0这条告警能在采集断掉的第一时间通知你比等到看板没数据再排查要快得多。6. 把 request 指标接进日常巡检与统一入口request 指标真正的价值在日常巡检里。我习惯每周看一次这几个查询花不了几分钟但能提前发现不少问题。第一个是租约续期异常sum by (resource) ( rate(apiserver_request_total{jobkubernetes-apiservers, resourceleases, verbPUT}[1h]) )正常情况下这个值应该和集群里组件数量成正比如果突然翻倍说明某个组件的续租逻辑出了问题。第二个是 LIST 请求放大sum by (resource) ( rate(apiserver_request_total{jobkubernetes-apiservers, verbLIST, scopecluster}[1h]) )集群级别的 LIST 如果持续增长通常意味着有控制器在频繁全量拉取长期下去会拖慢 apiserver。第三个是慢请求占比sum(rate(apiserver_request_duration_seconds_bucket{jobkubernetes-apiservers, le1, verb!~WATCH|CONNECT}[5m])) / sum(rate(apiserver_request_duration_seconds_count{jobkubernetes-apiservers, verb!~WATCH|CONNECT}[5m]))这个比值低于 0.99 就值得看一眼说明有超过 1% 的请求耗时超过 1 秒。把这些查询固化成 Grafana 面板或者告警规则之后剩下的就是保持入口统一。前面用到的 TaoToken 通道除了做字段校验也可以在日常写 PromQL 拿不准标签含义时快速问一次。Key 在 https://taotoken.net/api-keys 管理接入文档在 https://taotoken.net/doc 模型对话入口在 https://taotoken.net/chat 。如果你后面要长期跑编码类或 Agent 类任务可以看 https://taotoken.net/coding-plan 控制台在 https://taotoken.net/console 。整个链路只维护一个 Key比每个工具单独配一套要省心。最后留一个实操建议把apiserver_request_total的verb标签单独拉出来做一张表对照kubectl api-resources的输出逐个确认group和resource的对应关系。这张表建一次后面解读任何 request 指标都不用再猜。
返回列表