常见问题
按主题整理 Helm Chart 部署与运行中的高频问题。先对照本节;仍无法解决时再看 Helm 安装、架构说明、升级。提 Issue 时请附上文末提问模板。
命令里的资源名
下文示例默认 Release 名为 cube、命名空间为 cube-system(资源名形如 cube-master、cube-secret)。若 Release 名不同,请换成 <release>-…,或改用 app.kubernetes.io/component=… 标签选择器(不依赖 Release 名)。
目录
安装与校验
helm install 报错要配置 placement.*.nodeSelector
Chart 用 templates/validate.yaml 禁止「通配」部署,避免误伤节点。补上明确的 nodeSelector,例如:
placement:
controlPlane:
nodeSelector:
cube.tencent.com/cube-control: "true"同类校验:
| 报错关键字 | 含义 |
|---|---|
cube-node requires placement.compute.nodeSelector | 计算节点必须显式指定 |
…placement.pvm… allow-pvm-bootstrap | PVM DaemonSet 的 selector 必须含该 label;不要写进 placement.compute |
placement.compute… must not include …allow-pvm-bootstrap | 写进 compute 会让所有计算节点拉 PVM 大镜像 |
cubeProxy.enabled=true requires placement.controlPlane.nodeSelector | Proxy 跑在控制面节点上 |
configureClusterDNS=true requires cubeProxy.domain | 注入集群 DNS 时必须有 sandbox 域名 |
节点怎么打标签见 Helm 安装 · 打标签。
计算面 DaemonSet Ready 数不够
先看四条原生 DaemonSet:
kubectl -n cube-system get daemonset \
-l 'app.kubernetes.io/component in (cube-node,cube-node-installer,cube-node-bootstrap,cube-node-pvm)'| 现象 | 处理 |
|---|---|
DESIRED=0 | 没有节点匹配 placement.compute → 补 cube-node=true label |
CURRENT < DESIRED | 污点挡住了 → 检查 compute 污点与 toleration |
READY < CURRENT | Pod 起来了但未 Ready → Big Pod 先看 wait-node-prep 与 bootstrap,见计算面 |
helm test 里 CubeAPI /health 失败
多数是 CubeAPI 未 Ready,或 MySQL / migration 未完成:
kubectl -n cube-system logs -l app.kubernetes.io/component=api --tail=200
kubectl -n cube-system logs -l app.kubernetes.io/component=master -c cube-master --tail=200- CubeMaster 内嵌 schema migration,首次可能要几分钟;安装时用
--timeout 90m - 日志若是 MySQL connection refused → 见控制面 / 数据库
helm test 卡住、既不超时也没结果
Helm 3.13+ 才让 --timeout 对 test hook 生效。加上 --logs:
helm test cube -n cube-system --logs --timeout 20m单独看失败的测试 Pod:
kubectl -n cube-system get pods -l app.kubernetes.io/component=test
kubectl -n cube-system logs <test-pod-name>节点与调度
能不能少打几枚 label?
不建议。Chart 用显式 label 授权,是因为:
pvm-host-bootstrap会换 host kernel 并可能 reboot- 计算面有 privileged / hostPath,误调度代价大
生产可用 GitOps / Terraform 统一管 label。
控制面节点能否兼做计算节点?
技术上可以(单节点试用);生产不建议——资源争抢、升级策略也不同。
混部时:
- 同一节点打两枚独立 label:
cube-control=true与cube-node=true(不要用同一个 key 覆盖写) - 叠加
values-single-node.yaml,让控制面 / 计算面都容忍两把角色污点 - 需要 PVM 时再加
allow-pvm-bootstrap=true
扩容纯计算节点时只打 cube-node + compute 污点,不要打 cube-control。步骤见 Helm 安装 · 单节点。
PVC / PV 一直 Pending
kubectl get sc
kubectl get pvc -n cube-system
kubectl describe pvc -n cube-system <pvc-name>
kubectl -n cube-system describe pod <pod-name>通用集群(默认不建 SC):
- 没有 default StorageClass → 设
persistence.storageClassName,或改用 hostPath(见安装 · 准备配置) - 指定的 SC / CSI 不存在 → 先装 provisioner
- SC 是
WaitForFirstConsumer,但 Pod 因 selector / taint 调度不上 → 先让 Pod 可调度
TKE + values-tke.yaml: CBS 盘在 Pod 落点后再创建;常见是节点资源不足,或 nodeSelector 与 CBS 可用区不一致。
临时摘掉一台 compute 做维护
先 销毁节点上的沙箱,再:
kubectl drain <node> --ignore-daemonsets --delete-emptydir-data=false
# 维护完成后
kubectl uncordon <node>cube-node 会在节点重新可调度后自动起来并重新注册。
控制面 / 数据库
cube-master 报连不上 MySQL
按顺序查(以下命令假定 Release 名为 cube,命名空间 cube-system;其它 Release 名请把资源名前缀换成 <release>):
- 内置 MySQL 是否 Running:
kubectl -n cube-system get pods -l app.kubernetes.io/component=mysql - Secret 密码是否被误改:
kubectl -n cube-system get secret cube-secret - 容器内连通性:
kubectl -n cube-system exec cube-mysql-0 -- mysql -uroot \
-p"$(kubectl -n cube-system get secret cube-secret -o jsonpath='{.data.mysql-root-password}' | base64 -d)" \
-e 'show databases'外部 MySQL(在 CubeAPI Pod 上探测;环境变量是 CUBE_SANDBOX_MYSQL_*,不是 CUBE_MYSQL_HOST):
kubectl -n cube-system exec -l app.kubernetes.io/component=api -- \
sh -c 'nc -zv "$CUBE_SANDBOX_MYSQL_HOST" "$CUBE_SANDBOX_MYSQL_PORT"'CubeMaster 侧 MySQL 地址写在挂载的 conf.yaml(由 Chart 渲染),不通过上述 env 注入。
升级后表结构没迁完 / migration 卡住
CubeMaster 启动时跑内嵌 goose migration。查日志:
kubectl -n cube-system logs -l app.kubernetes.io/component=master -c cube-master | grep -i migrat也可连库看 goose_db_version。若上次异常退出导致 lock 卡住,需按库内状态手工处理(谨慎操作)。
外部 MySQL 8 caching_sha2_password 认证失败
Chart 已不再强制 mysql_native_password。CubeMaster / CubeAPI 驱动支持 caching_sha2_password。若用户仍是旧插件:
ALTER USER 'cube_user'@'%' IDENTIFIED WITH caching_sha2_password BY '<new-password>';
FLUSH PRIVILEGES;怎么用 cubemastercli?
# 进入交互 shell(镜像内 bashrc 会自动补 --address / --port)
kubectl -n cube-system exec -it -l app.kubernetes.io/component=cubemastercli -- bash
cubemastercli node list
cubemastercli sandbox list也可一行执行(与 Chart NOTES.txt 一致):
kubectl -n cube-system exec deploy/cube-cubemastercli -- \
sh -lc 'cubemastercli --address "$CUBEMASTERCLI_ADDRESS" --port "$CUBEMASTERCLI_PORT" node list'计算面 / PVM / 沙箱
pvm-host-bootstrap 反复重启 / 节点 reboot
跑在 cube-node-pvm(仅 allow-pvm-bootstrap 节点)。多数「反复重启」其实是换核后的正常 reboot。先看日志:
kubectl -n cube-system logs -l app.kubernetes.io/component=cube-node-pvm -c pvm-host-bootstrap --tail=100
kubectl -n cube-system logs -l app.kubernetes.io/component=cube-node-bootstrap -c wait-pvm-host --tail=50
kubectl -n cube-system logs -l app.kubernetes.io/component=cube-node -c wait-node-prep --tail=50正常链路(摘要):ensure pvm-not-ready → 腾空依赖 Pod → invalidate ready 标记 → 换核 / reboot → 写 pvm-host-ready 并清闩 → bootstrap 写 node-prep-ready → Big Pod wait-node-prep init 退出 → 主容器启动。完整说明见架构说明 · PVM。
若卡在 wait-node-prep:先确认 bootstrap Ready,以及 /var/lib/cube-node-bootstrap/node-prep-ready 指纹。若换核后迟迟不重启,多半是节点无 reboot 权限或 GRUB 未更新——登录节点人工 reboot,并检查:
uname -r # 应含 cubesandbox.pvm.host(与 Chart 默认 DESIRED_KERNEL_PATTERN 一致)
cat /proc/cmdline | grep -o pti=offcube-node-init 报 /dev/kvm 不可用
kubectl debug node/<node> -it --image=busybox -- sh
ls -la /dev/kvm
lsmod | grep kvm云主机需安装PVM;物理机需开 VT-x / AMD-V。
cube-node Ready 了,但看不到沙箱 / 节点没注册
kubectl -n cube-system exec -l app.kubernetes.io/component=cubemastercli -- \
sh -lc 'cubemastercli --address "$CUBEMASTERCLI_ADDRESS" --port "$CUBEMASTERCLI_PORT" node list'healthy: true→ 可创建沙箱- 不在列表 → 看注册日志:
kubectl -n cube-system logs -l app.kubernetes.io/component=cube-node -c cubelet --tail=200 | grep -i register常见原因是连不上 CubeMaster(网络 / DNS)。
沙箱启动很慢(>10s),节点却很空
- 排查节点CPU 负载是否较高。
- 查
/data/cubelet是否打满盘或 IOPS:iostat -x 1 - 是否有大量 Paused 沙箱占盘未清理
单节点沙箱数量大概卡在哪?
- 内存:每沙箱约数百 MB~数 GB
- 磁盘:CoW rootfs,看
/data/cubelet容量(默认 loopback 仅 25G,见安装 · 计算节点数据盘) - KVM 数量:单机通常最多数百级,受内核参数影响
Pause 可把非活跃沙箱的 CPU/RSS 压到接近 0(盘不释放)。运营上常:闲置 N 分钟 Pause,更久 Destroy。
/data/cubelet 空间不够 / 想改数据盘大小
默认 bootstrap.nodeInit.dataCubelet.loopback.size 为 25G,bootstrap 首次会创建 /data/cubelet-xfs.img 并挂到 /data/cubelet。
- 尚未装过 / 镜像文件还不存在:在 values 里改
size(如200G)后重装或重跑 bootstrap 即可。 - 镜像已经建好:再改 values 不会自动扩容。生产建议关掉 loopback,改用预挂载的大容量 XFS 盘;若必须重建 loopback,需维护窗口删旧 img(会清空该路径数据)。
配置示例见 Helm 安装 · 计算节点数据盘。
怎么关掉某台节点的 PVM?
去掉该节点的 label:
kubectl label node <node> cube.tencent.com/allow-pvm-bootstrap-然后重启节点所在的服务器。
自检当前 guest:
readlink /usr/local/services/cubetoolbox/cube-kernel-scf/vmlinux
# 或
readlink /var/lib/cube-node-bootstrap/vmlinux-activeCubeProxy / TLS / DNS
sandbox 域名解析不了
- 集群内(含 follow 节点 DNS 的 guest):
nslookup test.cube.app- 无应答 → 看 CoreDNS 是否含
# BEGIN cube-sandbox-dns(后跟 Release 名),或 Job 日志:kubectl -n cube-system logs job/cube-cluster-dns-apply - 应答应是 CubeProxy ClusterIP:
kubectl -n cube-system get svc cube-proxy -o wide
- 无应答 → 看 CoreDNS 是否含
- guest DNS:默认
cubeNode.dns.sandbox.followNodeDns=true;可显式设cubeNode.dns.sandbox.nameservers - 集群外:把
cube.app/*.cube.app指到 Ingress / LB
Ingress / 外部入口不通
排查:
- IngressClass / Ingress 是否存在
- passthrough 注解是否匹配你的 Controller(默认按 nginx-ingress)
- TKE:
values-tke.yaml默认关 Ingress,用 LoadBalancer(CLB);DNS 指 EXTERNAL-IP - 无 Ingress:设
cubeProxy.ingress.enabled=false,自行接到 Service
selfSigned 证书浏览器告警
试用预期行为。生产用:
cubeProxy:
tls:
mode: existingSecret # 或 certManager
existingSecret: my-cube-tls改了 cubeProxy.advertiseIP 好像没生效
cubeProxy.advertiseIP 在 Chart 里只是给人看的提示字段(values.yaml 注释写明 optional hint),不会写入 Proxy / DNS / Service 模板,改它再重启 Proxy 也不会改变集群行为。
真正要改的是:
- 外部 DNS / LB 指向的地址
- 或
cubeProxy.service/ Ingress 相关配置
若只想滚动 Proxy 副本:
kubectl -n cube-system rollout restart deploy/cube-proxyEgress 网络
沙箱上不了外网
- 登录到
cube-nodepod内,检查是否能连通外网。 - 排查沙箱网络策略
出站 MITM 后 TLS 报错
需要信任 Chart 下发的 egress CA:
kubectl -n cube-system get secret cube-egress-ca \
-o jsonpath='{.data.cube-root-ca\.crt}' | base64 -d > cube-ca.crt
# 注入模板 / guest 信任链,例如 /etc/ssl/certs/(Secret 名默认 <release>-egress-ca;证书 key 默认是 cube-root-ca.crt,不是 ca.crt。)
或用 cubeEgress.ca.mode: existingSecret 复用企业 CA。
cube-egress-net CrashLoopBackOff
它依赖主容器创建的 cube-dev:
kubectl -n cube-system logs <cube-node-pod> -c cube-egress-net --tail=100- 日志出现
interface cube-dev not present→ network-agent / cubelet 尚未创建cube-dev,通常会自愈;超过约 5 分钟查这两类容器日志 - 规则反复
rule reapply failed→ iptables 过旧(需 nft)或与 CNI 规则冲突
升级、回滚与卸载
helm upgrade 会不会中断存量沙箱?Pod IP 会变吗?
升 Big Pod 运行时镜像 / 改 Pod template:会。 cube-node 是原生 DaemonSet,变更会 recreate Pod(UID / IP / netns 变化),该节点存量沙箱会中断。只升 Installer / Bootstrap / PVM 且不动 Big Pod template 时,Big Pod 可保持不变。步骤与红线见 升级。
会 recreate Big Pod 的典型操作:bump images.cubelet 等运行时镜像、增删容器、改 volumeMount / securityContext / 容器名 / env。
helm rollback 会回滚 host kernel 吗?
不会。 Helm 只管 K8s 对象。kernel / GRUB / fstab / XFS 等需单独的宿主机回滚 runbook。
helm uninstall 后节点上数据还在
设计如此。卸载只删 Chart 管理的对象。计算节点上常见残留:
sudo rm -rf /data/cubelet /data/cube-shim /data/cube-shared /data/snapshot_pack \
/data/log/Cubelet /data/log/CubeShim /data/log/CubeVmm \
/usr/local/services/cubetoolbox /var/lib/cube-node-bootstrap /tmp/cube \
/data/cubelet-xfs.imgPVM 内核还需卸包、改 GRUB、reboot。也可用 Chart 附带的 deploy/kubernetes/chart/scripts/cleanup-node-host.sh。
PVC/PV 是否删除取决于实际 StorageClass 的 reclaimPolicy(TKE 的 cube-cbs-wffc 常见为 Delete;Retain 则会留下)。
镜像构建
构建 arm64
ONE_CLICK_ARCH=arm64 \
PUSH=1 REGISTRY=<your-registry> IMAGE_TAG=v0.6.0 \
./deploy/kubernetes/images/build-cube-images.sh需要 arm64 机器或 buildx multi-arch。
只想重打某一个镜像
可以。给脚本传镜像名即可(不需要的下载 / SOURCE_REF 导出会按需跳过):
./deploy/kubernetes/images/build-cube-images.sh cubelet
./deploy/kubernetes/images/build-cube-images.sh cubelet cube-shim完整列表见 ./deploy/kubernetes/images/build-cube-images.sh --help,说明见 images/README.md。
若发布包已解压好,可用 PACKAGE_DIR_OVERRIDE 指向该目录,避免重复下载。本地开发还可 LOCAL_BIN=1 / --local 把 _output/bin 叠进镜像。
老 curl 报 --retry-all-errors 未知
当前脚本默认不会加 --retry-all-errors;仅当显式设置 CURL_RETRY_ALL_ERRORS=1 且本机 curl 支持该 flag 时才会启用。一般无需关心;自改的旧 fork 若硬编码了该参数,删掉或升级 curl 即可。
提问模板
Chart 版本:
K8s 版本: (kubectl version)
运行环境: (TKE / 自建 / k3s / 单节点 …)
关键 values 片段: (隐去密码)
失败组件: Pod 名 + kubectl describe + kubectl logs
kubectl -n cube-system get pods -o wide