在 ARM64 + 新内核(6.17) 上踩 Pixie 的坑:从满怀期待到果断放弃

最近想给自建的 Kubernetes 集群上一套 eBPF 可观测性,第一个想到的就是 Pixie——无需埋点就能看到服务调用拓扑、HTTP/gRPC/SQL 流量、火焰图,听起来很美。

但我的集群是 Oracle Cloud 的 2 节点 ARM64(aarch64),内核 6.17。这篇记录在这套环境上装 Pixie 的完整过程(含所有命令)——结论先放前面:

Pixie 能装上、能连云、agent 也能在 ARM 跑,但它真正值钱的 eBPF 探针(尤其 socket_tracer)在内核 6.17 上全部加载失败,实际不可用。 如果你也是 ARM + 较新内核,建议直接看结尾换 Beyla。

0. 环境

1
2
3
4
5
6
7
8
$ kubectl get nodes -o wide
NAME STATUS VERSION OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIME
imwl-us-arm-03 Ready v1.33.1 Ubuntu 24.04.4 LTS 6.17.0-1016-oracle containerd://2.1.1
imwl-us-arm-04 Ready v1.33.1 Ubuntu 24.04.4 LTS 6.17.0-1016-oracle containerd://2.1.1

$ kubectl get nodes -o jsonpath='{range .items[*]}{.status.nodeInfo.architecture}{"\n"}{end}'
arm64
arm64

1. 先做可行性勘察(强烈建议先做这步)

helm install 之前,先确认几个关键点,结果就发现了硬伤。

坑 1:没有 Linux ARM64 的 px CLI

官方安装脚本里硬编码了 amd64:

1
2
$ curl -fsSL https://withpixie.ai/install.sh | grep ARTIFACT_NAME
ARTIFACT_NAME=cli_linux_amd64

release 里也只有 cli_linux_amd64cli_darwin_arm64——没有 cli_linux_arm64。所以 ARM Linux 节点上 px deploy / px run 这套命令行根本跑不了,本机也没装 x86 模拟。

应对:部署不一定要 CLI,可以用官方 Helm chart;查询走 Web UI。

坑 2:自托管 Cloud 的镜像只有 amd64

我本来想走自托管(不依赖第三方云)。自托管的那十几个 cloud-* 控制面镜像,kustomize 里写的是 :latest,但公共 registry 里 :latest 根本不存在;换成真实 tag 实测:

1
2
3
4
5
6
7
$ docker pull --platform linux/arm64 \
gcr.io/pixie-oss/pixie-prod/cloud-api_server_image:0.1.9
WARNING: image platform (linux/amd64) does not match the specified platform (linux/arm64)

$ docker image inspect gcr.io/pixie-oss/pixie-prod/cloud-api_server_image:0.1.9 \
--format '{{.Architecture}}/{{.Os}}'
amd64/linux

控制面镜像全是 amd64,调度到 ARM 节点上只会 exec format error。要硬跑就得整套 QEMU 跨架构模拟,得不偿失。

好消息:真正在节点上跑 eBPF 的 Vizier/PEM agent 镜像是有 arm64 版的

1
2
3
4
5
6
> $ docker pull --platform linux/arm64 \
> gcr.io/pixie-oss/pixie-prod/vizier-pem_image:0.14.15
> $ docker image inspect gcr.io/pixie-oss/pixie-prod/vizier-pem_image:0.14.15 \
> --format '{{.Architecture}}/{{.Os}}'
> arm64/linux
>

也就是说:agent 层能在 ARM 跑,难的是控制面。 而控制面正是社区云方案帮你托管的部分——所以最后改走社区云(getcosmic.ai)。

2. 实装:Helm 部署 Vizier 连社区云

社区云现在是 getcosmic.ai(原 withpixie.ai 已迁移)。先去 https://work.getcosmic.ai 用 Google/GitHub 免费注册一个 org,在 Admin → Deployment Keys 生成一个 px-dep-... 的 deploy key。

1
2
3
4
5
6
7
8
9
10
11
# 加 helm 仓库
helm repo add pixie-operator https://pixie-operator-charts.storage.googleapis.com
helm repo update

# 部署(cloudAddr 注意用 getcosmic.ai:443;给 PEM 设个内存上限免得它吃太多)
helm install pixie pixie-operator/pixie-operator-chart \
--namespace pl --create-namespace \
--set deployKey=<你的 deploy key> \
--set clusterName=my-arm-cluster \
--set cloudAddr=getcosmic.ai:443 \
--set pemMemoryLimit=1Gi --set pemMemoryRequest=600Mi

这个 operator chart 通过 OLM 部署,要等几分钟(OLM → operator → Vizier 组件)。盯着起来:

1
2
3
4
5
6
7
8
9
10
11
12
$ kubectl get pods -n pl
NAME READY STATUS RESTARTS AGE
kelvin-7b6fdbfb9f-wzm7f 1/1 Running 0 10m
pl-etcd-0 1/1 Running 0 10m
pl-etcd-1 1/1 Running 0 10m
pl-etcd-2 1/1 Running 0 10m
pl-nats-0 1/1 Running 0 10m
vizier-cloud-connector-df45849cc-tps5q 1/1 Running 0 10m
vizier-metadata-5f47d4fcfb-tm5vb 1/1 Running 0 10m
vizier-pem-62ncv 1/1 Running 0 10m
vizier-pem-brrb8 1/1 Running 0 10m
vizier-query-broker-765664495f-x87xl 1/1 Running 0 10m

10 个 pod 全 Running、0 重启,两个节点各一个 vizier-pem,cloud-connector 也连上了云。到这一步,看起来一切正常。

2.1 进阶:自定义命名空间

上面用的是默认的三个 ns(pl / px-operator / olm),它们都能自定义,但分两类:

  • olmpx-operator:chart 提供了参数 olmNamespaceolmOperatorNamespace

    ⚠️ 如果集群里已经装过 OLM,这两个要填成你现有 OLM 所在的 ns,否则会和已有的 OLM 冲突。

  • pl(Vizier 所在 ns):就是 helm install --namespace <你的名字> --create-namespace 的那个,想叫啥叫啥。

例如全部自定义:

1
2
3
4
5
6
helm install pixie pixie-operator/pixie-operator-chart \
--namespace my-pixie --create-namespace \
--set olmNamespace=my-olm \
--set olmOperatorNamespace=my-px-operator \
--set deployKey=<你的 deploy key> \
--set cloudAddr=getcosmic.ai:443

部署后对应去 my-pixie / my-olm / my-px-operator 这几个 ns 看 pod 即可。

2.2 国内集群怎么拉 gcr.io 镜像

Pixie 镜像全在 gcr.io/pixie-oss/...,国内直连基本拉不动,而 chart 没有 registry 覆盖参数。两条路:

方案 A(推荐):containerd 配 gcr.io 镜像加速——节点级改配置,不动任何 yaml。每个节点写 /etc/containerd/certs.d/gcr.io/hosts.toml

1
2
3
server = "https://gcr.io"
[host."https://gcr.m.daocloud.io"] # 或其它可用的 gcr 镜像站 / 公司内网代理
capabilities = ["pull", "resolve"]

然后 systemctl restart containerd。这样集群拉 gcr.io/... 自动走镜像站,Pixie chart 一字不改。

方案 B:镜像搬运到国内 registry——用 skopeo/docker 把镜像 copy 到你的 ACR/Harbor,再在节点配 mirror 指向它。需要的镜像:operator 层 2 个(operator-vizier_deleteroperator/bundle_index)+ Vizier 运行期约 12 个(vizier-pem_image / vizier-query_broker_server_image / vizier-metadata_server_image / kelvin_image / vizier-cloud_connector_server_image / cert_provisioner 等,都在 gcr.io/pixie-oss/pixie-prod/,tag 用 0.14.15)+ etcd/nats 几个依赖镜像。A 比 B 省事,除非要完全离线。

注:本文的 ARM 集群正是卡在镜像之外的内核兼容性问题;但如果你是国内的 amd64 集群,内核兼容性通常没 ARM 那些坑,把镜像拉取解决掉,Pixie 是能正常跑起来的。

3. 真正的坑:内核 6.17 上 eBPF 探针全挂

但 “pod Running” 不等于 “eBPF 探针加载成功”。翻 PEM 日志才看到真相:

1
$ kubectl logs -n pl vizier-pem-62ncv | grep -iE "source connector|Failed to load|BCC"
1
2
3
4
5
6
7
8
9
10
11
Creating Stirling, registered sources:
[process_stats, network_stats, jvm_stats, socket_tracer, perf_profiler, proc_exit_tracer, ...]

Kernel version greater than V5.1 detected (6.17.13) ...
W Source Connector (registry name=socket_tracer) not instantiated,
error: Unable to initialize BCC BPF program
bpf: Failed to load program: Invalid argument
W Source Connector (registry name=perf_profiler) not instantiated,
error: Failed to load sample_call_stack: -22
W Source Connector (registry name=proc_exit_tracer) not instantiated,
error: Failed to load tracepoint__sched__sched_process_exit: -22

逐个看:

探针 作用 在内核 6.17 ARM 上
process_stats / network_stats / jvm_stats 基础进程/网络/JVM 计数 ✅ 正常
socket_tracer HTTP/gRPC/SQL 协议追踪、服务拓扑(Pixie 招牌功能) 加载失败
perf_profiler CPU 火焰图 ❌ 加载失败
proc_exit_tracer 进程退出追踪 ❌ 加载失败

最致命的是 socket_tracer 挂了——它就是 Pixie “无埋点看服务调用” 的核心。它一挂,Pixie 就只剩进程/网络计数,招牌功能全没了

根因:Pixie 自带的 BCC/BPF 程序对 6.10+ 内核 + ARM 的兼容性还没跟上(社区 issue #2318 在追,但尚未修复)。-22 (EINVAL) 是内核 verifier 拒绝了这些 BPF 程序。

4. 卸载:清干净(OLM 残留要手动删)

确认不可用后果断卸载。注意 helm uninstall 不会自动清掉 namespace、CRD 和 cluster 级 RBAC,要手动删:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 1. helm 卸载(移除 pod)
helm uninstall pixie -n pl

# 2. 删命名空间
kubectl delete namespace pl px-operator olm

# 3. 删 CRD(Pixie 的 + OLM 的)
kubectl delete crd viziers.px.dev
for crd in $(kubectl get crd -o name | grep operators.coreos.com); do
kubectl delete "$crd"
done

# 4. 删残留的 cluster 级 RBAC
for r in $(kubectl get clusterrole,clusterrolebinding -o name \
| grep -iE "/pl-|/olm\.|olm-operator|catalog"); do
kubectl delete "$r"
done

# 5. 移除 helm 仓库
helm repo remove pixie-operator

验证清干净:

1
2
$ kubectl get pods -A | grep -iE "pixie|vizier|pl-|olm" || echo "✅ 无残留"
✅ 无残留

顺带:如果用过社区云的 deploy key,集群卸载后记得去 getcosmic 把那个 key 撤销掉。

5. 那 ARM + 新内核 想要 eBPF 可观测怎么办?

答案是 Beyla(Grafana 出的 eBPF 自动埋点):

  • 对新内核 + ARM 的兼容性好得多;
  • 原生对接 Grafana / Tempo / Prometheus 技术栈;
  • 同样无需改代码,能拿到服务的 RED 指标 + 分布式追踪。

也就是说,你想从 Pixie 体验的那种”无埋点追踪”,Beyla 在 ARM + 新内核上才是真能跑起来的那个。

一句话总结

Pixie 的设计很优雅,但它的 BPF 程序对前沿内核(尤其 ARM)的适配明显落后。选型 eBPF 工具时,第一件事是确认它的探针支持你的内核版本和 CPU 架构——docker pull --platform 验镜像架构、跑起来后第一时间翻 agent 日志看探针加载状态,比界面好不好看重要得多。