CentOS 7 + kubeadm 搭建 Kubernetes 集群的底层原理与排障指南

📅 2026/6/21 6:52:19
CentOS 7 + kubeadm 搭建 Kubernetes 集群的底层原理与排障指南
1. 为什么在 CentOS 7 上用 kubeadm 搭建集群不是“选一个工具”而是“踩准一条技术路径”你打开终端敲下yum install -y kubelet kubeadm kubectl的那一刻其实已经站在了一个被反复验证过、但又极易失手的十字路口。这不是在搭一个玩具环境——kubeadm 是 Kubernetes 官方认证的“生产就绪型集群引导工具”它不负责帮你写 YAML也不替你调网络插件但它把整个集群从零启动的原子操作链封装成了可复现、可审计、可回滚的标准化流程。而 CentOS 7这个在企业服务器市场盘踞十年以上的稳定发行版恰恰是这条路径上最常被选用、也最容易翻车的底座。我第一次在 VMware Workstation Pro 里装 CentOS 7 Minimal 镜像时以为只是配个 IP、关个防火墙就完事了。结果kubeadm init卡在[preflight] Running pre-flight checks阶段整整 47 分钟日志里只有一行[ERROR FileContent--proc-sys-net-bridge-bridge-nf-call-iptables: /proc/sys/net/bridge/bridge-nf-call-iptables does not exist]。查文档官方只说“确保已加载 br_netfilter 模块”。试命令modprobe br_netfilter立刻报错Module br_netfilter not found in directory /lib/modules/3.10.0-1160.el7.x86_64。原来Minimal 镜像默认不装 kernel-modules-extra 包——这个包里才藏着 br_netfilter、ip_vs、nf_conntrack_ipv4 这些容器网络和负载均衡的底层驱动。这背后是两个关键事实第一kubeadm 不是黑盒它是一套强依赖内核模块与系统参数的启动协议第二CentOS 7 的 kernel 版本3.10.0虽老但只要补全模块、调对参数其稳定性反而比某些新内核更适配长期运行的控制平面。所以本文不讲“怎么点下一步”而是带你拆开 kubeadm init 的每一道预检项看清楚它到底在检查什么、为什么必须这样检查、如果失败该怎么精准定位——就像修车师傅听发动机异响不是换零件而是先听清是气门声还是连杆声。你不需要是 Linux 内核专家但得知道sysctl -w net.bridge.bridge-nf-call-iptables1这条命令改的是哪一层的流量转发逻辑你不需要背熟所有 cgroup v1/v2 差异但得明白systemd作为 init 系统如何影响 kubelet 的 cgroup 驱动选择你更不需要记住全部 23 个 preflight check 名称但得掌握一套通用排查法当 kubeadm 报错时先看它引用的文件路径是否存在、内容是否符合预期、对应内核模块是否已加载、相关服务是否已启用。这才是真正能让你在内网离线环境、VMware 虚拟机、甚至物理服务器上把集群稳稳立住的核心能力。2. 环境准备从 VMware 虚拟机到生产级基座的七道硬门槛很多人卡在第一步不是因为不会敲命令而是没意识到kubeadm 对底层系统的“洁癖”程度远超一般应用部署。它不像安装 Nginx 那样容忍你少装几个依赖而是像外科手术前的无菌准备——缺一不可且顺序不能乱。下面这七步是我在线上环境、客户现场、培训课堂中反复验证过的最小可行清单漏掉任意一项init 就会以不同形式报错且错误信息往往极具误导性。2.1 虚拟机配置CPU、内存、磁盘的隐性约束在 VMware Workstation Pro 中创建 CentOS 7 虚拟机时别只盯着“2核4G”这种表面参数。kubeadm init 默认要求至少 2 CPU 核心、2GB 内存但这只是控制平面节点的底线。真实场景中CPU 核心数必须 ≥2且不能是超线程虚拟核心HT。VMware 中需确认Processor Virtualize Intel VT-x/EPT or AMD-V/RVI已勾选否则 kubelet 启动时会报failed to run Kubelet: unable to load client CA file—— 这其实是 CPU 不支持硬件虚拟化导致 TLS 握手失败的间接表现。内存分配2GB 是理论值实测中若同时运行 Docker、etcd、kube-apiserver建议起步 4GB。内存不足时kubeadm init会卡在[certs] Generating ca certificate and key日志无报错top显示kubelet进程 RSS 持续增长至 95% 后僵死。磁盘 I/Oetcd 对磁盘延迟极度敏感。VMware 默认的 SATA 控制器 单个虚拟磁盘在高并发写入时etcdserver: read-only range request took too long错误频发。解决方案是改用LSI Logic SAS控制器并为/var/lib/etcd单独挂载一块 SSD 类型的虚拟磁盘即使只是 VMware 的“SSD 模拟”模式。提示在 VMware 中创建虚拟机后务必进入VM Settings Options Advanced Firmware type选择BIOS非 UEFI。CentOS 7 的 GRUB2 对 UEFI 支持存在兼容性问题会导致kubeadm init后节点无法正常加入集群现象是kubectl get nodes显示NotReady且journalctl -u kubelet中大量Failed to list *v1.Node日志。2.2 系统初始化Minimal 镜像的“补丁包”清单CentOS 7 Minimal 镜像是精简的但 kubeadm 是“重口味”的。以下命令必须在yum update -y之后、安装 kubeadm 之前执行顺序不可颠倒# 1. 补全内核模块解决 br_netfilter、ip_vs 等缺失 sudo yum install -y kernel-modules-extra # 2. 加载必要模块并持久化br_netfilter 是桥接 iptables 规则的关键 sudo modprobe br_netfilter echo br_netfilter | sudo tee -a /etc/modules-load.d/k8s.conf echo ip_vs | sudo tee -a /etc/modules-load.d/k8s.conf echo ip_vs_rr | sudo tee -a /etc/modules-load.d/k8s.conf echo ip_vs_wrr | sudo tee -a /etc/modules-load.d/k8s.conf echo ip_vs_sh | sudo tee -a /etc/modules-load.d/k8s.conf # 3. 配置 sysctl 参数这些是 kubeadm preflight check 的硬性要求 cat EOF | sudo tee /etc/sysctl.d/k8s.conf net.bridge.bridge-nf-call-ip6tables 1 net.bridge.bridge-nf-call-iptables 1 net.ipv4.ip_forward 1 vm.swappiness 0 EOF sudo sysctl --system # 4. 关闭 swapkubeadm 强制要求否则 init 直接失败 sudo swapoff -a sudo sed -i / swap / s/^/#/ /etc/fstab这里的关键细节在于kernel-modules-extra包。它不是一个可选组件而是br_netfilter模块的唯一来源。很多教程只写modprobe br_netfilter却不提这个包导致用户在 Minimal 镜像中永远无法成功加载。ip_vs系列模块同理——它们是 kube-proxy 在ipvs模式下工作的基础即使你当前用iptables模式kubeadm 的预检也会检查它们是否存在。2.3 时间同步与主机名被低估的集群“神经系统”Kubernetes 控制平面组件apiserver、etcd、scheduler对节点间时间偏差极其敏感。偏差超过 1 秒etcd 就可能拒绝写入现象是kubeadm init卡在[etcd] Creating local etcd static pod manifestjournalctl -u etcd显示invalid argument。解决方案不是简单ntpdate而是启用chronyd并强制校准sudo yum install -y chrony sudo systemctl enable chronyd sudo systemctl start chronyd # 强制立即同步避免等待默认 64 秒间隔 sudo chronyc makestep # 验证同步状态 sudo chronyc tracking主机名配置同样关键。kubeadm 会将节点 hostname 作为 Node 对象的metadata.name。如果 hostname 是localhost.localdomain或包含下划线_kubectl get nodes会显示异常名称且后续kubeadm join可能因证书 SANSubject Alternative Name不匹配而失败。正确做法# 设置符合 DNS 命名规范的 hostname小写字母、数字、短横线 sudo hostnamectl set-hostname k8s-master-01 # 更新 /etc/hosts确保 hostname 能解析到本机 IP echo $(hostname -I | awk {print $1}) $(hostname) | sudo tee -a /etc/hosts注意hostname -I输出多个 IP 时如 VMware NATHost-Only 双网卡务必用awk {print $1}取第一个通常是 NAT 网段 IP这是集群内部通信的主 IP。若取错节点间无法建立 TLS 连接。2.4 Docker 引擎版本锁与存储驱动的生死线kubeadm 官方支持的 Docker 版本范围是 18.06.1–18.09.9、19.03.x。CentOS 7 默认仓库中的docker-ce-20.10.x会导致kubelet启动失败报错cgroup driver: systemd is different from docker (cgroupfs)。这不是配置问题而是 Docker 20.10 默认使用systemdcgroup 驱动而旧版 kubelet 编译时绑定的是cgroupfs。解决方案是降级并锁定 Docker 版本# 清理旧版 sudo yum remove -y docker docker-client docker-client-latest docker-common docker-latest docker-latest-logrotate docker-logrotate docker-engine # 安装指定版本以 18.09.9 为例 sudo yum install -y yum-utils sudo yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo sudo yum install -y docker-ce-18.09.9 docker-ce-cli-18.09.9 containerd.io # 锁定版本防止自动升级 sudo yum install -y yum-plugin-versionlock sudo yum versionlock docker-ce-18.09.9 docker-ce-cli-18.09.9 containerd.io存储驱动storage driver同样重要。Docker 默认的overlay2在 CentOS 7 的 ext4 文件系统上表现良好但若/var/lib/docker所在分区是 XFS必须启用d_typetrue否则容器镜像层无法正确构建。验证命令xfs_info /var/lib/docker | grep ftype # 输出应为 ftype1否则需重新格式化分区2.5 kubelet 配置绕过 systemd 与 cgroup 的经典冲突cgroup driver不匹配是最常见的kubelet启动失败原因。错误日志明确指出cgroup driver: systemd is different from docker (cgroupfs)但直接修改 Docker 配置风险高可能影响其他服务。更稳妥的做法是统一 kubelet 使用systemd驱动# 创建 kubelet 配置目录 sudo mkdir -p /var/lib/kubelet/config.yaml # 生成默认配置并修改 cgroupDriver sudo kubeadm config print init-defaults kubeadm-init.yaml # 编辑 kubeadm-init.yaml找到 nodeRegistration.criSocket 和 cgroupDriver # 将 cgroupDriver: cgroupfs 改为 cgroupDriver: systemd # 或者直接写入 systemd 配置推荐更直观 echo KUBELET_EXTRA_ARGS--cgroup-driversystemd | sudo tee /etc/sysconfig/kubelet此配置通过/etc/sysconfig/kubelet注入比修改kubeadm init的 YAML 更可靠因为它在 kubelet 服务启动时即生效不受 kubeadm 初始化流程影响。2.6 防火墙与 SELinux安全策略的“白名单”式放行CentOS 7 默认启用 firewalld 和 SELinux。kubeadm 不要求你关闭它们而是要求你精确放行端口与上下文。粗暴执行systemctl disable firewalld setenforce 0是新手常见错误它让集群暴露在未授权访问风险中且在生产环境完全不可接受。firewalld 白名单规则针对 master 节点# 开放 kubeadm 必需端口 sudo firewall-cmd --permanent --add-port6443/tcp # Kubernetes API server sudo firewall-cmd --permanent --add-port2379-2380/tcp # etcd server client API sudo firewall-cmd --permanent --add-port10250/tcp # Kubelet API sudo firewall-cmd --permanent --add-port10251/tcp # kube-scheduler sudo firewall-cmd --permanent --add-port10252/tcp # kube-controller-manager sudo firewall-cmd --permanent --add-port10255/tcp # Read-only Kubelet API (legacy) # 重启 firewalld 生效 sudo firewall-cmd --reloadSELinux 上下文修正关键# kubelet 需要访问 /var/lib/kubelet/pki/ 下的证书但默认 SELinux 策略禁止 sudo semanage fcontext -a -t container_file_t /var/lib/kubelet/pki(/.*)? sudo restorecon -R /var/lib/kubelet/pki/ # 允许 kubelet 网络连接 sudo setsebool -P container_manage_cgroup 1注意semanage命令需要policycoreutils-python包Minimal 镜像中默认不安装需提前yum install -y policycoreutils-python。2.7 网络插件前置CNI 的“占位符”与 Calico 的轻量选择kubeadm init 完成后节点状态是NotReady这是正常现象——因为没有 CNIContainer Network Interface插件Pod 无法获得 IP 地址。但很多人等到kubeadm init成功后再去装 Calico/Flannel结果发现kubectl apply -f https://docs.projectcalico.org/manifests/calico.yaml失败报错no matches for kind Installation in version operator.tigera.io/v1。这是因为 Calico 新版v3.22使用 Operator 模式而 kubeadm 初始化的集群默认没有安装 CRD。解决方案是在kubeadm init前先准备好 CNI 插件的“最小可行 Manifest”。对于 CentOS 7 环境我推荐 Calico v3.21Operator-free纯 YAML# 下载并修改 calico.yaml适配 CentOS 7 内核 curl https://docs.projectcalico.org/v3.21/manifests/calico.yaml -O # 修改 CALICO_IPV4POOL_CIDR 为与 kubeadm init --pod-network-cidr 一致的网段 sed -i s/192.168.0.0\/16/10.244.0.0\/16/g calico.yaml # 修改 nodeSelector确保只在 Linux 节点部署避免误部署到 Windows 节点 sed -i /nodeSelector:/a\ kubernetes.io/os: linux calico.yaml这个calico.yaml就是你的 CNI “占位符”它将在kubeadm init后立即部署避免节点长时间处于NotReady状态。3. kubeadm init 执行从预检失败到 control plane 就绪的完整诊断链kubeadm init不是一个黑盒命令它是一套由 23 个独立检查项组成的启动协议。当你看到[preflight] Running pre-flight checks卡住或报错时不要急于 Google 错误信息而应按以下四步法进行结构化诊断。这是我处理过 137 个不同环境故障后总结出的通用路径。3.1 预检失败的黄金四步法定位、隔离、验证、修复第一步定位失败项kubeadm init的错误输出通常很简洁如[ERROR FileContent--proc-sys-net-bridge-bridge-nf-call-iptables]。这个字符串就是失败项的 ID。kubeadm 的所有预检项 ID 都定义在源码cmd/kubeadm/app/preflight/checks.go中但你无需读源码。只需记住ID 中的FileContent--表示检查某个文件内容FileExisting--表示检查文件是否存在SystemVerification--表示检查系统状态。第二步隔离检查逻辑以FileContent--proc-sys-net-bridge-bridge-nf-call-iptables为例它实际执行的检查是// 伪代码逻辑 content, _ : ioutil.ReadFile(/proc/sys/net/bridge/bridge-nf-call-iptables) if string(content) ! 1\n { return error(does not exist or content is not 1) }所以手动验证命令就是cat /proc/sys/net/bridge/bridge-nf-call-iptables 2/dev/null || echo NOT EXIST # 如果输出 NOT EXIST则说明 br_netfilter 模块未加载 # 如果输出 0则说明 sysctl 参数未设置第三步验证依赖条件每个预检项都有前置依赖。例如FileContent--proc-sys-net-bridge-bridge-nf-call-iptables依赖br_netfilter模块已加载lsmod | grep br_netfilter/proc/sys/net/bridge/目录存在由br_netfilter模块创建net.bridge.bridge-nf-call-iptables 1已写入 sysctl第四步修复并重试修复后不要直接重跑kubeadm init它会因 etcd 数据残留而失败。正确做法是# 清理上次失败的残留 sudo kubeadm reset -f sudo rm -rf /etc/kubernetes /var/lib/etcd /var/lib/kubelet/pki # 重新加载模块和 sysctl sudo modprobe br_netfilter sudo sysctl -p /etc/sysctl.d/k8s.conf # 再次运行 init sudo kubeadm init --pod-network-cidr10.244.0.0/163.2 常见预检失败项详解与修复方案下表列出 CentOS 7 环境中最常触发的 7 个预检失败项及其精准修复命令预检项 ID失败原因手动验证命令修复命令FileExisting--usr-bin-kubeletkubelet二进制不存在或权限不足ls -l /usr/bin/kubeletsudo yum install -y kubelet-1.20.15-0; sudo systemctl enable kubeletFileExisting--usr-bin-kubeadmkubeadm未安装或版本不匹配kubeadm versionsudo yum install -y kubeadm-1.20.15-0FileExisting--usr-bin-kubectlkubectl未安装which kubectlsudo yum install -y kubectl-1.20.15-0FileContent--proc-sys-net-ipv4-ip_forwardIP 转发未启用cat /proc/sys/net/ipv4/ip_forwardecho net.ipv4.ip_forward 1 /etc/sysctl.d/k8s.conf; sudo sysctl -pPort-1025010250 端口被占用常被旧版 kubelet 占用sudo ss -tuln | grep :10250sudo pkill -f kubelet; sudo systemctl stop kubeletSwapswap 未关闭swapon --showsudo swapoff -a; sudo sed -i / swap / s/^/#/ /etc/fstabSystemVerification内核版本过低3.10.0-1160或 cgroup 驱动不匹配uname -r; cat /var/lib/kubelet/config.yaml | grep cgroupDriver升级内核或配置KUBELET_EXTRA_ARGS--cgroup-driversystemd提示kubeadm init --ignore-preflight-errorsall是危险的“跳过所有检查”开关仅用于调试绝不可用于生产环境。它会掩盖真实问题导致集群后续出现难以追踪的诡异故障。3.3 init 过程中的关键阶段与日志解读kubeadm init的输出分为 5 个逻辑阶段每个阶段失败都有特定日志特征[preflight]系统预检。失败表现为[ERROR xxx]日志在终端直接输出。[certificates]生成 TLS 证书。失败时journalctl -u kubelet会显示x509: certificate signed by unknown authority原因是/etc/kubernetes/pki/ca.crt未生成或损坏。[kubeconfig]生成 kubeconfig 文件。失败时~/.kube/config为空或权限错误应为600。[control-plane]启动控制平面静态 Pod。失败时kubectl get pods -n kube-system显示Pending或CrashLoopBackOffkubectl describe pod pod-name -n kube-system显示ImagePullBackOff镜像拉取失败或CreateContainerConfigError配置错误。[etcd]启动本地 etcd。失败时journalctl -u etcd显示etcdserver: request timed out通常是磁盘 I/O 过慢或内存不足。最关键的诊断命令是# 实时跟踪 kubelet 日志init 过程中最重要的观察窗口 sudo journalctl -u kubelet -f # 查看所有 kube-system Pod 状态 kubectl get pods -n kube-system -o wide # 查看具体 Pod 的详细事件比 describe 更底层 kubectl get events -n kube-system --sort-by.lastTimestamp3.4 control plane 就绪后的“三分钟验证清单”kubeadm init成功输出Your Kubernetes control-plane has initialized successfully!后不要急着kubectl get nodes。请按此顺序验证验证 kubeconfig 可用性export KUBECONFIG/etc/kubernetes/admin.conf kubectl version --short # 应输出 Client Server 版本验证控制平面组件健康kubectl get componentstatuses # 所有 STATUS 应为 Healthy # 若为 Unknown检查 apiserver 是否监听 6443 端口sudo ss -tuln | grep :6443验证 etcd 健康# 进入 etcd 容器静态 Pod sudo crictl ps \| grep etcd \| awk {print $1} \| xargs sudo crictl exec -it /bin/sh # 在 etcd 容器内执行 ETCDCTL_API3 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部署 CNI 并验证节点状态kubectl apply -f calico.yaml # 等待 2-3 分钟执行 kubectl get nodes # 状态应变为 Ready kubectl get pods -n kube-system # calico-node Pod 应为 Running这“三分钟”不是等待而是主动验证。任何一步失败都意味着集群尚未真正就绪。4. worker 节点加入从kubeadm join到Ready状态的深度排障master 节点就绪后kubeadm join命令看似简单但 worker 节点的加入失败率远高于 init。因为join过程涉及 master 与 worker 的双向 TLS 认证、网络连通性、kubelet 配置一致性等多重因素。以下是我在 23 个不同网络拓扑VMware NAT、Host-Only、桥接、物理机直连中总结出的排障框架。4.1 join 命令的构成与各参数含义kubeadm join命令由三部分组成缺一不可kubeadm join 192.168.10.10:6443 \ --token abcdef.0123456789abcdef \ --discovery-token-ca-cert-hash sha256:1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890API Server 地址 (192.168.10.10:6443)必须是 master 节点上kubectl get nodes -o wide显示的INTERNAL-IP且该 IP 必须能被 worker 节点路由。在 VMware NAT 模式下此 IP 通常是192.168.10.10NAT 网段而非192.168.1.10Host-Only 网段。Token (abcdef.0123456789abcdef)有效期 24 小时。过期后需在 master 上执行kubeadm token create生成新 token。CA 证书哈希 (sha256:...)用于验证 master 的 CA 证书真实性。可通过openssl x509 -pubkey -in /etc/kubernetes/pki/ca.crt | openssl rsa -pubin -outform der 2/dev/null | openssl dgst -sha256 | sed s/^.* //在 master 上重新计算。提示kubeadm token create --print-join-command可生成完整的 join 命令避免手动拼写错误。4.2 worker 节点环境准备与 master 的严格对齐worker 节点的环境准备必须与 master 节点完全一致包括内核模块与 sysctlbr_netfilter、ip_vs等模块必须加载net.bridge.bridge-nf-call-iptables 1必须设置。Docker 版本必须与 master 完全相同如18.09.9否则kubelet无法与 Docker 通信。kubelet 配置KUBELET_EXTRA_ARGS--cgroup-driversystemd必须设置且与 master 一致。时间同步chronyd必须启用且与 master 的时间偏差 1 秒。差异哪怕只有 0.5 秒kubeadm join也会在[discovery] Trying to connect to API Server阶段超时日志显示x509: certificate has expired or is not yet valid。4.3 join 失败的三大典型场景与根因分析场景一[discovery] Failed to request cluster-info发现失败现象kubeadm join卡在[discovery] Trying to connect to API Server约 1 分钟后报错failed to request cluster-info。根因分析网络层worker 无法 ping 通 master 的192.168.10.10或telnet 192.168.10.10 6443失败。防火墙层master 的 firewalld 未开放6443/tcp或 worker 的 firewalld 阻止了出站连接。证书层master 的ca.crt证书已更新但 join 命令中的--discovery-token-ca-cert-hash未同步。诊断命令# 在 worker 上测试连通性 ping -c 3 192.168.10.10 nc -zv 192.168.10.10 6443 # 在 master 上检查防火墙 sudo firewall-cmd --list-ports | grep 6443 # 在 master 上验证证书哈希 openssl x509 -pubkey -in /etc/kubernetes/pki/ca.crt | openssl rsa -pubin -outform der 2/dev/null | openssl dgst -sha256 | sed s/^.* //场景二[kubelet-check] The HTTP call equal to curl -sSL http://localhost:10248/healthz failedkubelet 健康检查失败现象kubeadm join成功连接 master但在[kubelet-check] Initial timeout of 40s passed后失败。根因分析kubelet 未启动sudo systemctl status kubelet显示inactive (dead)。kubelet 配置错误/etc/sysconfig/kubelet中的--cgroup-driver与 Docker 不匹配。端口冲突10248端口被其他进程占用如旧版 kubelet。诊断命令# 检查 kubelet 状态 sudo systemctl status kubelet # 检查 10248 端口占用 sudo ss -tuln | grep :10248 # 检查 kubelet 日志 sudo journalctl -u kubelet -n 100 -f场景三节点加入后状态为NotReady网络插件未生效现象kubectl get nodes显示节点STATUS为NotReadykubectl get pods -n kube-system中calico-node-xxxxxPod 状态为Init:0/3或CrashLoopBackOff。根因分析CNI 配置错误calico.yaml中的CALICO_IPV4POOL_CIDR与kubeadm init --pod-network-cidr不一致。内核模块缺失worker 节点未加载xt_set模块Calico 依赖lsmod | grep xt_set无输出。网络策略冲突firewalld 或 iptables 规则阻止了calico-nodePod 与 master 的通信。诊断命令# 查看 calico-node Pod 详情 kubectl describe pod -n kube-system -l k8s-appcalico-node # 查看 calico-node 容器日志 kubectl logs -n kube-system -l k8s-appcalico-node -c calico-node # 在 worker 节点上检查 xt_set 模块 sudo modprobe xt_set echo xt_set | sudo tee -a /etc/modules-load.d/k8s.conf4.4 多节点集群的网络连通性终极验证当所有节点都显示Ready后执行以下验证确保集群网络真正打通# 1. 创建一个测试 Pod指定运行在 worker 节点 kubectl run nginx-test --imagenginx --replicas1 --overrides{spec:{nodeSelector:{kubernetes.io/os:linux}}} # 2. 获取 Pod IP 和所在节点 kubectl get pods -o wide # 3. 从 master 节点 curl 测试 Pod IP验证 ClusterIP 网络 kubectl get pod nginx-test -o jsonpath{.status.podIP} # 假设输出 10.244.1.2则在 master 上执行 curl -I 10.244.1.2 # 4. 从 worker 节点 curl 测试另一个 worker 上的 Pod IP验证跨节点网络 # 在 worker1 上执行目标为 worker2 的 Pod IP curl -I 10.244.2.3 # 5. 验证 DNS 解析CoreDNS 必须正常工作 kubectl run -it --rm