Appearance
监控读什么、Trace 写什么、回滚验证什么
可选监控配置在 deploy/observability;Prometheus 通过 EndpointSlice 发现 chart-demo 的就绪端点,逐 Pod 抓样;如果只抓 Service 地址,一次 scrape 只会落到其中一个副本。Grafana 用同一个 Prometheus datasource 检查队列而非展示伪造的 GPU 显存。先人工执行 PromQL,确认单个标量及非空样本,再启用 KEDA;没有 KEDA CRD 时启用会安装失败。Prometheus scaler 参数。
sh
kubectl -n modeldock-lab create configmap prometheus-config --from-file=deploy/observability/prometheus.yml --from-file=deploy/observability/alerts.yml --dry-run=client -o yaml | kubectl apply -f -
kubectl apply -f deploy/observability/stack.yaml
helm upgrade --install keda keda --repo https://kedacore.github.io/charts --namespace keda --create-namespace --wait
helm template handbook deploy/chart -n modeldock-lab --set autoscale=true
# 先安装 KEDA 并验证指标,再部署;网关开启时保留原有 values
helm upgrade handbook deploy/chart -n modeldock-lab --reuse-values --set autoscale=true --set maxReplicas=2 --set prometheusURL=http://prometheus.modeldock-lab.svc:9090
helm history handbook -n modeldock-lab
# REV 是上一份已验证可用的 revision
helm rollback handbook "$REV" -n modeldock-lab --wait既要看 Ready,也要看业务流量。滚动中出现 503 先看 discovery 快照、端点是否就绪、readiness 和模型加载;不要马上调大超时。滚回镜像不能回滚数据库 schema,表结构变更要先兼容旧版本。日志记录 task_id、resource UID、operation ID;不要记录完整 Authorization 或 kubeconfig。图的 trace 是结构化节点轨迹,外接 OpenTelemetry exporter 时应对 tool 参数做脱敏,避免日志内容被索引。
PostgreSQL 检查点、可选 Redis 限流和 OTel spans 已有工程接口。MySQL HA、跨实例审批锁、集中身份审计及异地故障转移仍需独立验收。Secret 的 Base64 编码不是加密;使用外部 Secret 管理或 etcd 静态加密,并限制读取范围。NetworkPolicy 需要 CNI 支持。灰度建议先单独 Service 暴露新 runtime,对相同请求做低比例流量验证,再变更主服务选择;恢复条件以错误率与延迟窗口定义。
建立最短的因果链
队列变长不一定是 GPU 忙:先确认 Prometheus 有目标样本、HPA 已作决定,再查新 Pod 是否绑定、是否 Ready,最后查网关的首内容时间。只看一个总 GPU 使用率无法分辨模型冷启动、镜像拉取或客户端太慢。指标标签不要使用请求 ID,任务级关联用日志和 trace。
完整源码:opspilot/cluster/instrument.py · 第 5–24 行
python
def configure():
if not (os.getenv("OPS_TRACE_FILE") or os.getenv("OTEL_EXPORTER_OTLP_ENDPOINT")):return
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import BatchSpanProcessor, ConsoleSpanExporter
from opentelemetry.sdk.resources import Resource
provider=TracerProvider(resource=Resource.create({"service.name":"opspilot"}))
if os.getenv("OPS_TRACE_FILE"):
stream=open(os.environ["OPS_TRACE_FILE"],"a")
atexit.register(stream.close);exporter=ConsoleSpanExporter(out=stream)
else:
from opentelemetry.exporter.otlp.proto.http.trace_exporter import OTLPSpanExporter
exporter=OTLPSpanExporter()
provider.add_span_processor(BatchSpanProcessor(exporter));trace.set_tracer_provider(provider)
atexit.register(provider.shutdown)
def instrument(fn):
@functools.wraps(fn)
def wrapper(state):
with trace.get_tracer("opspilot.graph").start_as_current_span(fn.__name__) as span:
span.set_attribute("run.id",state["id"]);span.set_attribute("evidence.count",len(state.get("observations",{})))
return fn(state)Grafana 配置库位于 deploy/observability/grafana.json;若已有 Grafana,建立 Prometheus 数据源,URL 指向 http://prometheus.modeldock-lab.svc:9090,在 Dashboards → Import 导入该文件。Grafana 若在宿主机运行,应先 port-forward,Service DNS 只在集群内可用。OpenTelemetry 导出目的地由 OPS_TRACE_FILE 或 OTEL_EXPORTER_OTLP_ENDPOINT 选择;文件 span 可校验节点名、任务关联和执行时间,不记录密钥。Prometheus 在此教学栈使用 emptyDir;Pod 重建会丢历史,生产需持久卷、保留期、备份和查询限额。
sh
kubectl -n modeldock-lab get deploy prometheus
kubectl -n modeldock-lab port-forward svc/prometheus 19090:9090
# 另一终端
curl -fsSG http://127.0.0.1:19090/api/v1/query --data-urlencode 'query=sum(modeldock_waiting_requests)'
helm -n modeldock-lab history handbook无样本和数值 0 不同。恢复验证要回放同一请求和权限身份,比较错误、首内容延迟和就绪世代;除非已做独立存储演练,不能声称已验证异地容灾。
在 Kind 里配置实际 Grafana
下列命令从根目录执行。values 会创建 ModelDock Prometheus 数据源,并把同一个 dashboard JSON 挂入 Grafana。只在专用实验 namespace 安装,不开放公网入口。
sh
kubectl create ns cloudlab-dash --dry-run=client -o yaml | kubectl apply -f -
kubectl -n cloudlab-dash create configmap modeldock-dashboards --from-file=queue.json=deploy/observability/grafana.json --dry-run=client -o yaml | kubectl apply -f -
helm upgrade --install board grafana --repo https://grafana-community.github.io/helm-charts --version 14.4.1 -n cloudlab-dash --create-namespace -f deploy/observability/grafana-values.yaml --wait
kubectl -n cloudlab-dash port-forward svc/board-grafana 19300:80
# 另一终端;密码仅复制到自己 Mac 剪贴板,在本地页面登录 admin
kubectl -n cloudlab-dash get secret board-grafana -o jsonpath='{.data.admin-password}' | base64 -D | pbcopy打开 http://127.0.0.1:19300,在 Dashboards → ModelDock queue 查看队列,再打开数据源执行 Save & Test。无曲线先查 Prometheus 是否抓到 modeldock_waiting_requests。清理:停止 port-forward,运行 helm uninstall board -n cloudlab-dash;仅当该 namespace 专用于本实验时再删除它。
本轮用 Grafana 13.3.1、chart 14.4.1 在临时 Kind namespace 部署,请求 dashboard UID modeldock-queue 得到 ModelDock queue,datasource UID modeldock-prom 的 health 返回 OK。本机镜像索引的部分平台摘要在 kind load 时不可导入,验收使用相同镜像的 linux/arm64 根文件系统重装本地教学镜像后加载。这不验证生产镜像签名;默认命令直接使用官方镜像,需要节点能访问镜像仓库。