
1. 项目概述为什么“配置master节点”是K8S入门真正的分水岭刚接触Kubernetes的新手常有个错觉装完kubectl、kubeadm、kubelet跑个kubeadm init就等于“搞定了master”。我带过十几期K8S实操训练营几乎每期都有学员卡在这一步——命令执行成功了但kubectl get nodes永远显示NotReady或者etcd集群起不来API Server监听端口根本没开。问题不在于命令输错了而在于对“配置master节点”这五个字的理解太浅它不是一次性的初始化动作而是一整套网络拓扑确认、组件依赖校验、安全上下文设定、状态持久化保障的闭环操作。你配置的不是一个节点而是整个集群的“神经中枢”和“决策大脑”。这个环节一旦出偏差后续所有worker节点加入、Pod调度、Service暴露都会像多米诺骨牌一样接连失效。所以标题里特意强调“配置”而非“安装”就是提醒你这里要动的是逻辑不是文件要调的是关系不是参数。适合谁来学如果你已经能用Docker跑起Nginx容器但看到kubeadm init --pod-network-cidr10.244.0.0/16这种命令时会下意识去查CIDR是什么、为什么必须指定、不指定会怎样——那你就是这个内容最该盯住的人。它不讲抽象概念只拆解你敲下回车后系统到底在做什么、哪些文件被改了、哪些进程被启了、哪些端口被占了、哪些证书被生成了。没有PPT式原理图只有你SSH进机器后能立刻验证的现场痕迹。2. 配置思路拆解为什么必须按“环境准备→组件初始化→网络插件→状态验证”四步走2.1 不是顺序问题是依赖链断裂风险很多教程把kubeadm init放在第一步结果学员在虚拟机里执行完发现kubectl get componentstatuses返回红色API Server状态为Unknown。这不是kubeadm的问题而是跳过了前置依赖的显性确认。K8S master节点本质是四个核心组件的协同体kube-apiserver入口网关、etcd唯一数据源、kube-controller-manager集群状态调节器、kube-schedulerPod分配裁判。它们之间存在强依赖关系apiserver必须连上etcd才能启动controller-manager必须连上apiserver才能同步资源状态scheduler同样依赖apiserver获取Node和Pod信息。如果直接运行initkubeadm会尝试自动拉起所有组件但一旦某一个环节失败比如etcd监听地址配置错误、防火墙拦截6443端口、swap未关闭整个流程就会静默失败只给你一行“[init] Using Kubernetes version: v1.28.2”这样的安慰剂日志。所以我的实操路径强制拆成四步每步都做“可验证输出”环境准备不是简单执行swapoff -a而是用systemctl status kubelet确认服务已启用但未运行用cat /proc/sys/net/bridge/bridge-nf-call-iptables确认内核模块已加载用iptables -L -t nat | grep KUBE确认iptables规则链空——这些才是真实环境就绪的证据组件初始化kubeadm init不是黑盒命令它实际做了三件事生成TLS证书存于/etc/kubernetes/pki/、写入静态Pod清单/etc/kubernetes/manifests/、初始化etcd数据目录/var/lib/etcd。我会在init前手动检查这些路径是否存在、权限是否正确网络插件Calico/Flannel不是“装上就行”而是必须确认其DaemonSet是否真正调度到master节点因为master默认有NoSchedule污点且CNI配置文件/etc/cni/net.d/10-calico.conflist中的IP池与init时指定的--pod-network-cidr完全一致状态验证不用kubectl get nodes看一眼就结束而是分层验证先curl -k https://localhost:6443/healthz确认API Server存活再kubectl get cs看各组件健康状态最后kubectl get pods -A看kube-system命名空间下所有Pod是否Running且Ready为1/1。提示kubeadm init默认使用10.96.0.0/12作为Service CIDR但如果你的宿主机网段恰好是10.96.x.x比如公司内网就会导致Service IP冲突。这是我在某次企业内训中踩过的坑——集群能起来但CoreDNS Pod一直CrashLoopBackOff排查三天才发现是Service IP和物理网段重叠。解决方案是在init时显式指定--service-cidr10.97.0.0/16并同步更新kube-proxy的configmap。2.2 为什么拒绝“一键脚本”坚持手动逐条执行网上流传着大量“5分钟部署K8S集群”的Shell脚本把swapoff、modprobe、kubeadm init全塞进一个for循环。我试过三次每次都在不同环境翻车第一次在CentOS 7上因firewalld未停用导致6443端口被拦第二次在Ubuntu 22.04上因cloud-init自动修改了/etc/hosts导致etcd集群成员解析失败第三次在ARM64架构树莓派上脚本硬编码了amd64镜像地址。根本原因在于kubeadm init的执行结果高度依赖底层OS状态而脚本无法感知这些隐性状态。比如kubeadm要求hostname不能含下划线但脚本不会帮你检查它要求/etc/hosts中必须有127.0.0.1对应当前hostname的映射但脚本不会验证这一行是否存在。所以我坚持手动执行每条命令后必加验证# 手动执行非脚本 sudo swapoff -a sudo sed -i / swap / s/^/#/ /etc/fstab # 永久禁用swap # 验证free -h 应显示swap total为0 free -h | grep Swap # 加载内核模块 sudo modprobe br_netfilter echo br_netfilter | sudo tee -a /etc/modules # 验证lsmod | grep br_netfilter 应有输出 lsmod | grep br_netfilter # 配置sysctl sudo sysctl -w net.bridge.bridge-nf-call-iptables1 sudo sysctl -w net.ipv4.ip_forward1 # 验证sysctl net.bridge.bridge-nf-call-iptables 应返回1 sysctl net.bridge.bridge-nf-call-iptables这种“执行-验证-记录”的节奏看似慢但能让你在出错时精准定位到哪一步断了。比如当kubectl get nodes返回No resources found时你立刻知道问题出在第三步网络插件或第四步状态验证而不是对着几百行脚本日志大海捞针。2.3 安全配置不是选修课是master节点的生存底线新手最容易忽略的是master节点的安全上下文。kubeadm init默认生成的证书有效期只有1年且CA证书私钥/etc/kubernetes/pki/ca.key权限为600但很多教程教大家chmod 755去“方便复制”这等于把集群根证书明文暴露。更危险的是init默认不启用审计日志audit log所有API调用包括删除namespace、修改Secret都不留痕。我在某次故障复盘中发现一个误删Production namespace的操作竟找不到任何调用者记录——因为audit policy配置为空。所以我的配置清单里安全项是强制前置的证书续期策略在init前创建/etc/kubeadm/config.yaml明确指定certValiditycertValidity: 8760h即365天并设置rotateCertificates: true开启自动轮换审计日志启用通过--audit-policy-file参数指向自定义策略文件至少包含level: RequestResponse对敏感操作全量记录RBAC最小权限绝不使用system:masters组直接授权给开发账号而是为每个团队创建独立ServiceAccount绑定仅含必要verbsget/list/watch的Role。这些配置不增加部署时间但决定了集群上线后的可追溯性和抗误操作能力。记住master节点不是测试玩具它是生产环境的单点信任源它的配置深度直接决定整个集群的可信半径。3. 核心细节解析从kubeadm init命令到系统级变更的完整映射3.1 kubeadm init命令参数的物理意义与取舍逻辑kubeadm init不是魔法它背后是清晰的参数-行为映射。我们以最常用的命令为例kubeadm init \ --kubernetes-versionv1.28.2 \ --pod-network-cidr10.244.0.0/16 \ --service-cidr10.96.0.0/12 \ --cri-socketunix:///var/run/containerd/containerd.sock \ --upload-certs \ --ignore-preflight-errorsSwap逐条拆解其系统级影响--kubernetes-versionv1.28.2这不是单纯指定版本号。kubeadm会根据此值从k8s.gcr.io仓库拉取对应版本的control plane镜像kube-apiserver:v1.28.2、kube-controller-manager:v1.28.2等并写入/etc/kubernetes/manifests/下的静态Pod清单。若网络无法访问gcr.io需提前用docker pull拉取并tag为本地镜像否则init会卡在镜像拉取阶段超时--pod-network-cidr10.244.0.0/16此参数有两个关键作用。第一它写入kube-controller-manager的启动参数--cluster-cidr10.244.0.0/16告诉控制器为每个Node分配的Pod IP范围第二它成为后续网络插件如Calico的配置依据Calico的IPPool资源必须与此CIDR一致否则Pod间无法通信。我曾见过学员将此值设为192.168.0.0/16结果Calico启动后报错“failed to allocate IP from pool”因为Calico默认只支持RFC1918私有地址段而192.168.0.0/16虽属私有但Calico的IPAM模块有额外校验--service-cidr10.96.0.0/12这是Service ClusterIP的分配池。注意其掩码长度/12比Pod CIDR/16大意味着Service IP数量更多约104万个。若设得太小如/16当集群Service数量超65535时新Service创建会失败报错“failed to allocate cluster IP”。这个值必须在init时确定后期无法动态扩容--cri-socketunix:///var/run/containerd/containerd.sock明确指定容器运行时接口。K8S 1.24已移除dockershim必须显式告知kubeadm使用containerd还是CRI-O。若宿主机装了Docker但未配置containerd socketinit会报错“failed to run Kubelet: unable to load bootstrap kubeconfig”。此时需确认containerd服务状态sudo systemctl status containerd--upload-certs启用证书分发功能。它让kubeadm在init时生成一个加密的证书密钥kubeadm certs certificate-key并上传至etcd。后续添加master节点时其他节点可通过此密钥自动获取CA证书无需手动拷贝pki目录。这是高可用集群的基石但密钥本身需妥善保管泄露等于集群根证书泄露--ignore-preflight-errorsSwap跳过swap检查。虽然方便但强烈不建议在生产环境使用。K8S官方文档明确指出“Enabling swap violates the assumptions Kubernetes makes about memory management.” 实测中开启swap会导致kubelet内存压力判断失灵Node状态频繁在Ready/NotReady间切换。注意kubeadm init执行后会在当前目录生成两个关键文件admin.conf管理员kubeconfig和join-command.txtworker节点加入命令。很多人直接mv admin.conf ~/.kube/config就完事却忽略了admin.conf中的server字段是https://10.0.2.15:6443Vagrant虚拟机默认IP。若master节点IP变更如重启后DHCP分配新IP此配置立即失效。正确做法是编辑admin.conf将server字段改为master节点稳定IP如192.168.1.100或域名k8s-master.internal。3.2 /etc/kubernetes/manifests/目录下的静态Pod清单详解kubeadm init的核心产物之一是向/etc/kubernetes/manifests/目录写入四个YAML文件kube-apiserver.yaml、kube-controller-manager.yaml、kube-scheduler.yaml、etcd.yaml。这些不是普通配置而是Kubelet监控的“静态Pod定义”Kubelet会持续检查这些文件一旦发现变化或Pod退出立即拉起新实例。理解它们的结构是诊断master组件故障的关键kube-apiserver.yaml关键字段解析spec: containers: - command: - kube-apiserver - --advertise-address192.168.1.100 # 对外广播的IP必须是节点可达地址 - --allow-privilegedtrue - --authorization-modeNode,RBAC # 授权模式Node用于kubelet认证RBAC用于用户权限 - --client-ca-file/etc/kubernetes/pki/ca.crt # 客户端证书颁发机构 - --enable-admission-pluginsNodeRestriction,ResourceQuota # 准入控制插件 - --etcd-cafile/etc/kubernetes/pki/etcd/ca.crt # etcd CA证书 - --etcd-certfile/etc/kubernetes/pki/apiserver-etcd-client.crt # apiserver连接etcd的客户端证书 - --etcd-keyfile/etc/kubernetes/pki/apiserver-etcd-client.key # 对应私钥 - --etcd-servershttps://127.0.0.1:2379 # etcd服务地址必须与etcd.yaml中--listen-peer-urls一致 - --insecure-port0 # 禁用HTTP非安全端口 - --kubelet-client-certificate/etc/kubernetes/pki/apiserver-kubelet-client.crt # 认证kubelet的证书 - --kubelet-client-key/etc/kubernetes/pki/apiserver-kubelet-client.key - --proxy-client-cert-file/etc/kubernetes/pki/front-proxy-client.crt # 聚合API代理证书 - --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 # 前置代理CA - --requestheader-extra-headers-prefixX-Remote-Extra- # 请求头前缀 - --requestheader-group-headersX-Remote-Group # 组信息头 - --requestheader-username-headersX-Remote-User # 用户名头 - --secure-port6443 # HTTPS安全端口 - --service-account-issuerhttps://kubernetes.default.svc.cluster.local # ServiceAccount签发者 - --service-account-key-file/etc/kubernetes/pki/sa.pub # ServiceAccount公钥 - --service-account-signing-key-file/etc/kubernetes/pki/sa.key # ServiceAccount私钥 - --service-cluster-ip-range10.96.0.0/12 # Service IP池必须与init参数一致 - --tls-cert-file/etc/kubernetes/pki/apiserver.crt # API Server TLS证书 - --tls-private-key-file/etc/kubernetes/pki/apiserver.key # 对应私钥关键故障点排查若--advertise-address设为127.0.0.1外部kubectl将无法连接报错“connection refused”若--etcd-servers地址与etcd.yaml中--listen-client-urls不匹配apiserver启动失败日志出现“context deadline exceeded”若--service-cluster-ip-range与init时参数不符CoreDNS Pod会因无法分配ClusterIP而Pending。etcd.yaml关键字段解析spec: containers: - command: - etcd - --advertise-client-urlshttps://192.168.1.100:2379 # 对外提供服务的URL - --cert-file/etc/kubernetes/pki/etcd/server.crt # etcd服务端证书 - --client-cert-authtrue # 启用客户端证书认证 - --data-dir/var/lib/etcd # 数据存储目录 - --initial-advertise-peer-urlshttps://192.168.1.100:2380 # 集群内peer通信URL - --initial-clusterk8s-masterhttps://192.168.1.100:2380 # 初始集群成员 - --initial-cluster-statenew # 新集群状态 - --key-file/etc/kubernetes/pki/etcd/server.key # 服务端私钥 - --listen-client-urlshttps://127.0.0.1:2379,https://192.168.1.100:2379 # 监听地址必须包含127.0.0.1供本地apiserver连接 - --listen-peer-urlshttps://192.168.1.100:2380 # peer监听地址 - --namek8s-master # 本节点在etcd集群中的名称 - --peer-cert-file/etc/kubernetes/pki/etcd/peer.crt # peer通信证书 - --peer-client-cert-authtrue # peer间启用客户端证书认证 - --peer-key-file/etc/kubernetes/pki/etcd/peer.key # peer私钥 - --peer-trusted-ca-file/etc/kubernetes/pki/etcd/ca.crt # peer信任的CA - --snapshot-count10000 # 快照触发阈值 - --trusted-ca-file/etc/kubernetes/pki/etcd/ca.crt # 客户端信任的CA关键故障点排查--listen-client-urls若未包含https://127.0.0.1:2379apiserver将无法连接etcd报错“dial tcp 127.0.0.1:2379: connect: connection refused”--initial-advertise-peer-urls与--listen-peer-urls必须一致否则etcd集群无法形成--name必须全局唯一若多个master节点使用相同nameetcd集群会分裂。3.3 /etc/kubernetes/pki/证书体系的生成逻辑与生命周期管理kubeadm init生成的证书不是随机字符串而是遵循X.509标准的PKI体系每一类证书都有明确用途和信任链。理解其生成逻辑是解决“x509 certificate signed by unknown authority”这类经典错误的前提。证书生成流程简化版根CA生成kubeadm首先创建ca.crtCA证书和ca.keyCA私钥存于/etc/kubernetes/pki/。这是整个集群的信任锚点etcd CA生成独立创建etcd/ca.crt和etcd/ca.key专用于etcd组件间通信与主CA隔离提升安全性Front Proxy CA生成创建front-proxy-ca.crt和front-proxy-ca.key用于聚合APIAggregated API的认证如metrics-server服务端证书签发apiserver.crt由主CA签发Subject为CNkube-apiserverSANSubject Alternative Name包含所有可能访问API Server的地址127.0.0.1、192.168.1.100、kubernetes、kubernetes.default、kubernetes.default.svc、kubernetes.default.svc.cluster.localetcd/server.crt由etcd CA签发SAN包含127.0.0.1和192.168.1.100客户端证书签发apiserver-kubelet-client.crt由主CA签发Subject为CNsystem:kube-apiserver用于apiserver反向认证kubeletfront-proxy-client.crt由Front Proxy CA签发Subject为CNfront-proxy-client用于聚合API客户端认证。证书有效期与续期默认情况下所有证书有效期为1年8760小时。但kubeadm提供了续期工具# 查看证书到期时间 kubeadm certs check-expiration # 续期所有证书需在master节点执行 kubeadm certs renew all # 续期特定证书如apiserver证书 kubeadm certs renew apiserver # 注意续期后必须重启相关组件如kube-apiserver静态Pod sudo systemctl restart kubelet实操心得我在生产环境中发现kubeadm certs renew all命令会重新生成ca.crt和ca.key但这会导致所有依赖旧CA的客户端如worker节点的kubelet认证失败。因此生产环境续期必须使用--use-api参数通过API Server在线续期避免CA轮换# 安全续期方式推荐 kubeadm certs renew all --use-api此命令通过API Server的证书续期API完成只更新即将过期的证书不触碰CA确保集群平滑过渡。4. 实操过程与核心环节实现从零开始配置master节点的完整记录4.1 环境准备在Ubuntu 22.04上完成所有前置检查我使用的环境是VirtualBox Vagrant配置如下vagrantfileVagrant.configure(2) do |config| config.vm.box ubuntu/jammy64 config.vm.network private_network, ip: 192.168.1.100 config.vm.provider virtualbox do |vb| vb.memory 4096 vb.cpus 2 end endStep 1基础系统配置# 登录Vagrant虚拟机 vagrant ssh # 更新系统并安装必要工具 sudo apt update sudo apt upgrade -y sudo apt install -y curl wget vim git gnupg2 software-properties-common # 关闭swap永久 sudo swapoff -a sudo sed -i / swap / s/^/#/ /etc/fstab # 验证swap已关闭 free -h | grep Swap # 输出应为Swap: 0B 0B 0B # 加载内核模块 sudo modprobe br_netfilter sudo modprobe overlay echo br_netfilter | sudo tee -a /etc/modules echo overlay | sudo tee -a /etc/modules # 配置sysctl参数 sudo sysctl -w net.bridge.bridge-nf-call-iptables1 sudo sysctl -w net.bridge.bridge-nf-call-ip6tables1 sudo sysctl -w net.ipv4.ip_forward1 # 持久化 sudo tee /etc/sysctl.d/kubernetes.conf EOF net.bridge.bridge-nf-call-iptables 1 net.bridge.bridge-nf-call-ip6tables 1 net.ipv4.ip_forward 1 EOF sudo sysctl --system # 验证内核参数 sysctl net.bridge.bridge-nf-call-iptables net.ipv4.ip_forward # 应输出net.bridge.bridge-nf-call-iptables 1 和 net.ipv4.ip_forward 1Step 2安装容器运行时containerdK8S 1.24弃用Docker必须使用containerd# 安装containerd sudo apt install -y containerd # 生成默认配置 sudo mkdir -p /etc/containerd sudo containerd config default | sudo tee /etc/containerd/config.toml # 修改cgroup驱动为systemd与kubelet保持一致 sudo sed -i s/SystemdCgroup false/SystemdCgroup true/g /etc/containerd/config.toml # 启动并启用containerd sudo systemctl restart containerd sudo systemctl enable containerd # 验证 sudo systemctl status containerd | grep Active # 应显示 active (running)Step 3安装kubeadm、kubelet、kubectl# 添加K8S APT仓库 curl -s https://packages.cloud.google.com/apt/doc/apt-key.gpg | sudo apt-key add - echo deb https://apt.kubernetes.io/ kubernetes-xenial main | sudo tee /etc/apt/sources.list.d/kubernetes.list # 安装指定版本与后续init一致 sudo apt update sudo apt install -y kubelet1.28.2-00 kubeadm1.28.2-00 kubectl1.28.2-00 # 锁定版本防止自动升级 sudo apt-mark hold kubelet kubeadm kubectl # 启用并启动kubelet此时不启动等待init sudo systemctl daemon-reload sudo systemctl enable kubelet sudo systemctl start kubelet # 验证kubelet状态应为inactive因无配置 sudo systemctl status kubelet | grep Active # 应显示 inactive (dead) 或 active (running) 但无panic日志4.2 初始化master节点执行kubeadm init并处理常见中断Step 4执行kubeadm init# 创建kubeadm配置文件推荐比命令行参数更可控 sudo tee /tmp/kubeadm-config.yaml EOF apiVersion: kubeadm.k8s.io/v1.28 kind: ClusterConfiguration kubernetesVersion: v1.28.2 controlPlaneEndpoint: 192.168.1.100:6443 networking: podSubnet: 10.244.0.0/16 serviceSubnet: 10.96.0.0/12 certificatesDir: /etc/kubernetes/pki clusterName: k8s-cluster --- apiVersion: kubeadm.k8s.io/v1.28 kind: InitConfiguration nodeRegistration: criSocket: unix:///var/run/containerd/containerd.sock taints: - key: node-role.kubernetes.io/control-plane effect: NoSchedule - key: node-role.kubernetes.io/master effect: NoSchedule --- apiVersion: kubelet.config.k8s.io/v1beta1 kind: KubeletConfiguration cgroupDriver: systemd EOF # 执行初始化耗时约2-3分钟 sudo kubeadm init --config /tmp/kubeadm-config.yaml --upload-certs # 预期输出关键行 # Your Kubernetes control-plane has initialized successfully! # To start using your cluster, you need to run the following as a regular user: # mkdir -p $HOME/.kube # sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config # sudo chown $(id -u):$(id -g) $HOME/.kube/config # You should now deploy a pod network to the cluster. # Run kubectl apply -f [podnetwork].yaml with one of the options listed at: # https://kubernetes.io/docs/concepts/cluster-administration/addons/ # Then you can join any number of worker nodes by running the following on each as root: # kubeadm join 192.168.1.100:6443 --token ... --discovery-token-ca-cert-hash ...Step 5配置kubectl并验证API Server# 创建kubeconfig目录 mkdir -p $HOME/.kube # 复制admin.conf注意必须用sudo cp因文件属root sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config # 修改权限重要否则kubectl报错permission denied sudo chown $(id -u):$(id -g) $HOME/.kube/config # 验证kubectl是否能连通API Server kubectl version --short # 应输出 Client Version 和 Server Version # 示例输出Client Version: v1.28.2, Server Version: v1.28.2 # 检查API Server健康状态 curl -k https://localhost:6443/healthz # 应返回 ok # 查看集群组件状态此时etcd、controller-manager、scheduler应为Healthy kubectl get componentstatuses # 输出应类似 # NAME STATUS MESSAGE ERROR # scheduler Healthy ok # controller-manager Healthy ok # etcd-0 Healthy {health:true}Step 6部署Calico网络插件选择Calico因其成熟度和对BGP的支持# 下载Calico manifest适配K8S 1.28 curl https://raw.githubusercontent.com/projectcalico/calico/v3.26.1/manifests/calico.yaml -O # 修改CALICO_IPV4POOL_CIDR以匹配kubeadm init的podSubnet sed -i s/192.168.0.0/10.244.0.0/g calico.yaml sed -i s|/16|/16|g calico.yaml # 确保CIDR正确 # 应用Calico kubectl apply -f calico.yaml # 监控Calico Pod启动需等待约1-2分钟 watch kubectl get pods -n kube-system -l k8s-appcalico-node # 当STATUS变为Running且READY为1/1时表示Calico节点已就绪Step 7验证master节点状态# 查看所有Pod应看到coredns、calico-node、kube-apiserver等Running kubectl get pods -A # 查看Nodes此时应只有一个master节点STATUS为NotReady因网络插件未完全生效 kubectl get nodes # 等待Calico完全就绪后再次检查通常1-2分钟后 kubectl get nodes -o wide # 预期输出 # NAME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIME # k8s-master Ready control-plane 5m v1.28.2 192.168.1.100 none Ubuntu 22.04.3 LTS 5.15.0-86-generic containerd://1.6.27 # 深度验证检查kube-system命名空间下所有Pod kubectl get pods -n kube-system # 关键Pod必须Running # coredns-xxxxx 1/1 Running 0 5m # calico-node-xxxxx 1/1 Running 0 3m # kube-apiserver-k8s-master 1/1 Running 0 5m # kube-controller-manager-k8s-master 1/1 Running 0 5m # kube-scheduler-k8s-master 1/1 Running 0 5m # etcd-k8s-master 1/1 Running 0 5m4.3 故障注入与修复模拟并解决三个典型问题问题1kubectl get nodes返回No resources found现象执行完kubeadm init和kubectl apply -f calico.yaml后kubectl get nodes无输出。排查思路这不是节点不存在而是kubelet未向API Server注册。原因通常是kubelet配置错误或网络插件未就绪。诊断步骤# 1. 检查kubelet服务状态 sudo systemctl status kubelet # 2. 查看kubelet日志关键 sudo journalctl -u kubelet -n 100 -f # 常见错误日志 # Failed to run kubelet failed to run Kubelet: unable to load bootstrap kubeconfig # 表明kubelet找不到bootstrap配置 # 3. 检查bootstrap配置文件 ls -l /etc/kubernetes/bootstrap-kubelet.conf # 若不存在说明kubeadm init未生成或被误删 # 4. 检查/var/lib/kubelet/config.yaml中staticPodPath是否指向正确目录 grep staticPodPath /var/lib/kubelet/config.yaml # 应输出staticPodPath: /etc/kubernetes/manifests解决方案重新生成bootstrap配置需在kubeadm init后执行# 重新生成bootstrap-kubelet.conf sudo kubeadm init phase kubeconfig kubelet --config /tmp/kubeadm-config.yaml # 重启kubelet sudo systemctl restart kubelet问题2CoreDNS Pod一直处于Pending状态现象kubectl get pods -n kube-system中coredns-xxx显示Pending。排查思路Pending通常意味着调度器无法为Pod找到合适的Node。原因可能是Node未Ready、资源不足、或Taints/Tolerations不匹配。诊断步骤# 1. 查看coredns Pod详细事件 kubectl describe pod -n kube-system -l k8s-appkube-dns # 关键事件行 # Events: # Type Reason Age From Message # ---- ------ ---- ---- ------- # Warning FailedScheduling 2m default-scheduler