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-cidr=10.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-driver=systemd参数更彻底。 - 可溯(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 LTS(Noble Numbat)是首个默认启用cgroup v2的长期支持版本,这对K8s编译构成两重暴击:
- cgroup v2的ABI断裂:旧版
runc(<1.1.0)和containerd(<1.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_ENABLED=1,而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.21,Ubuntu 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_LINUX="systemd.unified_cgroup_hierarchy=0" # 更新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_STATE="clean"这一行,将其改为KUBE_GIT_TREE_STATE="dirty"。这样编译出的二进制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::status'; quick-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-m1 | 192.168.1.101 | Master | kube-apiserver, etcd, kube-controller-manager |
| k8s-m2 | 192.168.1.102 | Master | kube-apiserver, etcd, kube-scheduler |
| k8s-m3 | 192.168.1.103 | Master | kube-apiserver, etcd |
| k8s-w1 | 192.168.1.201 | Worker | kubelet, kube-proxy |
| k8s-w2 | 192.168.1.202 | Worker | kubelet, kube-proxy |
在每台机器上执行前置检查:
# 关闭swap(K8s禁止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] Description=etcd After=network.target [Service] Type=notify User=$(whoami) ExecStart=/usr/local/bin/etcd --config-file=/etc/etcd/config.yml Restart=on-failure RestartSec=10 LimitNOFILE=65536 [Install] WantedBy=multi-user.target EOF sudo systemctl daemon-reload sudo systemctl enable etcd sudo systemctl start etcd # 验证集群健康 ETCDCTL_API=3 /usr/local/bin/etcdctl \ --endpoints=https://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,RBAC | Ubuntu 24.04的systemd默认禁用CAP_SYS_ADMIN,需在/etc/systemd/system/kube-apiserver.service中加CapabilityBoundingSet=CAP_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,PodSecurityPolicy(v1.28已弃用,改用PodSecurity) |
在k8s-m1上创建/etc/kubernetes/manifests/kube-apiserver.yaml:
apiVersion: v1 kind: Pod metadata: name: kube-apiserver namespace: kube-system spec: containers: - command: - kube-apiserver - --advertise-address=192.168.1.101 - --allow-privileged=true - --authorization-mode=Node,RBAC - --client-ca-file=/etc/kubernetes/pki/ca.crt - --enable-admission-plugins=NodeRestriction,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-servers=https://127.0.0.1:2379 - --insecure-port=0 - --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-names=front-proxy-client - --requestheader-client-ca-file=/etc/kubernetes/pki/front-proxy-ca.crt - --requestheader-extra-headers-prefix=X-Remote-Extra- - --requestheader-group-headers=X-Remote-Group - --requestheader-username-headers=X-Remote-User - --secure-port=6443 - --service-account-issuer=https://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-range=10.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配置文件切换)。
在所有节点(master+worker)上:
# 创建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] Description=Kubernetes Kubelet Documentation=https://kubernetes.io/docs/ After=containerd.service Wants=containerd.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-certificates=true \\ --rotate-server-certificates=true \\ --exit-on-lock-contention=true \\ --lock-file=/var/run/lock/kubelet.lock \\ --network-plugin=cni \\ --cni-conf-dir=/etc/cni/net.d \\ --cni-bin-dir=/opt/cni/bin \\ --container-runtime=remote \\ --container-runtime-endpoint=unix:///run/containerd/containerd.sock \\ --image-pull-progress-deadline=2m \\ --v=2 Restart=always RestartSec=10 KillMode=process LimitNOFILE=65536 LimitNPROC=65536 LimitCORE=infinity Environment="KUBELET_KUBECONFIG_ARGS=--bootstrap-kubeconfig=/etc/kubernetes/bootstrap-kubelet.conf --kubeconfig=/etc/kubernetes/kubelet.conf" Environment="KUBELET_CONFIG_ARGS=--config=/var/lib/kubelet/config.yaml" Environment="KUBELET_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.1,v3.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" #