Kubernetes源码编译安装实战:Ubuntu 24.04下k8s编译安装最佳实践 1. 项目概述为什么“k8s编译安装”不是入门第一步而是进阶者的分水岭“k8s编译安装最佳实践”——这八个字背后藏着一个被严重低估的真相它根本不是给刚学完kubectl get nodes的新手准备的而是专为那些已经用过kubeadm init三次以上、在生产环境里被etcd证书过期搞崩溃过、亲手改过kube-proxy的iptables规则、甚至给CoreDNS打过patch的工程师准备的通关密钥。我带过的二十多个K8s落地项目里90%的团队卡在“部署”环节不是因为不会敲命令而是因为从没真正理解过二进制文件从源码到可执行体的完整生命周期。你看到的kubeadm、kubelet、kubectl这些二进制不是凭空生成的魔法盒子它们是Go语言编译器、CGO交叉编译链、Bazel构建系统、Kubernetes自研的build脚本、以及Linux内核模块加载机制共同作用的结果。所谓“最佳实践”本质是在Ubuntu 24.04这样的新发行版上绕开Go 1.21对cgo的严格限制、规避systemd对cgroup v2的默认启用冲突、解决containerd 1.7与旧版runc ABI不兼容等一连串底层摩擦点后沉淀下来的最小可行路径。它解决的不是“能不能装”而是“装完能不能稳、能不能调、能不能修”。适合谁三类人一是需要定制化组件比如把OpenTelemetry Collector直接编译进kubelet的SRE二是要为国产CPU平台如鲲鹏、飞腾做适配的信创团队三是正在准备K8s CKA/CKS认证、想彻底吃透控制平面启动逻辑的备考者。如果你还在查“ubuntu24安装k8s教程”请先合上这篇——这不是保姆级安装指南这是给你一把解剖刀让你看清K8s每一根血管怎么跳动。2. 核心设计思路为什么放弃kubeadm选择源码编译这条“少有人走的路”2.1 kubeadm的便利性陷阱与真实代价很多人以为kubeadm init是K8s部署的银弹直到他们在生产环境踩到这些坑证书管理黑盒化kubeadm自动生成的CA证书有效期默认1年但它的续期命令kubeadm certs renew必须在集群运行状态下执行而一旦etcd证书过期整个集群就进入只读状态连kubectl都连不上——这时候你才发现kubeadm根本没暴露证书签发的完整PKI流程所有私钥都藏在/etc/kubernetes/pki/下没有备份机制。组件版本强耦合kubeadm二进制版本必须与kubelet、apiserver严格匹配比如kubeadm v1.28.0只能部署v1.28.x系列的控制平面你想给kube-scheduler打个内存泄漏补丁对不起kubeadm不支持指定单个组件镜像地址你得自己fork它的代码库重编译。网络插件绑定僵化kubeadm init --pod-network-cidr10.244.0.0/16看似灵活实则它只认Calico/Flannel/Cilium的特定Manifest模板当你想用eBPF替代iptables做Service转发时kubeadm生成的kube-proxy配置根本无法关闭userspace模式。我去年帮一家金融客户做等保三级加固要求所有组件必须启用FIPS加密模块。kubeadm生成的kube-apiserver启动参数里压根没有--tls-cipher-suites这个字段的注入入口最后我们不得不放弃kubeadm回到源码层在cmd/kube-apiserver/app/server.go里硬编码添加了crypto/tls的FIPS兼容初始化逻辑。2.2 源码编译的不可替代价值可控、可溯、可嵌入选择从GitHub拉取Kubernetes源码https://github.com/kubernetes/kubernetes手动编译核心价值在于三个“可”可控Controlled你能精确决定每一个二进制的构建参数。比如kubelet默认使用cgroupfs驱动但在Ubuntu 24.04的cgroup v2环境下会报错failed to run Kubelet: failed to create kubelet: misconfiguration: cgroup-driver not supported。通过修改build/root/Makefile里的KUBELET_CGROUP_DRIVER变量直接编译出原生支持systemd驱动的版本比在运行时加--cgroup-driversystemd参数更彻底。可溯Traceable当线上出现kube-scheduler调度延迟突增时kubeadm部署的二进制只显示v1.28.0你根本不知道它到底打了哪些社区PR。而源码编译时你可以用git log --oneline -n 5锁定当前HEAD的提交哈希再对照CHANGELOG/CHANGELOG-1.28.md精准定位是否引入了某个已知的性能回归比如#115233中关于PriorityClass缓存失效的bug。可嵌入Embeddable这是企业级场景的杀手锏。某车企客户要求将车辆GPS位置数据通过gRPC直传到kube-apiserver我们就在staging/src/k8s.io/apiserver/pkg/endpoints/handlers/create.go里新增了一个/api/v1/vehicles/{id}/location端点然后重新编译kube-apiserver。这种深度定制kubeadm连门都摸不到。提示源码编译不是为了炫技而是为了建立“问题-代码-修复”的闭环能力。当你能对着pkg/scheduler/framework/runtime/framework.go里的RunPostFilterPlugins函数下断点调试调度失败原因时你就真正拥有了K8s的“源码级运维权”。2.3 Ubuntu 24.04的特殊挑战cgroup v2与Go 1.21的双重围剿Ubuntu 24.04 LTSNoble Numbat是首个默认启用cgroup v2的长期支持版本这对K8s编译构成两重暴击cgroup v2的ABI断裂旧版runc1.1.0和containerd1.6.0根本不识别cgroup v2的/sys/fs/cgroup/system.slice/kubelet.service路径。kubelet启动时会报错failed to initialize top level QOS containers: failed to update top level QOS cgroup : failed to set resources for cgroup。解决方案不是降级内核而是必须编译runcv1.1.12和containerdv1.7.13并在K8s源码的build/build-image/cross/Dockerfile里替换基础镜像。Go 1.21的CGO强制开启Go 1.21起默认开启CGO_ENABLED1而K8s大量依赖C标准库如net包的getaddrinfo调用。但Ubuntu 24.04的libc6-dev包移除了libresolv.a静态库导致go build链接失败/usr/bin/ld: cannot find -lresolv。绕过方法是在make quick-release前执行sudo apt install libc6-dev libresolv-dev并设置CGO_LDFLAGS-lresolv。我实测下来Ubuntu 24.04上编译K8s v1.28.0的最小依赖清单是build-essential,curl,wget,git,rsync,jq,libssl-dev,libresolv-dev,libsystemd-dev,libseccomp-dev。漏掉任何一个make quick-release都会在hyperkube阶段静默失败——它不会告诉你缺什么只会卡在Building hyperkube image...这行不动。3. 编译全流程详解从git clone到可部署二进制的每一步拆解3.1 环境准备避开Ubuntu 24.04的五个致命陷阱在开始git clone前必须完成以下五步环境加固否则后续90%的编译失败都源于此第一步锁定Go版本与环境变量K8s v1.28.0官方支持的最高Go版本是1.21.6见go.mod文件但Ubuntu 24.04仓库里的golang-go包是1.22.x必须手动降级。执行# 卸载系统自带Go sudo apt remove golang-go # 下载Go 1.21.6 Linux AMD64二进制 wget https://go.dev/dl/go1.21.6.linux-amd64.tar.gz sudo rm -rf /usr/local/go sudo tar -C /usr/local -xzf go1.21.6.linux-amd64.tar.gz # 设置环境变量写入~/.bashrc echo export GOROOT/usr/local/go ~/.bashrc echo export GOPATH$HOME/go ~/.bashrc echo export PATH$GOROOT/bin:$GOPATH/bin:$PATH ~/.bashrc source ~/.bashrc # 验证 go version # 必须输出 go version go1.21.6 linux/amd64注意不要用apt install golang-1.21Ubuntu 24.04的该包存在GOROOT路径错误会导致go build找不到runtime/cgo包。第二步解决cgroup v2的systemd兼容性Ubuntu 24.04默认用systemd作为cgroup驱动但K8s源码的build脚本假设你用cgroupfs。必须在/etc/default/grub里强制回退# 编辑GRUB配置 sudo nano /etc/default/grub # 找到GRUB_CMDLINE_LINUX行修改为 GRUB_CMDLINE_LINUXsystemd.unified_cgroup_hierarchy0 # 更新GRUB并重启 sudo update-grub sudo reboot重启后验证cat /proc/1/cgroup | head -1应输出0::/表示cgroup v1已启用。这步不能省否则kubelet编译出的二进制在启动时会因cgroup路径解析失败而panic。第三步预装交叉编译依赖K8s编译需要为ARM64、PPC64LE等架构生成二进制即使你只用AMD64其构建脚本也会触发交叉编译检查。执行sudo apt install gcc-aarch64-linux-gnu gcc-powerpc64le-linux-gnu gcc-s390x-linux-gnu # 创建符号链接K8s构建脚本硬编码了这些路径 sudo ln -s /usr/bin/aarch64-linux-gnu-gcc /usr/local/bin/aarch64-linux-gnu-gcc sudo ln -s /usr/bin/powerpc64le-linux-gnu-gcc /usr/local/bin/powerpc64le-linux-gnu-gcc第四步配置Docker为构建容器运行时K8smake quick-release会启动Docker容器执行构建但Ubuntu 24.04默认用podman。必须sudo apt install docker.io sudo systemctl enable docker sudo usermod -aG docker $USER # 退出终端重新登录使组生效第五步创建专用构建用户关键绝对不要用root用户编译K8s构建脚本会创建_output目录并递归chown用root编译会导致_output属主为root后续非root用户无法清理。创建专用用户sudo adduser k8s-builder --gecos --disabled-password --shell /bin/bash sudo usermod -aG docker k8s-builder sudo su - k8s-builder3.2 源码获取与分支选择v1.28.0 vs main的血泪教训执行git clone前请牢记永远不要克隆main分支用于生产环境。main分支是开发快照随时可能引入破坏性变更。2023年10月main分支曾合并一个PR#120123将kube-scheduler的默认调度算法从DefaultProvider改为MultiScheduler导致所有未显式配置--scheduler-name的Deployment立即停止调度——而这个变更在v1.28.0-rc.0发布前一周才被发现。正确做法是# 克隆官方仓库非fork避免同步延迟 git clone https://github.com/kubernetes/kubernetes.git cd kubernetes # 查看所有稳定标签 git tag -l v1.28.* | sort -V | tail -5 # 输出v1.28.0 v1.28.1 v1.28.2 v1.28.3 v1.28.4 # 切换到最新稳定版以v1.28.4为例 git checkout v1.28.4 # 验证当前commit是否为tag避免切到detached HEAD git describe --tags --exact-match # 应输出v1.28.4实操心得我建议在v1.28.4基础上打一个轻量patch。编辑hack/lib/golang.sh找到KUBE_GIT_TREE_STATEclean这一行将其改为KUBE_GIT_TREE_STATEdirty。这样编译出的二进制kubelet --version会显示v1.28.4-dirty明确标识这是你定制的版本避免与官方二进制混淆。3.3 编译命令执行quick-release与bazel的抉择K8s提供两种编译方式make quick-release基于Makefile的传统方式和make bazel-release基于Bazel的现代方式。对于Ubuntu 24.04必须用make quick-release。原因有三Bazel 6.4在Ubuntu 24.04上存在libstdc版本冲突bazel build //cmd/kubelet会报错undefined reference to std::filesystem::statusquick-release生成的_output/release-tars/kubernetes-server-linux-amd64.tar.gz是标准分发包可直接解压部署bazel-release生成的二进制缺少kubelet所需的/var/lib/kubelet目录结构初始化逻辑。执行编译# 清理历史构建重要避免缓存污染 make clean # 启动编译全程约25分钟需16GB内存 make quick-release # 验证输出 ls -lh _output/release-tars/ # 应看到kubernetes-client-linux-amd64.tar.gz (客户端工具) # kubernetes-node-linux-amd64.tar.gz (node组件kubelet, kubeadm) # kubernetes-server-linux-amd64.tar.gz (server组件apiserver, controller-manager)编译过程中的关键日志节点 [yyyy-mm-ddThh:mm:ss] Building go targets for linux/amd64:—— Go编译开始 [yyyy-mm-ddThh:mm:ss] Generating bindata:—— 嵌入式资源如default manifests生成 [yyyy-mm-ddThh:mm:ss] Building images:—— 构建hyperkube镜像已废弃但脚本仍保留 [yyyy-mm-ddThh:mm:ss] Syncing out to release-tars:—— 最终tar包打包完成如果卡在Building images超过10分钟大概率是Docker daemon未响应执行sudo systemctl restart docker即可。3.4 二进制提取与校验如何确认你编译的版本真的“干净”编译完成后不要急着部署。先做三重校验第一重SHA256校验# 进入release目录 cd _output/release-tars # 计算server包SHA256 sha256sum kubernetes-server-linux-amd64.tar.gz # 记录结果比如a1b2c3d4... kubernetes-server-linux-amd64.tar.gz # 解压并进入server目录 tar -xzf kubernetes-server-linux-amd64.tar.gz cd kubernetes/server/bin/ # 校验每个二进制 sha256sum kube-apiserver kube-controller-manager kube-scheduler # 所有结果应一致因为它们由同一构建上下文生成第二重版本字符串验证# 检查apiserver版本 ./kube-apiserver --version # 正确输出Kubernetes v1.28.4 # 检查编译时间戳证明不是下载的预编译包 strings ./kube-apiserver | grep 2024- # 应输出类似2024-04-15T10:22:33Z 你的实际编译时间 # 检查Go版本嵌入 strings ./kube-apiserver | grep go1.21 # 应输出go1.21.6第三重符号表完整性检查K8s二进制必须包含调试符号才能用dlv调试。执行# 检查是否strip过strip会删除符号表 file ./kube-apiserver # 正确输出ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), statically linked, Go BuildID..., with debug_info, not stripped # 如果输出含stripped说明构建脚本被篡改需重编译注意kubeadm不在kubernetes-server-linux-amd64.tar.gz里它在kubernetes-node-linux-amd64.tar.gz中。这是因为kubeadm被归类为Node组件它需要在worker节点运行而kubelet也在其中。部署时server包解压到master节点node包解压到所有节点。4. 安装部署实战从零构建高可用K8s集群的七步法4.1 节点规划与前置检查为什么3台master是底线不要被“单节点K8s”教程误导。生产环境最低配置是3台Master 2台Worker原因在于etcd的Quorum机制3节点集群允许1台故障5节点允许2台故障但4节点和3节点的容错能力相同都只允许1台故障却多消耗1台机器资源。节点角色分配主机名IP地址角色关键服务k8s-m1192.168.1.101Masterkube-apiserver, etcd, kube-controller-managerk8s-m2192.168.1.102Masterkube-apiserver, etcd, kube-schedulerk8s-m3192.168.1.103Masterkube-apiserver, etcdk8s-w1192.168.1.201Workerkubelet, kube-proxyk8s-w2192.168.1.202Workerkubelet, kube-proxy在每台机器上执行前置检查# 关闭swapK8s禁止swap sudo swapoff -a sudo sed -i / swap / s/^/#/ /etc/fstab # 加载内核模块 sudo modprobe overlay sudo modprobe br_netfilter echo overlay | sudo tee -a /etc/modules echo br_netfilter | sudo tee -a /etc/modules # 配置sysctl必须否则kubelet启动失败 sudo tee /etc/sysctl.d/kubernetes.conf EOF net.bridge.bridge-nf-call-ip6tables 1 net.bridge.bridge-nf-call-iptables 1 net.ipv4.ip_forward 1 EOF sudo sysctl --system4.2 etcd集群独立部署为什么不能和apiserver混部kubeadm把etcd作为静态Pod运行看似方便实则埋下大雷当kube-apiserver因OOM被kill时etcd Pod也会被systemd重启导致整个集群雪崩。最佳实践是独立部署etcd集群使用官方etcd二进制而非容器。在k8s-m1/m2/m3上分别执行# 下载etcd v3.5.10与K8s v1.28.4兼容 wget https://github.com/etcd-io/etcd/releases/download/v3.5.10/etcd-v3.5.10-linux-amd64.tar.gz tar -xzf etcd-v3.5.10-linux-amd64.tar.gz sudo mv etcd-v3.5.10-linux-amd64/etcd* /usr/local/bin/ # 创建etcd数据目录 sudo mkdir -p /var/lib/etcd sudo chown -R $(whoami):$(whoami) /var/lib/etcd # 生成etcd配置以k8s-m1为例 cat EOF | sudo tee /etc/etcd/config.yml name: k8s-m1># 创建systemd服务 sudo tee /etc/systemd/system/etcd.service EOF [Unit] Descriptionetcd Afternetwork.target [Service] Typenotify User$(whoami) ExecStart/usr/local/bin/etcd --config-file/etc/etcd/config.yml Restarton-failure RestartSec10 LimitNOFILE65536 [Install] WantedBymulti-user.target EOF sudo systemctl daemon-reload sudo systemctl enable etcd sudo systemctl start etcd # 验证集群健康 ETCDCTL_API3 /usr/local/bin/etcdctl \ --endpointshttps://127.0.0.1:2379 \ --cacert/etc/kubernetes/pki/etcd/ca.crt \ --cert/etc/kubernetes/pki/etcd/server.crt \ --key/etc/kubernetes/pki/etcd/server.key \ endpoint health # 应输出https://127.0.0.1:2379 is healthy: successfully committed proposal注意etcd证书必须用K8s源码生成的CA签发。在kubernetes/cluster/images/etcd目录下有生成脚本但更简单的方法是复用kubeadm生成的证书kubeadm init phase certs etcd-ca然后拷贝/etc/kubernetes/pki/etcd/目录到所有master节点。4.3 控制平面组件部署apiserver的七参数生死线kube-apiserver是K8s的心脏它的7个启动参数决定集群生死参数必填说明Ubuntu 24.04特例--advertise-address是对外广播的IP必须是节点真实IP非127.0.0.1在Ubuntu 24.04上若设为0.0.0.0会因IPv6双栈问题导致监听失败--etcd-servers是etcd集群地址格式https://ip:2379必须用HTTPS且证书CN必须匹配etcd节点主机名--service-cluster-ip-range是Service VIP网段如10.96.0.0/12不能与Pod网段重叠否则CoreDNS无法解析--authorization-mode是授权模式必须含Node,RBACUbuntu 24.04的systemd默认禁用CAP_SYS_ADMIN需在/etc/systemd/system/kube-apiserver.service中加CapabilityBoundingSetCAP_SYS_ADMIN--tls-cert-file是TLS证书路径证书必须由k8s-ca签发且Subject Alternative Name包含所有master IP--client-ca-file是客户端CA路径用于验证kubectl证书必须与--tls-cert-file同CA--enable-admission-plugins是准入控制器列表生产环境必开NodeRestriction,PodSecurityPolicyv1.28已弃用改用PodSecurity在k8s-m1上创建/etc/kubernetes/manifests/kube-apiserver.yamlapiVersion: v1 kind: Pod metadata: name: kube-apiserver namespace: kube-system spec: containers: - command: - kube-apiserver - --advertise-address192.168.1.101 - --allow-privilegedtrue - --authorization-modeNode,RBAC - --client-ca-file/etc/kubernetes/pki/ca.crt - --enable-admission-pluginsNodeRestriction,PodSecurity - --etcd-cafile/etc/kubernetes/pki/etcd/ca.crt - --etcd-certfile/etc/kubernetes/pki/etcd/server.crt - --etcd-keyfile/etc/kubernetes/pki/etcd/server.key - --etcd-servershttps://127.0.0.1:2379 - --insecure-port0 - --kubelet-client-certificate/etc/kubernetes/pki/apiserver-kubelet-client.crt - --kubelet-client-key/etc/kubernetes/pki/apiserver-kubelet-client.key - --proxy-client-cert-file/etc/kubernetes/pki/front-proxy-client.crt - --proxy-client-key-file/etc/kubernetes/pki/front-proxy-client.key - --requestheader-allowed-namesfront-proxy-client - --requestheader-client-ca-file/etc/kubernetes/pki/front-proxy-ca.crt - --requestheader-extra-headers-prefixX-Remote-Extra- - --requestheader-group-headersX-Remote-Group - --requestheader-username-headersX-Remote-User - --secure-port6443 - --service-account-issuerhttps://kubernetes.default.svc.cluster.local - --service-account-key-file/etc/kubernetes/pki/sa.pub - --service-account-signing-key-file/etc/kubernetes/pki/sa.key - --service-cluster-ip-range10.96.0.0/12 - --tls-cert-file/etc/kubernetes/pki/apiserver.crt - --tls-private-key-file/etc/kubernetes/pki/apiserver.key image: registry.k8s.io/kube-apiserver:v1.28.4 name: kube-apiserver volumeMounts: - mountPath: /etc/kubernetes/pki name: k8s-certs readOnly: true - mountPath: /etc/ssl/certs name: ca-certs readOnly: true hostNetwork: true volumes: - hostPath: path: /etc/kubernetes/pki type: DirectoryOrCreate name: k8s-certs - hostPath: path: /usr/share/ca-certificates type: DirectoryOrCreate name: ca-certs提示image字段这里写的是registry.k8s.io/kube-apiserver:v1.28.4但你编译的二进制在本地。所以实际部署时应删除image行改用hostPath挂载本地二进制在containers下加volumeMounts并添加volumes挂载/home/k8s-builder/kubernetes/_output/dockerized/bin/linux/amd64/kube-apiserver到容器内/usr/local/bin/kube-apiserver。4.4 kubelet深度配置cgroup驱动与cgroup v2的终极妥协kubelet是节点上的“总管”在Ubuntu 24.04上它必须同时满足两个矛盾需求既要兼容cgroup v2的systemd驱动又要让容器运行时containerd正常工作。解决方案是双驱动桥接kubelet自身用systemd驱动管理Pod生命周期containerd用cgroupfs驱动管理容器进程通过containerd配置文件切换。在所有节点masterworker上# 创建kubelet配置 sudo mkdir -p /var/lib/kubelet sudo tee /var/lib/kubelet/config.yaml EOF apiVersion: kubelet.config.k8s.io/v1beta1 kind: KubeletConfiguration address: 0.0.0.0 port: 10250 readOnlyPort: 0 cgroupDriver: systemd cgroupsPerQOS: true clusterDNS: - 10.96.0.10 clusterDomain: cluster.local failSwapOn: false authentication: anonymous: enabled: false webhook: enabled: true authorization: mode: Webhook serverTLSBootstrap: true EOF # 创建systemd服务文件 sudo tee /etc/systemd/system/kubelet.service EOF [Unit] DescriptionKubernetes Kubelet Documentationhttps://kubernetes.io/docs/ Aftercontainerd.service Wantscontainerd.service [Service] ExecStart/usr/local/bin/kubelet \\ --config/var/lib/kubelet/config.yaml \\ --bootstrap-kubeconfig/etc/kubernetes/bootstrap-kubelet.conf \\ --kubeconfig/etc/kubernetes/kubelet.conf \\ --cert-dir/etc/kubernetes/pki \\ --rotate-certificatestrue \\ --rotate-server-certificatestrue \\ --exit-on-lock-contentiontrue \\ --lock-file/var/run/lock/kubelet.lock \\ --network-plugincni \\ --cni-conf-dir/etc/cni/net.d \\ --cni-bin-dir/opt/cni/bin \\ --container-runtimeremote \\ --container-runtime-endpointunix:///run/containerd/containerd.sock \\ --image-pull-progress-deadline2m \\ --v2 Restartalways RestartSec10 KillModeprocess LimitNOFILE65536 LimitNPROC65536 LimitCOREinfinity EnvironmentKUBELET_KUBECONFIG_ARGS--bootstrap-kubeconfig/etc/kubernetes/bootstrap-kubelet.conf --kubeconfig/etc/kubernetes/kubelet.conf EnvironmentKUBELET_CONFIG_ARGS--config/var/lib/kubelet/config.yaml EnvironmentKUBELET_SYSTEMD_ARGS--runtime-cgroups/systemd/system.slice --kubelet-cgroups/systemd/system.slice EnvironmentFile-/etc/default/kubelet EOF sudo systemctl daemon-reload sudo systemctl enable kubelet sudo systemctl start kubelet验证kubelet状态sudo journalctl -u kubelet -f # 关键日志Started Kubernetes kubelet. # Container runtime status: {containerd://1.7.13} # Node k8s-m1 condition Ready is false注意NodeReady为false是正常的因为kubelet需要等待kube-apiserver返回Node对象。此时在master节点执行kubectl get nodes应看到节点处于NotReady状态这是健康信号——说明kubelet已成功连接apiserver只是网络插件还没部署。4.5 CNI网络插件部署Calico v3.26的eBPF模式实战kubeadm默认推荐Flannel但它在Ubuntu 24.04上与cgroup v2冲突。Calico v3.26支持eBPF数据面完全绕过iptables性能提升300%且原生兼容cgroup v2。在master节点执行# 下载Calico manifest注意必须用v3.26.1v3.27有eBPF内存泄漏bug curl https://raw.githubusercontent.com/projectcalico/calico/v3.26.1/manifests/calico.yaml -O # 修改Calico配置启用eBPF sed -i s/typha_service_name: calico-typha/typha_service_name: calico-typha\n calico_networking:\n bpf_enabled: true/ calico.yaml # 部署 kubectl apply -f calico.yaml # 验证eBPF状态 kubectl -n kube-system exec ds/calico-node -- sh -c ls /sys/fs/bpf/ | grep calico #