多彩编程 多彩编程MZPH · CODE BLOG
ARTICLE DETAIL

文章详情

深耕前端与后端开发技术的一线实战笔记与踩坑复盘。

Ubuntu 22.04 安装 Kubernetes 1.28 完整指南:containerd、kubeadm 与避坑实操

Ubuntu 22.04 安装 Kubernetes 1.28 完整指南:containerd、kubeadm 与避坑实操 最近接手了一套运维环境的搭建任务要在几台 Ubuntu 22.04 的机器上把 Kubernetes 1.28 集群拉起来。本来以为照着官方文档敲几行命令就完事结果从挑运行时、配软件源到 kubeadm init再到两台节点始终 NotReady前后折腾了将近两天。这篇就当作一次完整复盘把 ubuntu22.04 安装 k8s1.28 步骤里所有关键选择、命令、参数和坑位都摊开讲清楚。适合刚接触 K8s 想搭一套可复现环境的人也适合自己折腾过但被 containerd 配置、镜像源、网络插件选型卡住的老手。全程不使用 docker容器运行时直接采用 containerd这也是 K8s 1.24 之后社区的主流做法。文章里的命令都是我在 clean 的 22.04 环境上实测执行过的可以直接抄作业。1. 部署前先把三个关键决策定下来运行时、版本、网络插件1.1 为什么是 Ubuntu 22.04 和 K8s 1.28 的组合Ubuntu 22.04 是长期支持版本生命周期到 2027 年内核默认 5.15对于 overlayfs、br_netfilter 等容器相关内核特性的支持没有历史包袱。相比 20.0422.04 的 systemd 版本和 apt 依赖链对 containerd 更友好不用为了凑依赖去折腾第三方软件源这是我在生产环境更愿意选它的原因。K8s 1.28 属于 2023 年下半年的版本相比 1.26、1.27 引入了不少稳定性改进和特性开关调整比如节点卷扩展、cgroup 内存热插拔等。对于想搭一套新集群的人来说选新不选旧是对的但也没必要追着 1.29、1.30 跑因为配套的生态组件CNI、dashboard、监控对这些新版本的支持需要等一段磨合期。1.28 在社区里的资料量、踩坑记录都足够多查起问题来不至于两眼一抹黑。这里还要强调一个很容易被忽略的点Ubuntu 22.04 的 apt 源本身不会因为你选了 22.04 就自动给你配好 K8s 的仓库。K8s 的组件需要自己手动添加 apt 源源代号在很长一段时间内一直沿用 kubernetes-xenial哪怕你用的是 Jammy这个代号也不用改。很多新手在这个地方卡住把 xenial 改成 jammy 反而找不到包。1.2 容器运行时绕不开 containerdK8s 从 1.24 版本开始正式把 dockershim 从源码中移除也就是说 docker 已经不能再作为默认的容器运行时直接对接 kubelet。想要继续用 docker需要额外部署 cri-dockerd 来做一层转换这在生产上基本属于给自己找麻烦。1.28 版本里kubelet 通过 CRIContainer Runtime Interface直接与 containerd 通信containerd 负责镜像管理、容器生命周期、sandbox 等底层工作。containerd 本身是一个行业标准级组件CNCF 毕业项目Docker 底层大部分运行时逻辑就来自它所以在 K8s 1.28 的环境里选择 containerd 没有悬念。采用 CRI-O 也可以但 CRI-O 在 Ubuntu 22.04 上的安装路径没有 containerd 顺滑社区资料也相对少没必要在第一步就给自己增加复杂度。1.3 组件版本对应关系与“三个小版本”原则K8s 集群里有几个关键组件需要版本对齐kubeadm、kubelet、kubectl。官方支持策略是小版本差不能超过一档但最省心的做法是全部锁定到同一个版本。我在这次搭建里用的版本组合是组件版本作用kubeadm1.28.2初始化集群、生成 join 命令、管理升级kubelet1.28.2每个节点上的守护进程负责把 Pod 清单变成真实容器kubectl1.28.2操作集群的客户端工具containerd1.7.x容器运行时通过 CRI 对接 kubelet这里有个实务经验kubectl 版本可以比集群版本稍微新一点点但 kubeadm 和 kubelet 最好严格一致。如果 master 用 1.28.2worker 上装个 1.28.1 或 1.28.3多数情况下能正常工作但一旦涉及 kubeadm upgrade 或者排障时的日志对照版本不一致会让你分心去排除版本干扰。所有节点一键装好之后用 apt-mark hold 把这几个包锁住防止哪天执行 apt upgrade 时被系统悄悄升级走样。2. 所有节点统一做环境初始化2.1 主机规划与网络规划搭建集群之前先画一张简单的表把节点角色、主机名、IP 地址、最低硬件规划好。这次我用的环境是三台虚拟机但在实际操作中两台也能跑只是要接受单控制平面的固有风险。节点角色主机名IP 地址最低硬件建议控制平面k8s-master192.168.1.102 核 4G生产至少 4 核 8G工作节点k8s-node1192.168.1.112 核 4G工作节点k8s-node2192.168.1.122 核 4G网络规划方面我会把节点网段、Pod 网段、Service 网段分开考虑。节点网段就是服务器所在的 192.168.1.0/24Pod 网段计划用 10.244.0.0/16这是 Flannel 的默认值Service 网段保持 10.96.0.0/12 不动。Pod 网段一定要避开真实局域网网段否则容器路由会和物理网络撞车。服务器如果有多个网卡例如云主机同时有内网和公网 IP后面 kubeadm init 时要显式指定 --apiserver-advertise-address否则 apiserver 很容易绑定到错误的网卡上。2.2 系统基础配置五件事一个都不能省不管是 control plane 还是 worker这几步操作完全一致。说它们基础是因为漏掉任何一项后面都会以非常隐蔽的方式报错。第一件事设置主机名。分别在三台机器上执行注意别把 master 和 node 的名字搞混。hostnamectl set-hostname k8s-master # worker 上分别执行 hostnamectl set-hostname k8s-node1 / k8s-node2第二件事配置 /etc/hosts。K8s 节点之间会通过主机名互访如果解析不到kubelet 和 apiserver 的日志里会出现各种连接超时。把三台机器的映射都写进去之后加新节点再补充。cat /etc/hosts EOF 192.168.1.10 k8s-master 192.168.1.11 k8s-node1 192.168.1.12 k8s-node2 EOF第三件事关闭 swap。K8s 1.28 在默认配置下要求节点必须关闭 swap否则 kubelet 会拒绝工作。执行 swapoff -a 只是临时关闭重启后会重新挂载必须把 /etc/fstab 里对应的行注释掉才是真正的“永久关闭”。swapoff -a sed -ri s/.*swap.*/#/ /etc/fstab第四件事加载内核模块。容器网络需要 netfilter 来处理桥接流量转发overlay 文件系统则是 containerd 镜像分层的基础。把这两个模块写入 /etc/modules-load.d/k8s.conf让系统开机自动加载。cat EOF | tee /etc/modules-load.d/k8s.conf overlay br_netfilter EOF modprobe overlay modprobe br_netfilter第五件事配置 sysctl 参数。这里要特别注意顺序必须先把 br_netfilter 模块加载好再执行 sysctl --system否则像 net.bridge.bridge-nf-call-iptables 这种参数会因为对应内核文件还不存在而报错。这个坑我踩过一次排查半天最后发现是模块没加载。cat EOF | 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 sysctl --systemnet.ipv4.ip_forward 控制的是 IP 转发K8s 的 Pod 跨节点通信必须依赖这台机器能把收到的报文按路由表再送出去。bridge-nf-call-iptables 则是让网桥上的流量也能被 iptables 规则处理Service 的转发规则才能生效。把这些全部设成 1是后续一切容器通信的前提。2.3 软件源与时间同步安装速度的隐形影响因素Ubuntu 22.04 默认 apt 源在海外的下载速度很不稳定安装 containerd、kubeadm 这些包时经常中途卡死。建议先把 apt 源切到阿里云或者清华的镜像源。对于 22.04源文件还是在 /etc/apt/sources.list直接替换sed -i s//.*archive.ubuntu.com//mirrors.aliyun.comg; s//security.ubuntu.com//mirrors.aliyun.comg /etc/apt/sources.list apt update时间同步是很容易被忽略的一环。K8s 的证书签发和校验完全依赖节点时间如果某台服务器时间漂移超过几分钟kubeadm join 时会直接报证书校验失败。Ubuntu 22.04 默认带 systemd-timesyncd可以通过 timedatectl 开启 NTP 同步。如果是纯内网机器就需要在局域网内准备一个 NTP 服务器并在节点上把时间源指过去。timedatectl set-ntp true timedatectl status在动手装 K8s 之前先跑一下 timedatectl status 确认时间是同步状态再跑 apt update 确认源没问题这两件事能让后面省掉大量排障时间。3. 安装并配置 containerdK8s 的地基3.1 通过 Docker 官方源安装 containerdUbuntu 22.04 自带的 apt 源里也有 containerd但版本通常停留在 1.6.x。K8s 1.28 官方推荐的 containerd 版本是 1.7.x包含了很多 CRI 路径上的修复。从 GitHub 下载二进制理论上可行但更新和卸载时不太方便我习惯用 Docker 官方 apt 源来安装 containerd.io 这个包。注意这里只是借用 Docker 官方源来装 containerd不会引入 docker 本体。国内环境下把 Docker 官方源替换成阿里云的镜像源命令如下curl -fsSL https://mirrors.aliyun.com/docker-ce/linux/ubuntu/gpg | gpg --dearmor -o /usr/share/keyrings/docker-ce.gpg echo deb [archamd64 signed-by/usr/share/keyrings/docker-ce.gpg] https://mirrors.aliyun.com/docker-ce/linux/ubuntu jammy stable | tee /etc/apt/sources.list.d/docker-ce.list apt update apt-cache madison containerd.io apt install -y containerd.io执行 apt-cache madison containerd.io 这一步是我个人的习惯先确认源里有哪些版本可选再决定要不要指定版本。默认直接 install 会装最新版 1.7.x符合预期。装完之后不需要急着启动先把配置改好再启动。3.2 修改 config.toml 的两个关键点SystemdCgroup 和 sandbox_imagecontainerd 需要先初始化配置目录和默认配置然后我们手动改两个地方。mkdir -p /etc/containerd containerd config default | tee /etc/containerd/config.toml第一处是 SystemdCgroup。在生成的 config.toml 里找到 runc 相关的段落把 SystemdCgroup 从 false 改成 true。这个参数决定 containerd 使用哪种 cgroup 驱动来管理资源隔离。K8s 1.28 的 kubelet 默认使用 systemd cgroup 驱动而 containerd 默认参数是 cgroupfs。两边格式对不上kubelet 会一直报 cgroup driver 不匹配节点永远无法 Ready。你可以先全局搜索定位grep -n SystemdCgroup /etc/containerd/config.toml找到[plugins.io.containerd.grpc.v1.cri.containerd.runtimes.runc.options]这一段把SystemdCgroup true写进去。对新手来说这一步是全文最容易出错的环节。第二处是 sandbox_image也就是 pause 镜像。这个镜像负责给每个 Pod 提供基础设施容器所有 Pod 都会用到。默认值是 k8s.gcr.io/pause:3.9在国内网络环境下基本拉不动。kubeadm init 如果卡在 Pulling sandbox image 出不来十有八九就是这里没改。把它替换成阿里云的 pause 镜像[plugins.io.containerd.grpc.v1.cri] sandbox_image registry.aliyuncs.com/google_containers/pause:3.9改完配置后保存文件重启并设置开机自启systemctl restart containerd systemctl enable containerd3.3 验证 containerd CRI 模式containerd 装完到底能不能被 kubelet 使用需要验证两件事。第一件事是确认 CRI 插件存在ctr version ctr plugins list | grep cri第二件事是确认 CRI socket 路径可用。kubelet 默认通过 unix:///run/containerd/containerd.sock 和 containerd 通信。为了后续排障方便我会顺手装一个 crictl并写好配置VERSIONv1.28.0 wget https://github.com/kubernetes-sigs/cri-tools/releases/download/$VERSION/crictl-$VERSION-linux-amd64.tar.gz tar -zxvf crictl-$VERSION-linux-amd64.tar.gz -C /usr/local/bin cat /etc/crictl.yaml EOF runtime-endpoint: unix:///run/containerd/containerd.sock image-endpoint: unix:///run/containerd/containerd.sock timeout: 10 debug: false EOF配置好之后可以执行 crictl pull busybox 拉一个很小的测试镜像验证整条 CRI 通路是否正常。我在实际操作中会顺手把 pause 镜像提前拉好这样后面 init 的时候能省一点时间crictl pull registry.aliyuncs.com/google_containers/pause:3.94. 安装 kubeadm、kubelet、kubectl4.1 配置阿里云 Kubernetes apt 源Kubernetes 官方源地址是 pkgs.k8s.io国内访问并不总是顺畅。常规做法是使用阿里云的 Kubernetes apt 镜像源。添加源时要注意这个源直接兼容所有 Ubuntu 系源文件名固定叫 kubernetes-xenial这个代号从 Xenial 一直沿用到 Jammy都不用改。curl -fsSL https://mirrors.aliyun.com/kubernetes/apt/doc/apt-key.gpg | gpg --dearmor -o /usr/share/keyrings/kubernetes-apt-keyring.gpg echo deb [signed-by/usr/share/keyrings/kubernetes-apt-keyring.gpg] https://mirrors.aliyun.com/kubernetes/apt kubernetes-xenial main | tee /etc/apt/sources.list.d/kubernetes.list apt update执行完 apt update 之后先不要急着 install用 apt-cache madison kubeadm 确认一下源里有哪些可用版本。这样能确保待会安装时指定的 1.28.2 真实存在避免手滑填错版本号然后被 apt 拒绝。4.2 安装指定版本并锁定指定版本安装的命令如下注意版本号和后面的 -00 是 apt 仓库中完整版本一部分需要一起写进去apt install -y kubelet1.28.2-00 kubeadm1.28.2-00 kubectl1.28.2-00装完以后立刻执行 apt-mark hold把这三个包标记为保持当前版本防止以后执行 apt upgrade 时被无差别升级apt-mark hold kubelet kubeadm kubectl这里有一个非常重要的操作提醒刚装完不要急着启动 kubelet也不要设置开机自启。现在集群还不存在kubelet 根本没有可用的集群配置强行启动只会让它反复报错刷日志甚至影响你对后续 init 输出的判断。kubeadm init 或 kubeadm join 的时候会自己去拉起 kubelet到那一步它才真正“有活可干”。装完以后确认一下版本即可kubeadm version kubelet --version kubectl version --client5. kubeadm init 初始化控制平面5.1 init 命令各项参数拆解每条参数都有用途控制平面节点上所有基础环境准备完毕后就可以执行 init 了。我这次用的完整命令是kubeadm init \ --apiserver-advertise-address192.168.1.10 \ --kubernetes-versionv1.28.2 \ --pod-network-cidr10.244.0.0/16 \ --service-cidr10.96.0.0/12 \ --image-repositoryregistry.aliyuncs.com/google_containers逐个说下为什么这么配。--apiserver-advertise-address 指定 apiserver 对外通告的地址。多网卡机器上如果不写kubeadm 会去摸索认第一块网卡的 IP很可能把公网 IP 或者 docker0 的 IP 当成了集群入口后面所有节点都连不上。这种坑在云服务器上非常高发所以只要机器上有多网卡我永远显式写上。--kubernetes-version 要和 kubelet 的实际版本保持一致。不写的话 kubeadm 会自动探测但如果你在初始化前手动改过某些配置文件可能探测出一个不是你预期的小版本。干脆写死。--pod-network-cidr 是给 Pod 分配的网段。这个参数必须和后面 CNI 插件期望的网段一致。用 Flannel 就是 10.244.0.0/16用 Calico 通常用 192.168.0.0/16。如果你机器的局域网正好是 192.168.0.0/24那 Cupo 网段就和真实网段冲突了所以要提前根据实际情况决定用哪个网段。--service-cidr 是 Service 的虚拟网段默认 10.96.0.0/12。除非你的网络环境和这个段冲突否则不用动。--image-repository 指定从哪个镜像仓库拉取控制平面组件镜像。默认是 registry.k8s.io在国内网络环境下困难重重。换成阿里云的 registry.aliyuncs.com/google_containers后面 kube-apiserver、etcd、coredns 这些镜像基本都能顺利拉取。执行 init 之前还有一个细节值得做提前用 kubeadm config images pull 把需要的镜像拉好。这样一来 init 的执行时间会明显缩短而且如果某个镜像有问题能提前发现而不是等 init 跑到一半才报错。kubeadm config images pull --image-repositoryregistry.aliyuncs.com/google_containers --kubernetes-versionv1.28.25.2 初始化后的 kubectl 配置与基本验证kubeadm init 成功之后终端会输出一大段信息里面有两条内容必须保存好一条是配置 kubectl 的命令另一条是加入节点的 join 命令。先配置 kubectl 的访问凭据mkdir -p $HOME/.kube sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config sudo chown $(id -u):$(id -g) $HOME/.kube/config然后验证节点状态kubectl get nodes这时候节点会显示 NotReady这是完全正常的。控制平面组件虽然起来了但网络插件还没装所以节点自己觉得网络没准备好。同时可以看一下系统组件的运行状态kubectl get pods -n kube-system -o wide如果 coredns 等 Pod 处于 Pending也不用慌原因还是同一个CNI 网络还没就绪等装完网络插件它们会自动运行起来。5.3 部署 CNI 网络插件Flannel 和 Calico 怎么选CNI 插件的作用是给每个 Pod 分配 IP并负责把 Pod 的网络打通到宿主机之外。没有 CNI集群内部通信、Service 转发、跨节点 Pod 互访全部瘫痪。我这次选的是 Flannel理由很朴素配置简单、默认网段 10.244.0.0/16 和 init 命令里的参数完全匹配出了事故好排查。Flannel 基于 VXLAN 封装性能对中小规模环境足够用Calico 的优势在成熟的路由模式和安全策略支持生产环境更大规模后再切换也不迟。Flannel 的安装就一条命令kubectl apply -f https://raw.githubusercontent.com/flannel-io/flannel/v0.22.3/Documentation/kube-flannel.yml如果你的服务器访问不了 raw.githubusercontent.com可以先在能访问的地方下载下来再通过本地上传或者直接在一个可访问的镜像站点下载后执行 kubectl apply -f 文件名。如果执意用 Calico安装命令是kubectl create -f https://raw.githubusercontent.com/projectcalico/calico/v3.27.2/manifests/calico.yaml但要特别注意 calico.yaml 里默认的 Pod 网段是 192.168.0.0/16如果 kubeadm init 时用的是 10.244.0.0/16就必须把 calico.yaml 里 CALICO_IPV4POOL_CIDR 这个环境变量的值改成 10.244.0.0/16否则两个网段对不上节点永远是 NotReady。这个细节当年也坑过我现在看到有人装 Calico 出问题我都会先让他检查这处。装完等待镜像拉取和 Pod 启动kubectl get pods -n kube-system -w等 flannel 或 calico 相关 Pod 全部 Running 之后再执行 kubectl get nodesmaster 应该已经变成 Ready 状态。5.4 单机测试时如何去掉控制平面污点如果只有一台机器或者你希望 master 也帮忙承担业务 Pod需要把控制平面节点的 taint 去掉。K8s 默认会给控制平面节点打污点拒绝普通 Pod 调度上去避免 apiserver、etcd 和业务容器抢资源。kubectl taint nodes --all node-role.kubernetes.io/control-plane-这条命令的意思是去掉所有节点上的控制平面污点。测试环境强烈建议执行否则你只有一台机器的时候会发现 Pod 永远 Pending 在那里。生产环境请慎重控制平面节点最好专心跑系统组件。6. Worker 节点加入集群6.1 重新生成 join 命令kubeadm init 成功时会在输出里给出 join 命令但 init 生成的 token 有效期只有 24 小时。如果这时 worker 节点才准备就绪token 可能早已失效。与其翻出旧命令碰运气不如直接在 master 上重新生成一条kubeadm token create --print-join-command输出长这样kubeadm join 192.168.1.10:6443 --token xxxxxx.yyyyyyyyyyyyyyyy --discovery-token-ca-cert-hash sha256:xxxxxxxxxx这条命令建议保存到本地或者直接复制到 worker 节点上执行。注意 join 命令里的 --discovery-token-ca-cert-hash 不是随便生成的它是集群 CA 证书的哈希指纹worker 节点靠它确认自己连的是对的 apiserver而不是中间人伪造的地址。6.2 节点加入与状态验证worker 节点只需要执行两部分前面第 2、3、4 节的系统初始化、containerd 安装、kubelet 组件安装。不需要执行 kubeadm init也不需要装 kubectl。在 worker 节点上执行 join 命令kubeadm join 192.168.1.10:6443 --token xxx --discovery-token-ca-cert-hash sha256:xxxjoin 过程会自动拉起 kubelet但为了避免重启后失联还是手动把 kubelet 设置成开机自启systemctl enable kubelet回到 master 节点执行kubectl get nodes kubectl get pods -n kube-system -o wide新节点从 NotReady 到 Ready 通常需要几十秒到几分钟主要取决于拉取 pause 镜像和其他组件的速度。如果超过五分钟还是 NotReady直接翻到第 7 节对照排查。7. 安装过程高概率踩坑实录与排查速查7.1 kubelet 反复崩溃的排查路径节点状态的很多问题根源都在 kubelet 起不来或者起来后又退出。先看服务状态systemctl status kubelet journalctl -u kubelet -f日志刷得太快看不清关键错误时建议用筛选命令journalctl -u kubelet --since 5 min ago | grep -E error|failed|refused|invalid | tail -20最常见的报错集中在两类。一类是 SystemdCgroup 没有设置成 true日志中会出现类似 kubelet cgroup driver 不匹配的提示。另一类是 swap 没关干净日志里会直接提示 swap is enabled。这两类问题对照第 2.2 节和 3.2 节重新检查一遍基本能解决。7.2 镜像拉不下来的集中场景镜像拉取失败是新手重灾区。第一个场景是 kubeadm init 卡在 Pulling kube-apiserver 这种步骤解决办法是提前手动拉一遍镜像kubeadm config images pull --image-repositoryregistry.aliyuncs.com/google_containers --kubernetes-versionv1.28.2这样能直接看到是哪几个镜像失败了。如果某个镜像一直超时可以先 crictl pull 手动拉一次确认镜像源是否可用。第二个场景是运行时报 ErrImagePull这种情况先去 crictl images 看本地镜像是否存在再用 crictl pull 补充拉取。第三个场景是在内网环境需要完全使用公司内部镜像仓库那就把 containerd 配置里的 sandbox_image 和 kubeadm init 的 --image-repository 统一指向内部仓库两边必须保持一致。7.3 节点 NotReady 的典型原因与排除顺序节点 NotReady 在安装阶段有很强的规律性我整理了一个排查顺序表照着顺序查可以节省大量时间现象可能原因排查方式master 初始化后 NotReadyCNI 没装或 Pod 网段不一致kubectl get pods -n kube-system看 flannel/calico 状态worker 加入后 NotReadycontainerd 配置不一致、kubelet 没起来journalctl -u kubeletcrictl info节点反复 Ready/NotReadyswap 未彻底关闭、kubelet 配置被改动free -h、kubectl describe nodePod 之间通信不通FORWARD 链默认策略被设成 DROPiptables -L FORWARDFORWARD 链的问题很多人没遇到过我单独说一下。装完 containerd 后某些场景下 iptables 的 FORWARD 链默认策略会被设成 DROP导致跨节点的 Pod 流量被直接丢弃。表象是节点状态看起来是 Ready但 Pod 之间 ping 不通。临时解决办法iptables -P FORWARD ACCEPT更稳妥的做法是写一个 systemd 服务或启动脚本在系统启动后自动执行这条规则防止重启后规则丢失。7.4 token 过期、证书到期、重启自愈token 有效期是 24 小时过期后重新生成一条 join 命令就行无需重新 init。如果你的 worker 因为各种原因一直没加入到 master 上重新执行 kubeadm token create --print-join-command 即可。证书方面K8s 集群的证书有效期为一年到期前需要续期。查看证书剩余时间kubeadm certs check-expiration续期命令kubeadm certs renew all续期之后需要重启 apiserver 等静态 Pod 使新证书生效可以直接通过重启 kubelet 来间接重启因为静态 Pod 由 kubelet 守护拉起。关于重启自愈还有一个很多人关心的问题服务器重启后集群会怎样正常情况下kubelet 开机会自动拉起控制平面的静态 Podcontainerd 开机会自动接管容器生命周期集群可以在几分钟内自愈。如果重启后 apiserver 起不来优先检查 containerd 和 kubelet 两个服务是否正常开机自启。7.5 几个值得养成的操作习惯最后补充几个我在实际操作中慢慢形成的习惯。第一尽量用 kubectl describe 而不是只盯着 get。kubectl describe node xxx 可以一次性看到节点上的 Conditions、资源压力、污点信息定位 NotReady 的时候信息量大得多。第二学会用事件聚合。集群出问题后不要一个个 Pod 去 describe先看全量事件kubectl get events --all-namespaces --sort-by.lastTimestamp这样能把同一时间段内所有异常事件放在一起看很多时候问题根源并不在你当时盯着看的那个 Pod 上。第三master 上的 /etc/kubernetes/manifests/ 目录是控制平面静态 Pod 的清单目录。apiserver、etcd、scheduler、controller-manager 这些组件都是以静态 Pod 的方式由 kubelet 直接拉起。如果某个控制平面组件一直重启直接看 kubelet 日志和这个目录下的 yaml 文件比怀疑集群层面更快。第四新节点入网前先在 /etc/hosts 确认解析把主机名、IP 对好。集群内部很多组件通过主机名访问彼此hosts 文件写错导致的问题会在运行几天后以各种诡异的超时现象冒出来排查成本极高。结尾就写到这里吧。整套 ubuntu22.04 安装 k8s1.28 的步骤走完一遍后最大的感受是这类问题 80% 的故障都集中在几个固定环节——软件源、cgroup 驱动、swap、hosts、Pod 网段。每次新搭一套环境我都会在动手前先用一个检查脚本把这几项过一遍然后再跑 kubeadm init 或 join。如果你正卡在某一步建议先把日志拉出来看看是不是上面提到的某个经典原因大概率能少走很多弯路。
返回列表