实例指标存储
本页介绍如何接入实例指标存储,让 E2B SDK 读到 sandbox 的 CPU、内存与磁盘读数,让原生接口与 kibo workspace metrics 读到 Workspace 的读数。
概述
sandbox.getMetrics() 与 GetWorkspaceMetrics 读的就是这些读数。实例指标存储是可选的外部依赖,由部署方运营。不接入时其他功能照常:只有两个 sandbox 指标接口返回 501,GetWorkspaceMetrics 返回 failed_precondition。
各组件的分工:
- node 每 5 秒采样每个运行中的 Instance,带着
instance_id与node_id两个标签写入存储。其中 7 个读数来自 guest;其余由 node 在宿主上读取,来源是 VMM 的 cgroup、Instance 的 TAP 设备,Firecracker 后端还有 VMM 的块设备,所以 guest 不应答时它们照常写入。 - 写入地址与凭证由 ctrl 下发,node 没有指标相关的配置。
- ctrl 写入实例信息序列
kibotos_instance_info,把 Instance 对应到它的 Workspace,并带上部署选定的 Workspace labels。 - E2B 网关查询 guest 读数与实例信息,按 sandbox 合并后返回。接口语义见 sandbox 指标。
- 配了
query_url后,ctrl 用写入的同一种 token 以同样方式查询,供GetWorkspaceMetrics使用,并一同返回宿主侧读数。方法语义见读取资源读数。
写入存储的每条序列及其读取方见序列。
指标只用于观察,不是用量或计费数据。存储不可达、guest 没有按时应答、node 重启或写入凭证过期时,对应时段的样本会丢失,之后不会补写。
它与 ctrl、node 和网关自己的指标是两回事。后者由采集器从各服务的指标监听抓取,参考部署另用一套存储,见集群与服务指标。
存储要求
| 要求 | 说明 |
|---|---|
| 写入协议 | Prometheus remote write。node 与 ctrl 写同一个存储 |
| 查询协议 | Prometheus HTTP 查询 API(/api/v1/query 与 /api/v1/query_range),支持 PromQL 子查询 |
| 保留期 | 与网关的 KIBOTOS_E2B_METRICS_RETENTION、ctrl 的 retention_seconds 相同,默认 7 天 |
| token 认证 | 验证 ctrl 签发的 JWT,按其中的 kibotos_role 放行:node 只能写入,ctrl 能写入与查询。存储一般不自己验证 JWT,由前置的代理完成 |
| 查询认证 | basic auth 或 bearer token,只放行查询 |
参考部署是 VictoriaMetrics 单节点版,前面放它的鉴权代理 vmauth。同时实现上面两种协议、并能在前面完成认证的存储都可以使用。
容量估算
- 每个运行中的 Instance 有 21 条序列,每 5 秒各一个样本:7 条 guest 序列、宿主内存、运行时长与 12 条宿主侧计数器。Firecracker 后端的 Instance 另有 4 条磁盘计数器,共 25 条。ctrl 另为每个 Instance 每分钟写一个实例信息样本。
- 1000 个同时运行的 Instance 约为每秒 4200 个样本,全是 Firecracker 时约 5000 个。在 VictoriaMetrics 上保存 7 天,占用的磁盘在 10 GB 量级。
- 每次启动 Instance(包括 sandbox 恢复)都产生一组新序列。启动频繁时,按保留期内的启动次数乘以 22(Firecracker 为 26)估算序列总数。
- 每台 node 每半小时向 ctrl 续取一次 token。
写入凭证
ctrl 用部署方生成的私钥签发写入凭证,node 不保存任何指标秘密。
| 凭证 | 谁持有 | 有效期 |
|---|---|---|
| ctrl 写入用的 token | ctrl 进程内存 | 1 小时,剩余不足一半时换新 |
| node 写入用的 token | node 进程内存,经与 ctrl 的连接取得 | 1 小时,剩余不足一半时续取 |
- token 是 ES256 签名的 JWT。
sub是 node ID,ctrl 自己的是ctrl;kibotos_role是node或ctrl。 - ctrl 没有
[metrics]段时告诉 node 不采样。node 之后每 5 分钟再问一次,所以 ctrl 加上[metrics]并重启后,node 最多 5 分钟后开始采样。 - 撤销一台 node 后,ctrl 不再给它签发;它的写入最迟在当前 token 到期时停止,最多一小时。
- ctrl 不可达期间,node 用手里的 token 写到到期为止,之后样本出现缺口,ctrl 恢复后继续写入。
在 ctrl 宿主上生成签名私钥并导出公钥。公钥不是秘密,要写进 vmauth 的配置:
sudo install -o kibotos-ctrl -g kibotos-ctrl -m 0600 /dev/null /etc/kibotos/ctrl/metrics-signing-key.pem
sudo openssl genpkey -algorithm EC -pkeyopt ec_paramgen_curve:P-256 -out /etc/kibotos/ctrl/metrics-signing-key.pem
sudo openssl pkey -in /etc/kibotos/ctrl/metrics-signing-key.pem -pubout- 私钥只给
kibotos-ctrl读取。持有它的人能以任何 node 的身份写入,也能签出一个可以读全部 Workspace 读数的 ctrl token。 - 私钥只在泄露时轮换,步骤见轮换签名私钥。
安全
- node、ctrl 与网关要能访问 vmauth。租户不能访问它:guest 网络与公网都不应能连到它的地址。能写入的人可以伪造任意 sandbox 的读数,能查询的人可以看到全部 sandbox 的读数。
- 被攻破的 node 在当前 token 到期前仍能写入,可以搅乱它知道 ID 的 sandbox 的读数,但不能查询。
- ctrl 的 token 能读全部 Workspace 的读数。它只在 ctrl 进程内存里。
- ctrl 只把
instance_info_labels列出的 Workspace labels 写入存储。E2B 部署列哪些见ctrl 的配置。
参考部署:VictoriaMetrics 与 vmauth
VictoriaMetrics 只听同机 vmauth 能访问的地址,自身不设口令;vmauth 对外提供写入与查询入口,并负责认证:
| 用途 | 地址 |
|---|---|
ctrl 的 remote_write_url,node 从 ctrl 取得同一个地址 | https://metrics.example.com:8427/api/v1/write |
网关的 KIBOTOS_E2B_METRICS_URL | https://metrics.example.com:8427 |
ctrl 的 query_url | https://metrics.example.com:8427 |
VictoriaMetrics 的启动参数:
| 参数 | 示例 | 说明 |
|---|---|---|
-retentionPeriod | 7d | 保留期,对应网关的默认值 168h |
-httpListenAddr | 127.0.0.1:8428 | 只让同机的 vmauth 访问 |
-storageDataPath | /var/lib/victoria-metrics | 数据目录 |
vmauth 至少用 v1.152.0,这个版本修复了按 JWT claim 选择路由时的授权绕过。启动参数:
| 参数 | 示例 | 说明 |
|---|---|---|
-auth.config | /etc/vmauth/auth.yml | 下面的配置文件 |
-httpListenAddr | 10.0.0.5:8427 | 只监听 ctrl、node 与网关能访问的内网地址 |
-tls、-tlsCertFile、-tlsKeyFile | 证书与私钥的路径 | 流量经过不受信任的网络时启用 HTTPS |
-configCheckInterval | 1m | 定期重读配置,改公钥或口令后不必重启 |
把在写入凭证里导出的公钥写进 vmauth 配置的三个 JWT 用户。网关的口令从 vmauth 进程的环境变量 KIBOTOS_E2B_METRICS_PASSWORD 读取:
users:
- name: kibotos-other-sink
jwt:
default_vm_access_claim: {}
public_keys:
- |
-----BEGIN PUBLIC KEY-----
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE...
-----END PUBLIC KEY-----
match_claims:
kibotos_role: ".+"
kibotos_sink: ".+"
url_map:
- src_paths: [".*"]
deny_paths: [".*"]
url_prefix: "http://127.0.0.1:1"
- name: kibotos-node
jwt:
default_vm_access_claim: {}
public_keys:
- |
-----BEGIN PUBLIC KEY-----
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE...
-----END PUBLIC KEY-----
match_claims:
kibotos_role: node
url_map:
- src_paths: ["/api/v1/write"]
url_prefix: "http://127.0.0.1:8428/"
- name: kibotos-ctrl
jwt:
default_vm_access_claim: {}
public_keys:
- |
-----BEGIN PUBLIC KEY-----
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE...
-----END PUBLIC KEY-----
match_claims:
kibotos_role: ctrl
url_map:
- src_paths: ["/api/v1/write", "/api/v1/query", "/api/v1/query_range"]
url_prefix: "http://127.0.0.1:8428/"
- name: kibotos-e2b
username: kibotos-e2b
password: "%{KIBOTOS_E2B_METRICS_PASSWORD}"
url_map:
- src_paths: ["/api/v1/query", "/api/v1/query_range"]
url_prefix: "http://127.0.0.1:8428/"- node 的 token 只能写入;ctrl 的 token 能写入,也能查询,供
GetWorkspaceMetrics使用;网关的口令只能查询。其他路径一律拒绝。 kibotos-other-sink拒绝带kibotos_sink声明的 token,即 ctrl 签的追踪 token,返回 403。指标 token 不带这个声明,match_claims又写不出「不带某个声明」,所以要靠这个用户:vmauth 先试match_claims条目多的用户,它比另两个 JWT 用户多一条。链路追踪与实例指标共用一把私钥时,两个存储因此互相隔离。- 三个 JWT 用户都要有
default_vm_access_claim: {}。vmauth 只放行带vm_access声明的 token,或配了这一项的用户;ctrl 签的 token 不带vm_access,缺了这一项时所有写入都返回 401。 - 公钥直接写在配置文件里,不放单独的文件:vmauth 只在配置文件本身变化时重新加载。
-search.latencyOffset保持默认值30s时,网关的查询延迟用默认值即可。调大它时同步调大网关的KIBOTOS_E2B_METRICS_QUERY_DELAY,见E2B 网关的配置。
Kubernetes 上的参考部署
deploy/helm/kibotos-instance-metrics/ 是同一套参考部署的 Helm chart,在 Kubernetes 集群里装出:
- VictoriaMetrics 单节点,跑在 StatefulSet 上,数据在持久卷里。它只在集群内可达,NetworkPolicy 只放行 vmauth 的 Pod。
- vmauth,配置就是上面的
auth.yml:公钥从 values 传入,网关口令从部署方创建的 Secret 经环境变量注入,chart 不渲染口令。vmauth 自己的/metrics、/flags、pprof 与配置重载用 chart 生成的 Secret<release>-vmauth-admin的键key作authKey,不对网络敞开。 - vmauth 的 Service。ctrl、node 与网关运行在集群外,经这个地址访问;它要能被三者访问,不能被 guest 与公网访问。用内网负载均衡或 NodePort,不要给它公网地址。
前提:签名私钥已按写入凭证生成;集群的 CNI 执行 NetworkPolicy,否则同一集群里的任何 Pod 都能直接写 VictoriaMetrics。
把导出的公钥存为 metrics-signing-public.pem,生成网关口令,创建命名空间与口令 Secret,然后安装。口令文件不能带换行:vmauth 把 Secret 的内容原样当作口令,多一个换行网关就对不上。示例用命名空间 kibotos-instance-metrics、阿里云 ACK 的内网负载均衡注解;其他集群换成对应的注解,或者改用 NodePort:
set -eu
umask 077
openssl rand -hex 24 | tr -d '\n' > metrics-query-password
kubectl create namespace kibotos-instance-metrics
kubectl -n kibotos-instance-metrics create secret generic kibotos-instance-metrics-query --from-file=password=metrics-query-password
cat > instance-metrics.yaml <<EOF
vmauth:
publicKeys:
- |
$(sed 's/^/ /' metrics-signing-public.pem)
query:
secretName: kibotos-instance-metrics-query
service:
type: LoadBalancer
annotations:
service.beta.kubernetes.io/alibaba-cloud-loadbalancer-address-type: intranet
EOF
helm install kibotos-instance-metrics deploy/helm/kibotos-instance-metrics -n kibotos-instance-metrics -f instance-metrics.yaml --wait
kubectl -n kibotos-instance-metrics get service kibotos-instance-metrics-vmauth最后一条输出的 EXTERNAL-IP 就是存储的地址:ctrl 的 remote_write_url 写 http:// 加这个地址加 :8427/api/v1/write,网关的 KIBOTOS_E2B_METRICS_URL 写 http:// 加这个地址加 :8427,KIBOTOS_E2B_METRICS_PASSWORD 是 metrics-query-password 的内容。给地址配一个 DNS 名字时,ctrl 与网关都用那个名字。
本 chart 特有的键与默认值见下表;与另外两个存储 chart 共有的键见 chart 的通用 values。
| 键 | 说明 |
|---|---|
vmauth.publicKeys | 公钥 PEM 的列表,必填。可以有多把,轮换私钥期间新旧并存 |
vmauth.query.secretName、vmauth.query.username | 口令 Secret 的名字(键 password),必填;用户名默认 kibotos-e2b |
victoriaMetrics.retentionPeriod | 默认 7d。改了就同步改网关的 KIBOTOS_E2B_METRICS_RETENTION 与 ctrl 的 retention_seconds |
victoriaMetrics.storage.size | 默认 20Gi |
- 设了
vmauth.tls.secretName、证书由私有 CA 签发时,CA 交给 ctrl 的ca_file与网关的KIBOTOS_E2B_METRICS_CA_FILE。 - 配置变化后 vmauth 重启,重启的几秒里写入失败,这段时间的样本有缺口,之后 node 与 ctrl 继续写入。
- 轮换签名私钥的第 2 步与第 4 步在这里就是改
vmauth.publicKeys再helm upgrade。
chart 的通用 values
三个存储 chart 共有下面这些键:本 chart、集群与服务指标的 kibotos-metrics,以及链路追踪的 kibotos-traces。kibotos-traces 里存储的键以 victoriaTraces. 开头,不是 victoriaMetrics.。每个 chart 的 values.yaml 在注释里说明了全部键。
| 键 | 说明 |
|---|---|
vmauth.readers | 给看板用的只读用户,每项 name 与 secretName(键 password),名字只用小写字母、数字与连字符。两个指标 chart 里只能调 Prometheus 查询 API:query、query_range、query_exemplars、series、labels、label/<名字>/values、metadata、status/buildinfo;kibotos-traces 里只能调 /select/jaeger/api/ 下的 Jaeger 查询 API |
vmauth.tls.secretName | kubernetes.io/tls 类型的 Secret。设了之后 vmauth 只提供 HTTPS,地址改用 https://。流量经过不受信任的网络时启用 |
vmauth.service.type、annotations、loadBalancerIP、loadBalancerSourceRanges、nodePort | Service 的类型与限制。类型默认 ClusterIP,只在集群内可达;端口 port 默认 8427 |
victoriaMetrics.retentionPeriod | 保留期,各 chart 的默认值不同 |
victoriaMetrics.storage.size、victoriaMetrics.storage.storageClassName | 持久卷大小与 StorageClass。StorageClass 留空时用集群默认的 |
victoriaMetrics.resources、vmauth.resources | 两个容器的资源请求与上限 |
victoriaMetrics.extraArgs、vmauth.extraArgs | 额外的启动参数,每项一个 -name=value |
- 镜像按 digest 固定。vmauth 与集群与服务指标的 vmagent 同一版本。
- 改 values 后
helm upgrade。vmauth 的配置变化会让它重启。 helm uninstall不删除持久卷,确认不要数据后再删 PVC。
ctrl 的配置
只有 ctrl 有 [metrics] 段。没有这个段时,ctrl 不写实例信息序列,node 不采样。每个键的取值范围与默认值见 ctrl 配置参考的 [metrics]。
在 /etc/kibotos/ctrl/config.toml 末尾加上:
[metrics]
remote_write_url = "https://metrics.example.com:8427/api/v1/write"
signing_key_file = "/etc/kibotos/ctrl/metrics-signing-key.pem"
instance_info_labels = ["e2b.kibotos.app/namespace", "e2b.kibotos.io/namespace"]
query_url = "https://metrics.example.com:8427"然后重启 ctrl。node 不需要改配置,也不需要重启。
- 文件都用绝对路径,可以是符号链接,最终指向的要是
kibotos-ctrl能读取的普通文件。 retention_seconds要等于存储的保留期,query_delay_seconds不能小于存储的可见延迟,规则与E2B 网关的配置相同。默认值与参考部署一致。- E2B 部署把
instance_info_labels写成命名空间的两个 key:e2b.kibotos.app/namespace,以及v0.3.0之前的网关写的e2b.kibotos.io/namespace,后者到v0.4.0去掉。缺少前者时,网关找不到任何 sandbox 的 Instance,所有 sandbox 的指标都是空数组。 - E2B sandbox metadata 生成的 labels(
m.e2b.kibotos.app/前缀)是调用方的数据,不要列入。 kibotos-ctrl的init、enrollment create、check-upgrade与服务本身都校验[metrics]并读取私钥与 CA 文件,与dsn_file相同。文件读不到或格式不对时这些命令都会失败。migrate只读取数据库连接,不校验[metrics]。- 启用后,ctrl 日志有一行
instance info series enabled,每台 node 日志有一行guest metrics sampling enabled。配了query_url时 ctrl 日志还有一行Workspace metrics reads enabled。 - Platform 的 guest 早于采样接口时,node 不采样这个 Instance,日志记一行
guest does not support resource sampling。
E2B 网关的配置
在 /etc/kibotos/e2b/config.env 里填写下面的变量,然后重启网关。示例见 e2b.example.env 末尾。
| 变量 | 说明 |
|---|---|
KIBOTOS_E2B_METRICS_URL | 查询 API 的基础地址,不带 /api/v1,例如 https://metrics.example.com:8427。留空时两个 sandbox 指标接口返回 501,能力名 metrics |
KIBOTOS_E2B_METRICS_USERNAME | basic auth 用户名,参考部署是 kibotos-e2b |
KIBOTOS_E2B_METRICS_PASSWORD | basic auth 口令,与 vmauth 配置里的相同 |
KIBOTOS_E2B_METRICS_BEARER_TOKEN | bearer token。与 basic auth 只能选一种 |
KIBOTOS_E2B_METRICS_CA_FILE | 可选。替换系统根证书的 PEM 文件,kibotos-e2b 账户要能读取 |
KIBOTOS_E2B_METRICS_RETENTION | 存储的保留期,写法如 168h,默认 168h。必须与存储的保留期相同 |
KIBOTOS_E2B_METRICS_QUERY_DELAY | 查询延迟,写法如 30s,默认 30s。网关只返回在「当前时间减去查询延迟」之前已经结束的桶,批量接口的最新样本也只取到这个时刻。不能小于存储的可见延迟 |
- 没有设置地址、却设置了凭证或 CA 时,网关拒绝启动。
- 查询延迟要不小于存储的可见延迟,也就是新写入的样本多久之后才出现在查询结果里。VictoriaMetrics 的可见延迟是
-search.latencyOffset,默认30s,与网关的默认值相同;调大它时同步调大查询延迟。网关按本机时钟计算截止时刻,与存储所在宿主机的时钟有偏差时再留出余量。 - 查询延迟小于可见延迟时,最近一段的桶可能是存储补出来的值:刚暂停的 sandbox 末尾会多出没有样本的桶,稍后又消失;批量接口也可能找不到最新样本。
- 查询延迟设为
0只适合样本写入后立即可查的存储。 - 同一部署的所有网关实例使用相同的指标配置。
- 启用后,启动日志
starting kibotos-e2b gateway一行的sandbox_metrics为true。
确认
用 E2B SDK 创建一个 sandbox,它运行一分钟后 sandbox.getMetrics() 应返回非空数组。样本要过了查询延迟(默认 30 秒)才会返回。
也可以用网关的口令直接查询,确认两类序列都已写入。curl 会提示输入口令:
curl -sS -u kibotos-e2b --get \
--data-urlencode 'query=count by (__name__) ({__name__=~"kibotos_instance_info|kibotos_guest_cpu_count"})' \
https://metrics.example.com:8427/api/v1/query结果里应同时出现 kibotos_instance_info 与 kibotos_guest_cpu_count。
配了 query_url 后,对一个运行了一分钟的 Workspace,kibo workspace metrics <workspace-id> 应显示宿主侧与 guest 内两组读数。返回 unavailable、ctrl 日志里 workspace metrics unavailable 带着 vmauth 的 HTTP 400 或 401 时,vmauth 配置里 ctrl 用户缺那两个查询路径。
轮换签名私钥
签名私钥只在泄露时轮换。按下面的顺序做,写入不会中断:
- 生成新私钥,导出新公钥。
- 把新公钥加到 vmauth 配置三个 JWT 用户的
public_keys,旧公钥保留。等 vmauth 重新加载配置。Kubernetes 上是把新公钥追加到 values 的vmauth.publicKeys,再helm upgrade。 - 用新私钥替换
signing_key_file指向的文件,重启 ctrl。 - 一小时后,旧私钥签的 token 都已到期,从 vmauth 配置里删掉旧公钥。
看板
实例指标有两个 Grafana 看板,导入时都选一个指向实例指标存储的 Prometheus 类型数据源。数据源用 chart 的通用 values 里 vmauth.readers 的只读用户,不要用网关的口令。集群内的地址按示例的命名空间是 http://kibotos-instance-metrics-vmauth.kibotos-instance-metrics.svc:8427,Basic auth 填这个用户的名字与口令。类型要选 Prometheus 而不是 VictoriaMetrics 插件:看板只用标准 PromQL,数据源变量也只列 Prometheus 类型的数据源。
| 看板 | 内容 |
|---|---|
grafana-instances.json「Kibotos 实例概览」 | 总览:采样中与 ctrl 登记的 Instance 数、分配的 vCPU 与 guest 内存、宿主实占的 guest 内存与实占比、内存或磁盘超过 90% 的 Instance 数、vCPU 加权的 CPU 忙碌率、最近 5 分钟出现与消失的 Instance。采样健康:最近 2 分钟没有样本的 node、ctrl 实例信息最近写入距今、有实例信息却没有 guest 样本(以及反过来)的 Instance 列表、每台 node 最近一次样本距今。按 node 与按命名空间的 vCPU、内存、宿主实占与根文件系统分布。CPU 最忙、内存使用率最高、磁盘最满、宿主占用最多、运行最久的前 15 个 Instance |
grafana-workspace.json「Kibotos Workspace」 | 一个 Workspace 各个 Instance 的 CPU、内存(used、cache、total)、根文件系统、宿主实占对比 guest 分配、vCPU 数,以及 Instance 所在的 node 与运行时长 |
- 概览的变量
node、命名空间缩小范围;表格里的 Workspace 可以点进「Kibotos Workspace」,带着命名空间与时间范围。 - 命名空间来自实例信息上的
label_e2b_kibotos_app_namespace,instance_info_labels没有列e2b.kibotos.app/namespace时按命名空间的面板为空。v0.3.0之前写入的样本带的是label_e2b_kibotos_io_namespace,按命名空间的面板不显示它们。 kibotos_instance_host_memory_bytes与kibotos_instance_uptime_seconds从v0.2.0的 node 起写入,更早的版本这几块没有数据。- 看板暂不展示宿主侧计数器与磁盘计数器。宿主侧的 CPU、压力与网络计数器从
v0.3.0的 node 起写入。 - 「采样健康」里的列表与计数正常时为空或为 0。刚启动的 Instance 在第二次采样之前只有实例信息、没有 guest 样本,属正常。
序列
下面的序列由 node 写入,带 instance_id 与 node_id 两个标签,每个运行中的 Instance 每 5 秒一个样本;kibotos_instance_info 由 ctrl 写入。
| 序列 | 值 | 读取方 |
|---|---|---|
kibotos_guest_cpu_count | guest 在线的 CPU 数 | E2B 网关、GetWorkspaceMetrics、看板 |
kibotos_guest_cpu_used_percent | 自上一个样本以来 guest CPU 时间里忙碌的比例,0 到 100。idle 与 iowait 不算忙碌 | E2B 网关、GetWorkspaceMetrics、看板 |
kibotos_guest_memory_total_bytes | guest 的 MemTotal | E2B 网关、GetWorkspaceMetrics、看板 |
kibotos_guest_memory_used_bytes | guest 的 MemTotal 减 MemAvailable | E2B 网关、GetWorkspaceMetrics、看板 |
kibotos_guest_memory_cache_bytes | guest 的 Cached | E2B 网关、GetWorkspaceMetrics、看板 |
kibotos_guest_disk_total_bytes、kibotos_guest_disk_used_bytes | guest 看到的 / 所在文件系统的大小,以及它减去非特权用户可用空间后的值 | E2B 网关、GetWorkspaceMetrics、看板 |
kibotos_instance_host_memory_bytes | VMM 在宿主上占用的 guest 内存:VMM 的 cgroup 的 memory.stat 里 anon 与 shmem 之和。用它按 Instance 查看实际占用、估算内存超卖倍数 | GetWorkspaceMetrics、看板 |
kibotos_instance_uptime_seconds | VMM 进程启动以来的时长。一个 VMM 进程就是一次 guest 开机,node 升级接管时不重新计时 | 看板 |
| 12 条宿主侧计数器 | VMM 的 cgroup 与 Instance 的 TAP 设备。guest 不应答时可以看出 VMM 是否仍在消耗 CPU、网络是否还有收发 | GetWorkspaceMetrics |
| 4 条磁盘计数器 | VMM 的块设备,只有 Firecracker 后端 | 暂无 |
kibotos_instance_info | 值为 1。标签是 instance_id、workspace_id,以及 instance_info_labels 里每个 key 各一个。ctrl 在 Instance 运行后写入,之后每分钟一次 | E2B 网关、GetWorkspaceMetrics、看板 |
宿主侧计数器
| 指标 | 来源 |
|---|---|
kibotos_instance_cpu_seconds_total | VMM 单元 cgroup 的 cpu.stat usage_usec:VMM 的全部线程,Firecracker 还包括 jailer |
kibotos_instance_cpu_pressure_some_seconds_total | 该 cgroup 的 cpu.pressure some 行的 total |
kibotos_instance_memory_pressure_some_seconds_total、kibotos_instance_memory_pressure_full_seconds_total | memory.pressure 的 some、full 行 |
kibotos_instance_io_pressure_some_seconds_total、kibotos_instance_io_pressure_full_seconds_total | io.pressure 的 some、full 行 |
kibotos_instance_network_receive_bytes_total、kibotos_instance_network_transmit_bytes_total | Instance 的 TAP 设备的字节数 |
kibotos_instance_network_receive_packets_total、kibotos_instance_network_transmit_packets_total | TAP 的包数 |
kibotos_instance_network_receive_dropped_total、kibotos_instance_network_transmit_dropped_total | TAP 的丢包数 |
- 时间都换算成秒。用
rate()或increase()读:采样丢点时区间内的总量仍然正确。 - 每次启动 VMM 都有新的 cgroup,CPU 与压力计数器从 0 开始,查询按计数器重置处理。
- 宿主内核关闭了 PSI(
psi=0)时不写三类压力计数器,node 日志记一次,其他序列照常。 - 网络方向按 guest 的视角:TAP 发出的是 guest 收到的。TAP 是 guest 网卡在宿主侧的一端,经 Egress 转发的流量、经 Resolver 应答的 DNS 查询也经过它;exec、文件与端口转发走 vsock,不计入。
磁盘计数器
| 指标 | 来源 |
|---|---|
kibotos_instance_disk_read_bytes_total、kibotos_instance_disk_written_bytes_total | guest 向它的全部虚拟盘读、写的字节数,由 VMM 的块设备按请求累计 |
kibotos_instance_disk_read_requests_total、kibotos_instance_disk_write_requests_total | 读、写请求数 |
- 计数的是 guest 请求了多少,与宿主页缓存是否命中、盘放在本地还是 NFS 存储池上无关。只读的 Template 基础层、可写层与 Volume 合在一起。
- 数据面传输本身不计入;上传的文件写到盘上时按写入计。
- 用
rate()或increase()读。新的 VMM 与 node 重启接管时都从 0 开始,查询按计数器重置处理。 - 目前只有 Firecracker 后端写这 4 条:node 在 VMM 开机前把 Firecracker 的 metrics 指向 jail 里的命名管道,每轮采样时让它 flush 再读取。KiboVM 后端暂不写。
- 升级前启动的 Firecracker VMM 没有配置 metrics,重启之前不写。
- 宿主侧的 cgroup
io.stat与/proc/<pid>/io量的是宿主存储层:NFS 上的块文件不计入io.stat,缓存命中的读不计,同一块回写前的重复写只计一次。要看存储被压了多少,读它们;要看 Instance 做了多少 IO,读这 4 条。
排查
| 现象 | 原因 | 处理 |
|---|---|---|
两个 sandbox 指标接口返回 501 metrics | 网关没有设置 KIBOTOS_E2B_METRICS_URL | 设置后重启网关 |
所有 sandbox 都返回 [] | ctrl 没有 [metrics] 段,或 instance_info_labels 缺少 e2b.kibotos.app/namespace | 补上后重启 ctrl |
个别 sandbox 始终返回 [] | 它所用 Platform 的 guest 早于采样接口,node 日志有 guest does not support resource sampling | 用这个版本发布 Platform 并设为默认版本,之后创建的 sandbox 会被采样 |
| 接口返回 500 | 网关连不上存储,或认证失败 | 查看网关日志里的 sandbox metrics unavailable |
| 最后一个桶重复前一个桶的值,稍后又消失;批量接口返回的 sandbox 时有时无 | 查询延迟小于存储的可见延迟 | 把 KIBOTOS_E2B_METRICS_QUERY_DELAY 调到不小于存储的可见延迟后重启网关 |
样本出现缺口,node 与 ctrl 日志有 metrics remote write rejected 与 HTTP 401 | vmauth 的公钥与 ctrl 的私钥不匹配,JWT 用户缺少 default_vm_access_claim,或 vmauth 早于 v1.152.0 | 对照上面的配置检查 vmauth,重新导出公钥 |
样本出现缺口,node 日志有 metrics write credential request failed | node 连不上 ctrl,token 到期后停止写入 | 恢复 node 与 ctrl 的连接,node 会自动续取 |
| 样本出现缺口 | 存储短暂不可达,或拒绝了写入 | 查看 node 与 ctrl 日志里的 metrics remote write failed、metrics samples dropped |