Kubernetes 1.33.7 安装部署教程:kubeadm、containerd 与 CNI 网络实践

发布时间:2026/10/3 3:27:19
Kubernetes 1.33.7 安装部署教程:kubeadm、containerd 与 CNI 网络实践
1. 版本确认先行1.33.7 的兼容性边界1.1 版本号背后不只是更新日志后台问 Kubernetes 1.33.7 安装部署的人又多了起来。装 K8s 这件事说难不难说简单也简单但绝大多数半途放弃的人都栽在版本兼容这类最基础的细节上。我现在的习惯是任何大版本升级或全新部署先别急着复制命令先花十分钟读 release note 和 compatibility matrix。Kubernetes 1.33.7 这个版本我以它为例来说实际动手前一定要确认官方 release 页面里是否已经正式发布该小版本如果还没有就使用最近一个可用的 1.33.x 小版本部署思路完全一样。版本号之所以重要是因为 K8s 的组件之间遵循严格的版本偏差策略kubeadm、kubelet、kubectl 建议与控制平面保持在同一大版本内小版本可以略低容器运行时和 CNI 插件则各自维护一套兼容矩阵。1.33.7 如果只是控制平面的补丁版本那它通常只修复稳定性问题不会带来 API 变化但对 etcd、containerd 的版本要求可能已经悄悄变了。用旧文档里的参数去装新版经常会出现“文档没错、环境也没错但就是装不上”的尴尬。我建议把下面几项提前核对一遍官方 release 页面的 CHANGELOG、kubeadm 最低支持的 kubelet 版本、containerd 与 CRI 的版本要求、以及你要用的 CNI 插件是否已经声明支持该版本。把这些写进部署前的 checklist比装完出问题再查日志省时间得多。1.2 兼容性核对清单以下是我个人整理的关键版本对应关系实际以官方兼容矩阵为准组件推荐版本备注Kubernetes 控制平面1.33.7以 release 页正式发布为准kubeadm / kubelet / kubectl与集群版本一致建议安装 1.33.7-00容器运行时containerd 1.7.x 以上CRI 端点走 unix socketetcd内置镜像版本kubeadm 自动拉取无需手动指定CNI 插件Calico v3.28 或 Cilium 1.16按组网需求选择CoreDNS随 kubeadm 镜像发布无需单独管理这三张表要在部署时反复确认操作系统与内核、容器运行时与 K8s 版本、CNI 与 K8s 版本。K8s 官方对内核的要求正在逐步提高1.33.x 建议内核 5.15 以上。如果你还在用老旧的 CentOS 7 内核 3.10很多网络特性、cgroup v2 支持都会出问题。不要在这种地方图省事。1.3 硬件与系统底线控制平面节点建议 2 核 4G 以上工作节点可以根据负载往上加。这里的“建议”不是随便说说kubeadm init 时如果内存低于 2Getcd 很容易被 OOM 干掉控制平面直接不稳定。磁盘方面etcd 对 IO 延迟敏感SSD 是底线节点上如果跑日志采集和本地镜像/var分区最好留出充裕空间。系统层面我通常选择 Ubuntu 22.04 LTS 或 Rocky Linux 9内核 5.15 起步容器运行时用 containerd。选操作系统的原则只有一个你用起来最熟、能长期维护的那个才是生产环境的最优解。这篇教程里的命令以 Debian/Ubuntu 系的 apt 为主Rocky 系替换成 dnf 即可。2. 环境初始化四件事内核、Swap、模块与主机名2.1 内核模块与系统参数装 K8s 之前第一步不是装 kubeadm而是把 Linux 内核的网络转发和桥接参数调好。K8s 的 Service、Pod 网络依赖 iptables/ipvs而流量从容器网桥出去时需要 br_netfilter 模块在网桥层过滤 IPv4/IPv6 包。cat EOF | sudo tee /etc/modules-load.d/containerd.conf overlay br_netfilter EOF sudo modprobe overlay sudo modprobe br_netfilter cat EOF | sudo tee /etc/sysctl.d/k8s.conf net.bridge.bridge-nf-call-iptables 1 net.bridge.bridge-nf-call-ip6tables 1 net.ipv4.ip_forward 1 EOF sudo sysctl --system这一步特别容易踩的坑是执行sysctl --system后提示net.bridge.bridge-nf-call-iptables文件不存在。原因通常是你没有先modprobe br_netfilter或者系统没装 bridge 相关内核模块。Kubeadm 的 preflight 检查会直接报这个错提前在这里解决能省一次完整的初始化失败重试。2.2 关闭 Swap 与配置 cgroup 驱动K8s 官方要求 kubelet 和容器运行时使用同一套 cgroup 驱动。在 systemd 为主流的 Linux 发行版上两个都应该使用 systemd cgroup 驱动。如果你一块用 systemd、一块用 cgroupfs节点状态会一直 NotReadykubelet 日志里全是 cgroup 相关的报错。先关 Swap并让重启后也不会自动开启sudo swapoff -a sudo sed -i / swap / s/^/#/ /etc/fstab这里要强调一句swapoff -a只对当前会话生效如果不改/etc/fstab重启后 Swap 又挂上kubelet 会拒绝运行。很多“重启之后节点就没了”的问题根源就是这个。2.3 主机名、DNS 与时间同步K8s 集群内部靠主机名互相识别控制平面初始化时指定的--control-plane-endpoint会被写进证书和 kubeconfig。建议在每台机器上把/etc/hosts写清楚192.168.1.10 k8s-master 192.168.1.11 k8s-node1 192.168.1.12 k8s-node2同时确认 DNS 能解析、时间同步开启。etcd 对时间漂移非常敏感如果节点间时间差超过几百毫秒选举和心跳都会出现诡异问题。装完系统后先跑timedatectl set-ntp true这是成本最低的稳定性投资。3. 容器运行时为什么选 containerd以及怎么配置 systemd cgroup3.1 为什么不是 Docker很多初学者会问装了 Docker 是不是就有容器运行时了在 K8s 1.24 之后dockershim 被移除Kubelet 直接通过 CRIContainer Runtime Interface与容器运行时通信。Docker 自己不做 CRI需要额外的 cri-dockerd 适配层徒增复杂度。所以我建议直接装 containerd它是 CNCF 的毕业项目也是当前 K8s 默认支持的运行时之一性能和稳定性都有保障。如果你有强烈的 Docker CLI 使用习惯也没有问题containerd 提供的ctr和crictl可以覆盖大部分镜像管理需求习惯之后反而更直接。3.2 containerd 安装与默认配置修正安装 containerd 最省事的方式是用 Docker 官方 apt 源因为 containerd 的发行版源码包并不是每个发行版都齐全sudo apt-get update sudo apt-get install -y ca-certificates curl gnupg sudo install -m 0755 -d /etc/apt/keyrings curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg echo \ deb [arch$(dpkg --print-architecture) signed-by/etc/apt/keyrings/docker.gpg] \ https://download.docker.com/linux/ubuntu $(. /etc/os-release echo $VERSION_CODENAME) stable | \ sudo tee /etc/apt/sources.list.d/docker.list /dev/null sudo apt-get update sudo apt-get install -y containerd.io装完先别急着用生成默认配置并修改 cgroup 驱动sudo mkdir -p /etc/containerd sudo containerd config default | sudo tee /etc/containerd/config.toml sudo sed -i s/SystemdCgroup false/SystemdCgroup true/ /etc/containerd/config.toml sudo systemctl restart containerd第一处是 cgroup 驱动改成 systemd 以匹配 kubelet第二处是 sandbox 镜像地址。默认配置里的sandbox_image指向registry.k8s.io/pause:3.x如果所处网络环境拉这个仓库很慢可以改成你常用的镜像源或内网镜像仓库。改完配置后要记得 restart containerd。3.3 pause 镜像与拉取慢的处理每个 Pod 启动前Kubelet 会先拉起 pause 容器用于持有网络命名空间。如果 pause 镜像拉不动Pod 会一直处于 ContainerCreating。处理办法是在 containerd 配置里改sandbox_image改成内网或加速镜像对应的 pause 版本注意 tag 要与 containerd 默认的兼容性匹配。改完配置后执行sudo systemctl restart containerd sudo crictl pull mirror.example.com/pause:3.9想要快速验证 containerd 是否正常执行sudo ctr version能出来版本号就没有大问题。如果crictl还没有可以等 kubeadm 工具一起装。4. 控制平面初始化kubeadm init 参数拆解与失败排错4.1 安装 kubeadm、kubelet、kubectl容器运行时就绪后开始装 Kubernetes 组件。官方源已经迁移到pkgs.k8s.ioDebian 系用以下命令sudo apt-get install -y apt-transport-https ca-certificates curl gpg curl -fsSL https://pkgs.k8s.io/core:/stable:/v1.33.7/deb/Release.key | \ sudo gpg --dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring.gpg echo deb [signed-by/etc/apt/keyrings/kubernetes-apt-keyring.gpg] \ https://pkgs.k8s.io/core:/stable:/v1.33.7/deb/ / | \ sudo tee /etc/apt/sources.list.d/kubernetes.list /dev/null sudo apt-get update sudo apt-get install -y kubelet kubeadm kubectl sudo apt-mark hold kubelet kubeadm kubectl最后一行apt-mark hold很重要。如果你某天执行apt upgrade这三个组件会在不知情的情况下升级到不兼容的版本集群重启后直接旧新组件混跑排查起来非常头疼。生产环境里我见过不止一次因为自动升级导致集群出问题的事故。4.2 kubeadm init 参数逐项拆解初始化控制平面参数不要背但要知道每一个在做什么sudo kubeadm init \ --apiserver-advertise-address192.168.1.10 \ --control-plane-endpointk8s-master:6443 \ --pod-network-cidr192.168.0.0/16 \ --kubernetes-versionv1.33.7 \ --cri-socketunix:///run/containerd/containerd.sock--apiserver-advertise-addressapi-server 对外广播的 IP一般是主节点 IP。如果节点有多个网卡必须显式指定否则 kubelet 可能绑定到错误网卡。--control-plane-endpoint控制平面入口单节点时可以填主节点名:6443高可用集群则填负载均衡器地址。这个地址会写进证书 SAN所以最好从一开始就想好后期改很麻烦。--pod-network-cidrPod 网段必须和 CNI 插件的默认网段一致或至少不冲突。我后面用 Calico 时习惯用 192.168.0.0/16这是 Calico 默认网段。--cri-socket告诉 kubeadm 用哪个 CRI 端点。如果系统里同时装过 Docker这里不显式指定可能会认错。初始化成功后按提示执行三条命令配置 kubectlmkdir -p $HOME/.kube sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config sudo chown $(id -u):$(id -g) $HOME/.kube/config4.3 初始化失败的真实排除链路我来还原一个常见的失败现场执行kubeadm init后卡在 preflight 阶段报[ERROR FileContent--proc-sys-net-bridge-bridge-nf-call-iptables]: /proc/sys/net/bridge/bridge-nf-call-iptables contents are not set to 1处理链路是先确认br_netfilter是否加载lsmod | grep br_netfilter没有就modprobe br_netfilter并把模块写进/etc/modules-load.d/再检查/proc/sys/net/bridge/bridge-nf-call-iptables是否等于 1不满足就重新执行sysctl --system。如果这一步还是报错看看是不是缺bridge内核模块安装bridge-utils或对应的内核包即可。另一类高频问题是镜像拉取超时。kubeadm init 会从镜像仓库拉取 etcd、api-server、controller-manager、scheduler、coredns 等镜像。网络不好的环境经常卡在这一步。可以先手动执行sudo kubeadm config images list --kubernetes-versionv1.33.7 sudo kubeadm config images pull --kubernetes-versionv1.33.7 --cri-socketunix:///run/containerd/containerd.sock如果拉取缓慢在 containerd 配置中配置 mirror 或改用加速源。逐个镜像拉取成功后再重新执行kubeadm init。每次失败后用kubeadm reset清理现场但不能在同一台机器上反复初始化却从不 reset残留的 etcd 数据和证书会让下一次初始化更诡异。5. CNI 网络插件Calico 和 Cilium 的选型与部署要点5.1 CNI 解决什么问题控制平面初始化成功后kubectl get nodes看到 master 是 NotReady 是很正常的因为没有安装 CNI 插件。CNI 干的事是给每个 Pod 分配 IP、打通跨节点通信、实现网络策略。没有 CNIPod 和 Service 的网络就是空的调度上去了也是永远不可用。选型时我主要看三点组网模式、运维复杂度、性能需求。Flannel 最简单只做 Overlay 二层网络但它不支持 NetworkPolicyCalico 用 BGP 或 VXLAN支持网络策略覆盖面广Cilium 基于 eBPF性能和数据平面能力最好但内核要求更高、上手门槛也更高。5.2 Calico 部署要点用 Calico 的话推荐用官方 manifestcurl -O https://raw.githubusercontent.com/projectcalico/calico/v3.28.0/manifests/calico.yaml kubectl apply -f calico.yaml要点有三个--pod-network-cidr必须和 Calico 默认的192.168.0.0/16对齐安装前确认 BGP 模式下节点之间 179 端口能互通如果改了 Calico 的 IP 池网段所有节点要统一否则会看到 Pod 拿到错误网段的 IP。部署后观察kubectl get pods -n kube-system等calico-node全部 Runningmaster 节点状态通常会在一两分钟内变成 Ready。5.3 Cilium 部署要点与性能收益如果对网络延迟敏感Cilium 是很值得尝试的方向。安装方式直接用 Helmhelm repo add cilium https://helm.cilium.io/ helm install cilium cilium/cilium --version 1.16.0 \ --namespace kube-system \ --set ipam.modekubernetesCilium 会在节点上加载 eBPF 程序因此需要内核开启CONFIG_BPF、CONFIG_DEBUG_INFO_BTF等选项。Ubuntu 22.04 的内核通常没问题老内核就直接放弃吧。Cilium 的运维复杂度比 Calico 高一些但换来的是 Service 转发路径短、可观测性数据丰富。小规模集群用 Calico 更省心大规模或对网络性能敏感的场景再考虑 Cilium。5.4 切换 CNI 时的残留清理如果一开始装了 Flannel后来想换成 Calico千万不要只执行一个kubectl apply -f calico.yaml完事。要先删除旧 CNI 的 DaemonSet/Deployment清理节点上的 CNI 配置目录/etc/cni/net.d重启 kubelet再把新 CNI 装上去。旧 CNI 没清干净的话新建 Pod 可能同时被两套插件处理网络直接乱掉。6. 工作节点接入与用 nginx 验证集群6.1 kubeadm join 的原理与 token 处理控制平面 Ready 后初始化成功的输出里会给出一段 join 命令。原理是这样工作节点通过 kubeadm join 向 api-server 发起带 token 的请求通过 bootstrap 机制拿到自己的身份证书然后把 kubelet 连到控制平面。默认 token 有效期是 24 小时过期后不需要重新初始化重新生成即可sudo kubeadm token create --print-join-command在工作节点上执行后回到主节点用kubectl get nodes等节点变为 Ready。如果节点一直 NotReady先看systemctl status kubelet的输出再用journalctl -u kubelet -f看实时日志。绝大多数节点加入失败都是 cgroup 驱动不一致、主机名解析不到、或者 join 命令里的 token 过期。6.2 用 nginx 验证 Pod 调度与网络节点全部 Ready 之后我会先用一个最小负载验证集群是否真的能干活。nginx 是最好的探路石kubectl create deployment nginx --imagenginx:1.27 kubectl scale deployment nginx --replicas2 kubectl expose deployment nginx --port80 --typeNodePort kubectl get pods -o wide kubectl get svc nginx看到两个 Pod 在不同节点上 RunningService 的 NodePort 端口能访问说明调度、kube-proxy、CNI 都正常。这里如果 Pod 一直 ContainerCreating优先kubectl describe pod nginx-xxxx看事件大部分原因逃不出镜像拉不到、CNI 未就绪、资源不足这三类。6.3 NodePort、LoadBalancer 与 Ingress 的取舍验证完 NodePort很多人会纠结要不要配 LoadBalancer 和 Ingress。我的建议是离线调试用 NodePort 够了云上直接用云厂商的 LoadBalancer统一流量入口最终还是要上 Ingress。K8s 的 Service 本身解决的是 Pod IP 漂移带来的服务发现问题真正对外发布能力要靠 Ingress Controller比如 ingress-nginx。这些都可以在集群稳定后再逐步补齐第一天的目标是把集群装起来、确认所有组件健康不要一次上太多东西。7. 装完不是终点证书、备份、健康检查与维护习惯7.1 装完先跑几条检查命令我每次装完新集群固定会跑下面这几条kubectl get nodes -o wide kubectl get pods -A -o wide kubectl get events --all-namespaces --sort-by.lastTimestamp | tail -20 sudo kubeadm certs check-expiration前三条确认调度和运行状态最后一条看证书剩余时间。K8s 的默认证书有效期是一年但很多小团队装完就忘了等证书过期后整个集群的 API 全部不可用才手忙脚乱去查。kubeadm certs renew all可以续期但最好还是把证书过期时间写进监控。7.2 etcd 备份是最后一道防线K8s 的集群状态全部存在 etcd 里包括所有资源的定义、期望状态和配置。一旦误删 Namespace、错误应用了一个摧毁性的 manifest日常操作无法恢复时etcd 备份就是救命稻草。etcd 备份最实用的方式是快照sudo ETCDCTL_API3 etcdctl \ --endpoints127.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 \ snapshot save /backup/etcd-$(date %F).db建议配合定时任务每天跑一次并同步到异机存储。恢复流程虽然简单但不要在没有演练过的情况下第一次就上生产。7.3 我长期带着的几个排查命令最后分享几个我平时排查用的顺手命令。节点 NotReady 时journalctl -u kubelet -f是第一个要看的地方Pod 调度失败时kubectl describe pod name能告诉你事件DNS 解析异常时先确认 CoreDNS Pod 是不是 Running再用一个临时 pod 做nslookup kubernetes.default这类探针测试。这些命令看着基础但真实排障时比翻各种文档都管用。Kubernetes 1.33.7 的部署流程本身并不复杂真正拉开稳定运维差距的是这些“装完之后”的细节。你只要把环境、运行时、网络、验证、备份这条链路都走顺整个集群的底座就算扎实了。