Kibotos

集群与服务指标

本页说明 ctrl、node、E2B 网关与 Exposure 网关怎样导出 Prometheus 指标,以及怎样采集、存储并在 Grafana 里查看。

概述

每个服务可以打开一个指标监听,在上面用明文 HTTP 提供 GET /metrics,输出 Prometheus 文本格式。Kibotos 自己不采集、不存储这些指标:部署方运行采集器定期抓取,写进自己的时序存储。

ctrl 除了自己的进程指标,还在被抓取时读出整个集群的状态:node 的状态与资源、存储池、Workspace 与 Volume 的数量、进行中的命令。

这些指标与实例指标存储是两回事:

  • 实例指标存储保存每个 Instance 的 CPU、内存与磁盘读数,由 node 与 ctrl 写入,供 E2B SDK 查询。
  • 本页的指标描述服务进程与集群本身,由采集器抓取。

两者分开存储:不要把这些指标写进实例指标存储,也不要让 E2B 网关查询它们的存储。两者的保留期、读取方与访问权限都不同。

采集器与存储要能从 Kibotos 宿主访问,租户不能访问:指标里有 node ID、集群规模与错误率。

指标允许丢失,不是用量记录:计费、配额与任何状态判断都不要依据它们。

监听

服务配置参考地址
ctrl配置文件 [telemetry] 段的 listen127.0.0.1:18192
node配置文件 [telemetry] 段的 listen127.0.0.1:18191
E2B 网关环境变量 KIBOTOS_E2B_TELEMETRY_LISTEN127.0.0.1:18195
Exposure 网关环境变量 KIBOTOS_GW_TELEMETRY_LISTEN127.0.0.1:18197

参考端口是各服务主端口加 100。

  • 不配置时不开监听,升级后也不会多出端口。
  • 监听只提供 /metrics,不认证。其他路径返回 404,GET 与 HEAD 以外的方法返回 405。
  • 宿主上绑回环地址,由同一台宿主上的采集器抓取。容器里绑 0.0.0.0,再用 NetworkPolicy 只让采集器连这个端口,见 Kubernetes。
  • 地址不是 host:port 的形式时配置校验失败,服务不启动。端口已被占用时服务启动失败,日志写明地址,不会跳过指标监听继续运行。

打开监听

ctrl 与 node 在配置文件里加上下面这一段,ctrl 用 18192,node 用 18191。以 node 为例:

[telemetry]
listen = "127.0.0.1:18191"

两个网关在环境文件里加一行。以 Exposure 网关为例:

echo 'KIBOTOS_GW_TELEMETRY_LISTEN=127.0.0.1:18197' | sudo tee -a /etc/kibotos/gw/config.env >/dev/null

然后重启服务。下面的命令重启 node,并读一次它的指标:

sudo systemctl restart kibotos-node.service
curl -s http://127.0.0.1:18191/metrics | grep '^kibotos_build_info'

监听打开后,ctrl 与 node 的日志有一行 metrics enabled;两个网关的启动日志 starting kibotos-e2b gateway、starting kibotos-gw 带 telemetry_address。

导出的指标

下表按前缀概述各组指标。每个指标的类型、标签与说明见由源码生成的指标参考。

指标来自内容
kibotos_build_info全部值为 1,标签是组件、版本与 VCS revision
go_*、process_*全部Go 运行时与进程:goroutine、堆、GC、CPU、常驻内存、文件描述符
kibotos_rpc_server_*ctrl、node每个 Connect 方法的调用次数(按错误码)与一元调用的耗时
kibotos_http_server_*两个网关,node 的 /v1/files 与 /v1/service每个路由的请求数(按状态码)与耗时。WebSocket 与代理连接按整个连接计时
kibotos_cluster_*ctrl集群状态:每台 node 的状态与不可放置原因、可放置与已分配的资源、宿主用量与 PSI、时钟偏差与证书到期;存储池的容量、已保留量与对象数;Workspace 与 Volume 按状态计数;进行中的命令与最早一条已过去的时间
kibotos_ctrl_*ctrl命令结算、尝试失败与预算用尽;控制会话结束的原因;数据库连接池;集群状态读取失败
kibotos_instance_metrics_*ctrl、node实例指标写入队列的长度与丢弃的样本。没有接入实例指标存储时队列为 0
kibotos_traces_dropped_total全部没有推送到 trace 存储的 span,按原因 reason:queue_full、export_failed、no_credential。没有接入 trace 存储时为 0,见链路追踪
kibotos_node_*nodekibotos_node_info;Instance 按状态计数;guest 无响应与内存饱和、探测失败与 node 调 guest 的调用;等待重试清理的 Instance;控制连接;存储池是否可用;Template 缓存;数据面进行中的流与凭证被拒;guest 日志丢失与采样跳过
kibotos_gateway_*两个网关调 ctrl 或 node 失败的次数(按操作与错误码)、认证拒绝、代理连接异常结束
kibotos_gw_*Exposure 网关进行中的代理连接、因并发上限拒绝的连接与搬运的字节
  • 标签只有 node ID、存储池 ID、Connect 方法名与路由模式、错误码与 HTTP 状态码、命令所属的 API 方法名、网关的上游操作名,以及各指标自己的几个固定取值。Workspace、Instance、Volume 等对象的 ID,Workspace label,路径、地址、凭证与错误消息都不会成为标签,所以序列数不随 Workspace 的数量增长。
  • 按固定集合计数的指标,集合里每个取值都输出,没有发生过的为 0。
  • 集群状态(kibotos_cluster_ 开头)在 ctrl 被抓取时读库。15 秒内的抓取共用同一次读取,一次读取最长 5 秒。读取失败或超时后,15 秒内的抓取都不输出这些指标,kibotos_ctrl_cluster_read_failures_total 按读取次数加一,其余指标照常输出。
  • node 加入集群、取得身份之后才输出带 node 身份的指标。kibotos_node_info 的值为 1,标签 node_id 是 node ID;宿主上抓到的 node 指标按它对应到 node ID,见常用查询。

常用查询

想看查询(PromQL)
抓不到的进程up == 0
各状态的 node 数,retired 是退役后留下的登记sum by (status) (kibotos_cluster_node_status)
不可放置的 node 与原因kibotos_cluster_node_unready == 1
积压最久的命令max by (method) (kibotos_cluster_command_oldest_processing_seconds)
最近 5 分钟没有成功的命令结算sum by (method, code) (increase(kibotos_ctrl_command_settlements_total{code!="ok"}[5m]))
宿主上抓到的 node 指标换成 node IDkibotos_node_instances * on (job, instance, host) group_left (node_id) kibotos_node_info

参考部署:vmagent、VictoriaMetrics 与 Grafana

参考部署用 vmagent 抓取,写入一套只存这些指标的 VictoriaMetrics 单节点版,用 Grafana 查看。选 vmagent,是因为它为每个抓取目标记录 up,进程抓不到时看得出来,而且它支持按 Kubernetes Pod 发现目标。能抓取 Prometheus 文本格式的采集器、提供 Prometheus 查询接口的存储都可以替换它们。

下面几节分别在宿主上、Kubernetes 里与 Docker Compose 里装出存储与 vmagent;Grafana 一节对它们都适用。

容量

容量按序列数估算。下表是一个 KiboVM 部署跑完生命周期操作后实测的序列数:

进程序列数随什么增长
node每台约 540调用过的数据面方法与 guest 方法
ctrl约 150,另加每台登记的 node 约 20登记的 node 与存储池
E2B 网关约 110访问过的路由
Exposure 网关约 100基本固定

按每集群 2000 台 node、每 30 秒抓取一次计,约 110 万条活跃序列、每秒约 3.7 万个样本,绝大部分来自 node。一次抓取的耗时在 100 ms 以内,最长的是 ctrl,因为它要读集群状态。

宿主

宿主上的做法是在一台内网机器上运行 VictoriaMetrics,在每台运行 Kibotos 服务的宿主上运行一个 vmagent。

宿主上的 VictoriaMetrics

这一套 VictoriaMetrics 只存本页的指标,与实例指标存储分开部署。启动参数:

参数示例说明
-storageDataPath/var/lib/victoria-metrics-telemetry数据目录,放在本地磁盘
-retentionPeriod30d保留期
-httpListenAddr10.0.0.7:8428只监听采集器与 Grafana 能访问的内网地址
-httpAuth.username、-httpAuth.passwordkibotos、file:///etc/victoria-metrics/password写入与查询的认证。file:// 写法从文件读取口令,口令不出现在命令行里。需要分开写入与查询的权限时,在前面放 vmauth

宿主上的 vmagent

每台运行 Kibotos 服务的宿主运行一个 vmagent,抓本机的指标监听:

  • vmagent.yml 是抓取配置,每个服务一个 job:kibotos-ctrl、kibotos-node、kibotos-e2b、kibotos-gw。删掉这台宿主上没有的服务:连不上的目标 up 一直为 0,vmagent 每次抓取还会记一条警告。
  • kibotos-vmagent.service 是 systemd 单元。它给每条序列加上 host 标签,取值是宿主名:各宿主的抓取地址都是 127.0.0.1,没有这个标签就分不出序列来自哪台宿主。
  • 口令放在只有 root 能读的文件里,单元用 LoadCredential 把它交给 vmagent,口令不出现在命令行与环境变量里。

下面的命令下载 vmagent,核对摘要后装到 /usr/local/bin/vmagent:

set -eu
version=v1.154.0
base="https://github.com/VictoriaMetrics/VictoriaMetrics/releases/download/$version"
curl -fsSLO "$base/vmutils-linux-amd64-$version.tar.gz"
curl -fsSLO "$base/vmutils-linux-amd64-${version}_checksums.txt"
sha256sum --check --ignore-missing "vmutils-linux-amd64-${version}_checksums.txt"
tar xzf "vmutils-linux-amd64-$version.tar.gz" vmagent-prod
sudo install -m 0755 vmagent-prod /usr/local/bin/vmagent

在源码仓库的根目录执行下面的命令,装上抓取配置、口令文件与服务单元。两次 sudoedit 分别写入口令,以及把单元里的 -remoteWrite.url 改成 VictoriaMetrics 的地址;抓取配置里不需要的 job 也在 /etc/vmagent/kibotos.yml 里删掉:

set -eu
sudo install -d -m 0755 /etc/vmagent
sudo install -m 0644 deploy/metrics/vmagent.yml /etc/vmagent/kibotos.yml
sudo install -m 0600 /dev/null /etc/vmagent/remote-write-password
sudoedit /etc/vmagent/remote-write-password
sudo install -m 0644 deploy/metrics/kibotos-vmagent.service /etc/systemd/system/kibotos-vmagent.service
sudoedit /etc/systemd/system/kibotos-vmagent.service
sudo systemctl daemon-reload
sudo systemctl enable --now kibotos-vmagent.service

vmagent 的状态页只监听回环地址。下面的命令列出每个目标,state=up 表示最近一次抓取成功:

curl -s http://127.0.0.1:8429/targets

Kubernetes

Kubernetes 上由 Helm chart 装出存储,由一份清单在 kibotos 命名空间运行 vmagent;chart 还可以把数据源与看板交给 Grafana 的 sidecar。集群外宿主上的 vmagent 也可以写入同一套存储。

集群里的 VictoriaMetrics

deploy/helm/kibotos-metrics/ 在 Kubernetes 集群里装出这套 VictoriaMetrics,结构与实例指标存储的 chart相同:

  • VictoriaMetrics 单节点,跑在 StatefulSet 上,数据在持久卷里。它只在集群内可达,NetworkPolicy 只放行 vmauth 的 Pod。
  • vmauth 在前面认证。写入用户只能调 /api/v1/write,供 vmagent 使用;只读用户只能调 Prometheus 查询 API,供 Grafana 使用。口令都放在部署方创建的 Secret 里,经环境变量交给 vmauth,chart 不渲染口令。
  • vmauth 的 Service。宿主上的 vmagent 从集群外经这个地址写入;它要能被 Kibotos 宿主访问,不能被 guest 与公网访问。用内网负载均衡或 NodePort,不要给它公网地址。
  • 可选:给 Grafana sidecar 读取的数据源与看板,见Grafana sidecar。

前提:集群的 CNI 执行 NetworkPolicy,否则同一集群里的任何 Pod 都能直接读写 VictoriaMetrics。

下面的命令生成写入口令与 Grafana 的只读口令,创建命名空间与 Secret,然后安装。口令文件不能带换行:vmauth 把 Secret 的内容原样当作口令比较。示例用命名空间 kibotos-metrics、阿里云 ACK 的内网负载均衡注解;其他集群换成对应的注解,或者改用 NodePort:

set -eu
umask 077
openssl rand -hex 24 | tr -d '\n' > remote-write-password
openssl rand -hex 24 | tr -d '\n' > metrics-grafana-password
kubectl create namespace kibotos-metrics
kubectl -n kibotos-metrics create secret generic kibotos-metrics-writer --from-file=password=remote-write-password
kubectl -n kibotos-metrics create secret generic kibotos-metrics-grafana --from-file=password=metrics-grafana-password
cat > metrics.yaml <<EOF
vmauth:
  writers:
    - name: kibotos
      secretName: kibotos-metrics-writer
  readers:
    - name: grafana
      secretName: kibotos-metrics-grafana
  service:
    type: LoadBalancer
    annotations:
      service.beta.kubernetes.io/alibaba-cloud-loadbalancer-address-type: intranet
EOF
helm install kibotos-metrics deploy/helm/kibotos-metrics -n kibotos-metrics -f metrics.yaml --wait
kubectl -n kibotos-metrics get service kibotos-metrics-vmauth

最后一条输出的 EXTERNAL-IP 就是存储的地址。宿主上的 vmagent 把 -remoteWrite.url 写成 http:// 加这个地址加 :8427/api/v1/write,用户名 kibotos,口令是 remote-write-password 的内容,见宿主上的 vmagent。同一集群里的 vmagent 用集群内地址 http://kibotos-metrics-vmauth.kibotos-metrics.svc:8427/api/v1/write,见集群里的 vmagent。

Kibotos 三个存储 chart 共有的键,例如 vmauth.readers、vmauth.tls.secretName、vmauth.service.* 与存储大小,见 chart 的通用 values。本 chart 特有的键与默认值:

键说明
vmauth.writersvmagent 的写入用户,每项 name 与 secretName(键 password),至少一个。用户名就是 name。几处 vmagent 可以共用一个,也可以各用一个,便于单独更换口令
victoriaMetrics.retentionPeriod默认 30d
victoriaMetrics.storage.size默认 50Gi。200 台 node 保存 30 天约占 10 GB,按 node 数估算
victoriaMetrics.resources默认请求 1 GiB、上限 4 GiB 内存。内存随活跃序列增长,每条约 1 KiB,超过几百台 node 时调高
grafana.*给 Grafana sidecar 的数据源与看板,默认不渲染,见Grafana sidecar
  • vmauth 自己的 /metrics、/flags、pprof 与配置重载用 chart 生成的 Secret kibotos-metrics-vmauth-admin 的键 key 作 authKey,不对网络敞开。
  • 配置变化后 vmauth 重启,重启的几秒里写入失败,vmagent 把样本暂存在本地,之后补写。

集群里的 vmagent

  • kubernetes-vmagent.yaml 在 kibotos 命名空间运行一个 vmagent。它按 Pod 发现目标,只抓名为 telemetry 的容器端口;job 取 Pod 的 app.kubernetes.io/name 标签,与宿主上的 job 名相同,host 取 Pod 所在的节点,pod 取 Pod 名。它的 ServiceAccount 只能读这个命名空间里的 Pod。

  • 示例清单 ctrl.yaml、e2b.yaml 与 gw.yaml 都声明了名为 telemetry 的端口。两个网关的 ConfigMap 已经把监听设为 0.0.0.0:18195 与 0.0.0.0:18197。要打开 ctrl 的监听,在 ctrl 的 config.toml 里加上下面这一段;不加时 ctrl 目标的 up 一直为 0:

    [telemetry]
    listen = "0.0.0.0:18192"
  • 三个清单各带一个 NetworkPolicy:服务端口照常开放,telemetry 端口只允许 vmagent 的 Pod 连接。集群要启用 NetworkPolicy,否则同一集群里的任何 Pod 都能读到这些指标。

  • Service 不暴露 telemetry 端口,vmagent 直接连 Pod。

清单里的 -remoteWrite.url 是集群里的 VictoriaMetrics按示例安装后的集群内地址,用户名 kibotos。存储在别处时把它改成那个地址。把写入口令放进 Secret,再应用:

set -eu
kubectl -n kibotos create secret generic kibotos-vmagent --from-file=password=./remote-write-password
kubectl apply -f deploy/metrics/kubernetes-vmagent.yaml
kubectl -n kibotos rollout status deploy/kibotos-vmagent --timeout=5m

vmagent 的状态页只在 Pod 里监听。下面的命令把它转发到本机,之后打开 http://127.0.0.1:8429/targets 查看抓取状态:

kubectl -n kibotos port-forward deploy/kibotos-vmagent 8429:8429

Grafana sidecar

Grafana 运行在 Kubernetes 上、开了 sidecar 时,可以让 kibotos-metrics chart 渲染数据源与看板,不用手工添加和导入:

  • grafana.datasource.enabled:渲染一个带 grafana_datasource: "1" 标签的 ConfigMap,里面是 Prometheus 类型数据源的 provisioning 文件,名字 Kibotos 指标、uid kibotos-metrics,经 vmauth 以 grafana.datasource.reader 指定的只读用户查询。口令不写进 ConfigMap,文件里写 $__env{KIBOTOS_METRICS_GRAFANA_PASSWORD},由 Grafana 从自己的环境变量读取。
  • grafana.dashboards.enabled:两个看板各渲染一个带 grafana_dashboard: "1" 标签的 ConfigMap。看板的数据源变量预选 uid 为 grafana.datasource.uid 的数据源,同一个 Grafana 里还有实例指标存储等其他 Prometheus 数据源时,打开看板默认就查这一套。手工添加数据源时,把它的 uid 设成同一个值。
  • grafana.namespace:ConfigMap 所在的命名空间,默认是 chart 的命名空间。Grafana 的 sidecar 要搜索这个命名空间。标签与看板的注解可以用 grafana.datasource.labels、grafana.dashboards.labels 与 grafana.dashboards.annotations 改。

下面以 grafana-community 的 grafana chart 为例,Grafana 装在命名空间 monitoring。先把只读口令放进 Grafana 所在命名空间的 Secret:

kubectl -n monitoring create secret generic kibotos-metrics-grafana --from-file=password=metrics-grafana-password

Grafana 的 values 打开两个 sidecar,把口令交给 Grafana 的环境变量,并按注解 grafana_folder 建文件夹:

envValueFrom:
  KIBOTOS_METRICS_GRAFANA_PASSWORD:
    secretKeyRef:
      name: kibotos-metrics-grafana
      key: password
sidecar:
  datasources:
    enabled: true
  dashboards:
    enabled: true
    folderAnnotation: grafana_folder
    provider:
      foldersFromFilesStructure: true

kibotos-metrics 的 values 在前面的 metrics.yaml 基础上加上:

grafana:
  namespace: monitoring
  datasource:
    enabled: true
  dashboards:
    enabled: true
    annotations:
      grafana_folder: Kibotos

然后 helm upgrade kibotos-metrics deploy/helm/kibotos-metrics -n kibotos-metrics -f metrics.yaml。几秒后 Grafana 里出现数据源 Kibotos 指标 与文件夹 Kibotos 下的两个看板。

  • sidecar 加载的数据源与看板是只读的,在 Grafana 里改了不能保存。要改看板,改 deploy/metrics/ 里的 JSON,再 helm upgrade;chart 里的两个看板是指向这两个文件的符号链接。
  • 存储启用了 TLS 且证书由私有 CA 签发时,Grafana 要信任这个 CA,或者手工添加数据源并填上 CA。

Docker Compose

compose.yaml 已经打开两个网关的指标监听,它们只在 Compose 网络里可达,没有发布到宿主。要打开 ctrl 的监听,在 ctrl/config.toml 的 [telemetry] 一节写上 listen = "0.0.0.0:18192",它同样不发布到宿主。

在同一个 Compose 项目里加一个 vmagent 服务来抓取。它的抓取配置照 vmagent.yml 写,目标地址换成 ctrl:18192、e2b:18195 与 gw:18197:

  vmagent:
    image: docker.io/victoriametrics/vmagent:v1.154.0@sha256:2a939a9df9c8591aa5447efcd21af8c4f2ecc60ca6a8e742ffd46b9c76ef7f17
    restart: unless-stopped
    command:
      - -promscrape.config=/etc/vmagent/kibotos.yml
      - -remoteWrite.url=http://10.0.0.7:8428/api/v1/write
      - -remoteWrite.basicAuth.username=kibotos
      - -remoteWrite.basicAuth.passwordFile=/etc/vmagent/remote-write-password
      - -remoteWrite.label=host=docker-a
      - -remoteWrite.tmpDataPath=/var/lib/vmagent
    volumes:
      - ./vmagent/kibotos.yml:/etc/vmagent/kibotos.yml:ro
      - ./vmagent/remote-write-password:/etc/vmagent/remote-write-password:ro
      - vmagent-data:/var/lib/vmagent

host 写这台 Docker 宿主的名字;vmagent-data 加到文件末尾的 volumes 里。

Grafana

添加一个 Prometheus 类型的数据源:地址填 VictoriaMetrics 的 http://10.0.0.7:8428,打开 Basic auth,填用户名与口令。存储用 chart 安装时,地址填 vmauth(集群内是 http://kibotos-metrics-vmauth.kibotos-metrics.svc:8427),用户名与口令用一个只读用户的。然后导入下面两个看板,导入时选这个数据源:

看板内容
grafana-cluster.json「Kibotos 集群概览」node 状态与不可放置原因;可放置与已分配的 CPU 与内存,以及每台 node 的明细;宿主可用内存、CPU 空闲与 PSI 最差的几台;时钟偏差与证书到期;存储池的容量与已保留量;Workspace 与 Volume 按状态计数;进行中的命令、最早一条的时长与命令结算
grafana-services.json「Kibotos 服务」每个目标的 up 与版本;Connect 方法的请求速率、非 ok 比例与 p95 耗时;HTTP 路由的请求、5xx 与耗时;网关的上游失败、认证拒绝与代理连接;node 的 Instance、guest、控制连接、存储池、Template 缓存与数据面;实例指标的写入队列与丢弃;ctrl 的数据库连接池与控制会话;各进程的 Go 运行时、CPU、内存与文件描述符

实例指标存储另有「Kibotos 实例概览」与「Kibotos Workspace」两个看板,数据源指向那套存储,见实例指标存储的看板。

「Kibotos 服务」用 job、host 与 node 三个变量缩小范围。它的 node 面板用 kibotos_node_info 把宿主上的序列对应到 node ID,按 node 筛选。

排查

现象原因处理
一个目标的 up 为 0服务没有配置指标监听、没有运行,或采集器连不上它在服务所在的宿主上 curl 一次 /metrics;查看服务日志里的 telemetry_address
服务启动失败,日志有 listen for metrics on指标端口已被占用换一个端口,或停掉占用它的进程
服务启动失败,日志提到 telemetry.listen、KIBOTOS_E2B_TELEMETRY_LISTEN 或 KIBOTOS_GW_TELEMETRY_LISTEN地址不是 host:port 的形式改成 127.0.0.1:18191 这样的写法
集群概览的面板同时出现缺口,服务看板正常ctrl 那几次没有读到集群状态,常见于数据库不可用或很慢查看 kibotos_ctrl_cluster_read_failures_total,以及 ctrl 日志里的 cluster metrics read failed 记录
node 的面板没有数据,但 node 的 up 为 1node 还没有取得身份,不输出 kibotos_node_info按安装 node完成加入
不同宿主的序列混在一起宿主上的 vmagent 没有加 host 标签按参考单元加上 -remoteWrite.label=host=%H
Kubernetes 里 up 为 0,错误是连接超时NetworkPolicy 没有放行:vmagent 的 Pod 标签不是 app.kubernetes.io/name: kibotos-vmagent用参考清单里的标签,或同时修改三个 NetworkPolicy
vmagent 写入一直失败,/targets 正常,日志里远端返回 401写入口令与 vmauth 的对不上,常见于 Secret 里的口令带换行用 tr -d '\n' 去掉换行后重建 Secret,再 kubectl -n kibotos-metrics rollout restart deploy/kibotos-metrics-vmauth
Grafana 的 Kibotos 指标 数据源测试返回 401Grafana 没有 KIBOTOS_METRICS_GRAFANA_PASSWORD 环境变量,或口令与只读用户的不同按Grafana sidecar给 Grafana 加上环境变量

下一步

  • 日志:在同一批宿主上采集与查询日志。
  • 实例指标存储:让 E2B SDK 读到 sandbox 的 CPU、内存与磁盘读数。
  • 用容器运行:Kubernetes 与 Docker Compose 的示例清单。

本页内容