1. 这不是教科书是我在三个真实生产环境里踩出来的K8s入门路径“K8s入门指南”这六个字我见过太多人把它当成一本说明书去读——翻完Pod、Service、Deployment的定义合上文档面对一个空集群还是不知道从哪下手。我自己第一次在某电商公司的测试环境里部署第一个应用时卡在kubelet无法注册节点上整整两天查日志像在解谜最后发现只是容器运行时没正确配置cgroup驱动。后来在某金融类SaaS项目里做CI/CD流水线集成又因为Ingress控制器版本和API组不匹配导致所有HTTP路由全部404回滚了六次才定位到是v1beta1被废弃后没同步更新CRD。这些不是理论漏洞是真实发生在我手上的、带着报错截图和凌晨三点咖啡渍的操作现场。你看到的这个标题“K8s入门指南核心概念、集群搭建与排错实战”它背后真正想说的其实是别从yaml文件开始学先搞懂控制平面和工作节点之间到底在“聊什么”别急着kubectl apply先确认etcd有没有写入权限、kube-apiserver能不能被kubelet连上别迷信一键脚本要亲手拆开kubeadm init每一步干了什么。这不是给面试突击者准备的速记卡片而是给即将接手第一个K8s集群的运维工程师、刚转岗的DevOps同学、或者需要把老系统迁上云原生架构的后端开发写的实操手册。它覆盖的是你打开终端后前72小时最可能遇到的断点证书过期、网络插件冲突、DNS解析失败、镜像拉取超时、资源配额拒绝调度……每一个问题我都附上了当时用的诊断命令、截取的关键日志片段、以及为什么选这个命令而不是别的——比如为什么用kubectl get events --sort-by.lastTimestamp而不是kubectl describe pod来看调度失败原因因为前者能暴露Scheduler根本没触发调度的底层事实。核心关键词“K8s入门”“集群搭建”“排错实战”不是并列关系而是递进链条概念理解不到位搭建必然出偏搭建过程跳过验证环节排错就变成大海捞针。所以这篇内容不会按“先讲概念→再教搭建→最后给案例”的教科书逻辑走而是以一个真实上线任务为锚点——比如“把一个Spring Boot订单服务部署到新集群并对外提供HTTPS访问”——所有概念只在它实际影响该任务推进时才展开所有命令只在它解决当前阻塞点时才出现。你现在看到的每一行字都对应着我某次深夜重启kube-apiserver前敲下的最后一行命令或是在某个客户现场白板上画给开发同事看的那张控制平面通信图。2. 内容整体设计与思路拆解为什么放弃“先学再做”选择“边做边建认知”2.1 拒绝概念先行从“调度失败”反推Control Plane组件职责传统教学路径总爱从“Kubernetes是一个开源的容器编排平台”开始接着列四大核心对象Pod/Service/Deployment/ConfigMap再讲声明式API。但现实是当你第一次执行kubectl create deployment nginx --imagenginx终端返回Error from server (NotFound): the server could not find the requested resource时你根本不在乎“声明式”是什么哲学概念你只想知道“我的命令为什么被拒了”。这时候强行灌输API Server和etcd的关系不如直接带你去看kubectl api-resources输出里有没有deployments.apps这一行再用curl -k https://localhost:6443/apis/apps/v1/deployments验证API组是否可用——概念必须长在具体错误上才有血肉。所以我把整个内容骨架倒过来搭以7个高频阻塞场景为纵轴节点NotReady、Pod Pending、Service不可达、Ingress 503、ConfigMap不生效、HPA不触发、etcd集群脑裂每个场景下再横向展开——当前现象对应的K8s内部哪个组件在“失语”比如Pending状态本质是Scheduler没生成Binding对象该组件依赖哪些前置条件Scheduler依赖kube-apiserver健康、etcd可写、Node对象存在且Ready验证这些条件的最小命令集kubectl get componentstatuses已废弃改用kubectl get cs或直接curl各组件健康端点修复后如何确认闭环不只是kubectl get nodes显示Ready还要kubectl run debug --imagebusybox --rm -it -- sh -c nslookup kubernetes.default验证DNS是否真通。这种设计让“核心概念”不再是名词解释而变成故障树里的节点标签。当你第三次因为FailedScheduling排查到node.kubernetes.io/unreachable污点时“Taint and Toleration”就自动刻进肌肉记忆了。2.2 集群搭建不选“一键脚本”坚持kubeadm手动分步现在网上90%的“K8s搭建教程”都在推kubeadm init --pod-network-cidr10.244.0.0/16加两行calico安装命令。这在实验室环境没问题但一旦放到企业内网你会立刻撞上三堵墙内网DNS服务器拦截了kubeadm自动生成的kubernetes.io/cluster/*证书SAN安全策略禁止节点间UDP 8472端口VXLAN默认端口导致Flannel无法跨主机通信容器运行时升级后cgroup驱动从cgroupfs切到systemd但kubeadm配置没同步kubelet启动即崩溃。所以我把集群搭建拆成五个不可跳过的手动阶段环境预检不只是free -h看内存而是lsmod | grep br_netfilter确认内核模块加载、sysctl net.bridge.bridge-nf-call-iptables验证iptables桥接、getenforce检查SELinux状态证书体系构建用kubeadm config print init-defaults kubeadm.yaml导出模板手动修改certificatesDir指向独立目录添加extraArgs: { feature-gates: RotateKubeletServerCertificatetrue }开启证书轮换Control Plane初始化禁用--upload-certs参数改用kubeadm init phase upload-certs --upload-certs分步上传确保etcd证书和API Server证书密钥分离管理CNI插件定制化安装不直接kubectl apply -f calico.yaml而是下载YAML后修改CALICO_IPV4POOL_CIDR匹配内网规划用kubectl set env daemonset/calico-node -n kube-system FELIX_IGNORELOOSERPFtrue关闭反向路径过滤Worker节点加入加固kubeadm join命令后追加--node-name$(hostname -s)强制指定节点名避免DNS变更导致节点标识混乱。每个步骤都附带“不这么做会怎样”的后果说明。比如跳过第2步证书定制三个月后所有节点kubelet证书过期整个集群将无法新增Pod——这不是假设是某车企私有云真实发生的事故。2.3 排错实战聚焦“可观测性基建”而非单点命令罗列很多排错指南止步于“kubectl describe pod看Events”“kubectl logs查容器日志”但这在微服务场景下完全失效。当一个订单服务调用支付服务超时你看到的可能是支付Pod的CrashLoopBackOff但根源可能是其依赖的Redis密码配置错误。如果只盯着Pod层面你会陷入“重启→再崩溃→再重启”的死循环。因此我把排错能力拆解为三层可观测性建设基础设施层用kubectl get nodes -o wide确认节点IP和容器运行时版本用ip link show查CNI虚拟网卡是否存在用ss -tuln | grep :10250验证kubelet监听端口K8s控制层用kubectl get events --all-namespaces --sort-by.lastTimestamp | tail -20抓最近事件流用kubectl get componentstatuses虽已弃用但仍有参考价值或curl -k https://localhost:6443/healthz直连API Server健康检查应用依赖层在Pod内执行curl -v http://payment-svc:8080/actuator/health验证服务连通性用nslookup payment-svc.default.svc.cluster.local确认CoreDNS解析路径用tcpdump -i any port 53 -w dns.pcap抓包分析DNS查询失败点。这种分层不是理论模型而是我处理某物流平台订单积压故障的标准动作序列。当时kubectl get pods显示所有Pod Running但业务监控告警持续最终在第三层用tcpdump发现CoreDNS Pod的53端口被安全组拦截而第一层kubectl get nodes显示一切正常——排错的本质是建立分层信任链每一层都必须用独立手段验证不能靠上层状态反推下层健康。3. 核心细节解析与实操要点那些文档里不会写的“脏活儿”3.1 Pod生命周期里的隐藏关卡Init Container不是可选项是必经闸门几乎所有K8s教程讲Init Container都停留在“用于初始化配置”的抽象描述但实际生产中它承担着比主容器更关键的准入控制职能。比如在某银行核心系统迁移中我们要求所有Pod必须通过三项检查才能启动主容器检查所在节点是否已打上envprod标签kubectl label nodes node-1 envprod验证Secret中数据库密码长度≥12位用awk {print length} /etc/secrets/db-password确认ConfigMap中的API网关地址能被curl通curl -f -s -o /dev/null http://gateway:8000/health。这些检查写在Init Container里一旦失败Pod状态直接卡在Init:0/1且不会产生任何主容器日志。很多人看到这个状态第一反应是删Pod重试结果重试十次还是卡住——因为你没意识到Init Container的退出码就是Pod的“准生证”。调试时必须用kubectl logs pod-name -c init-container-name单独查看而不是kubectl logs pod-name。更隐蔽的坑在于资源限制。Init Container共享Pod的requests/limits但它的内存峰值往往远高于主容器比如解压大体积配置包。某次我们给主容器设了512Mi内存limitInit Container解压时瞬间冲到800Mi直接OOMKilled导致Pod永远无法进入Running状态。解决方案是在Pod spec里显式为Init Container设置更高limitinitContainers: - name: config-init resources: limits: memory: 1Gi requests: memory: 512Mi提示Init Container的执行顺序严格遵循YAML中定义的顺序且前一个必须成功退出exit code 0才会启动下一个。不要试图用sleep 30模拟等待应该用until curl -f http://service:port/readyz; do sleep 2; done做真正的健康探针。3.2 Service背后的iptables与IPVS双面性为什么ClusterIP有时“通”有时“不通”Service的ClusterIP看似简单实则是K8s网络最易出幻觉的模块。新手常困惑“我kubectl get service看到CLUSTER-IP是10.96.0.1curl 10.96.0.1:80却超时但kubectl exec -it pod -- curl http://my-service:80却成功”。这背后是K8s Service实现机制的代际差异。在kube-proxy的iptables模式下ClusterIP只是一个虚拟IP所有流量通过iptables DNAT规则转发到Endpoint Pod。但iptables规则链有顺序如果某条自定义规则比如安全组插入的DROP规则挡在K8s规则之前ClusterIP就彻底失效。验证方法是# 查看K8s生成的iptables链 iptables -t nat -L KUBE-SERVICES | grep 10.96.0.1 # 检查规则是否在链首 iptables -t nat -S | head -20而IPVS模式则完全不同——它把Service IP注册为本地VIP用IPVS内核模块做负载均衡。这时curl 10.96.0.1:80能通但ip addr show却找不到这个IP因为它是内核态虚拟地址。某次我们在某政务云平台切换IPVS后监控系统用netstat -tuln | grep :80检测端口占用始终报告“未监听”差点误判Service异常。更致命的是混合模式陷阱。kubeadm默认启用iptables但某些CNI插件如Cilium会接管Service功能此时kube-proxy应设为--proxy-modenone。我们曾因未关闭kube-proxy导致Cilium和iptables规则双重DNAT请求被转发两次Endpoint Pod收到的源IP变成10.96.x.x而非真实客户端IP。注意kubectl get endpoints是唯一可信的Service连通性黄金指标。只要它显示非空Endpoint列表如10.244.1.3:8080就证明Service后端已注册若为空则问题一定出在Selector匹配或Pod状态上与iptables/IPVS无关。3.3 Ingress控制器的“隐形依赖”为什么Nginx Ingress突然返回503Ingress对象本身只是K8s API资源真正干活的是Ingress Controller如nginx-ingress-controller。但它的健康状态不体现在kubectl get ingress里而藏在Controller Pod的日志和配置同步状态中。某次某电商平台大促前所有Ingress路由突然返回503kubectl get ingress显示全部正常kubectl get pods -n ingress-nginx也显示Running但kubectl logs -n ingress-nginx deploy/nginx-ingress-controller里滚动着大量W0321 02:15:23.221342 7 controller.go:141] Error getting SSL certificate default/tls-secret: local SSL certificate default/tls-secret was not found. Using default certificate.原来是因为Ingress资源引用的Secret被误删Controller无法加载TLS证书于是降级到默认证书但默认证书域名不匹配浏览器直接拒绝连接——表面是503本质是TLS握手失败。更隐蔽的问题是Ingress Controller的Leader选举。当部署多个副本时只有Leader副本会同步Ingress配置。我们曾因未配置--election-idingress-controller-leader参数导致两个副本同时认为自己是Leader疯狂争抢ConfigMap锁日志里充斥failed to acquire lease最终所有Ingress配置停止更新。解决方案是强制指定Leader选举ID并用kubectl get configmap -n ingress-nginx ingress-controller-leader-nginx -o yaml检查control-plane.alpha.kubernetes.io/leader字段是否包含当前Leader Pod名。4. 实操过程与核心环节实现从零搭建高可用集群的完整记录4.1 环境准备三台CentOS 7.9虚拟机的硬性清单我们以三台虚拟机为例1台Master2台Worker所有操作基于CentOS 7.9 Minimal安装镜像。这不是理想化的Ubuntu环境而是企业最常见的Linux发行版所有命令都经过真实环境验证。硬件要求硬性清单Master节点2核CPU/4GB内存/40GB磁盘etcd对IO敏感建议SSDWorker节点2核CPU/4GB内存/40GB磁盘运行Pod需预留资源所有节点关闭swapswapoff -a sed -i / swap / s/^/#/ /etc/fstab关闭防火墙systemctl stop firewalld systemctl disable firewalld关闭SELinuxsetenforce 0 sed -i s/^SELINUXenforcing$/SELINUXpermissive/ /etc/selinux/config。内核模块加载验证必须逐条执行# 加载br_netfilter模块iptables桥接必需 modprobe br_netfilter echo br_netfilter /etc/modules-load.d/k8s.conf # 启用iptables桥接 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 EOF sysctl --system # 验证模块是否生效 lsmod | grep br_netfilter # 应输出br_netfilter相关行 sysctl net.bridge.bridge-nf-call-iptables # 应返回1实操心得CentOS 7.9默认内核为3.10.0-1160该版本存在cgroup v2兼容性问题。必须确认/proc/sys/user/max_user_namespaces值≥10000默认为0否则kubelet启动失败。执行echo 10000 /proc/sys/user/max_user_namespaces并写入/etc/sysctl.conf永久生效。4.2 容器运行时安装Containerd 1.7.13的精准配置K8s 1.24已移除Dockershim必须使用containerd。但直接yum install containerd安装的版本1.4.x不支持K8s 1.27的cgroup v2必须手动安装1.7.13。安装步骤# 下载二进制包国内用户替换为清华源 wget https://github.com/containerd/containerd/releases/download/v1.7.13/containerd-1.7.13-linux-amd64.tar.gz tar Cxzvf /usr/local containerd-1.7.13-linux-amd64.tar.gz # 创建systemd服务 cat EOF | sudo tee /etc/systemd/system/containerd.service [Unit] Descriptioncontainerd container runtime Documentationhttps://containerd.io Afternetwork.target [Service] ExecStartPre/sbin/modprobe overlay ExecStart/usr/local/bin/containerd Typenotify Delegateyes KillModeprocess Restartalways RestartSec5 LimitNPROCinfinity LimitCOREinfinity LimitNOFILEinfinity TasksMaxinfinity OOMScoreAdjust-999 [Install] WantedBymulti-user.target EOF systemctl daemon-reload systemctl enable containerd systemctl start containerd关键配置修改/etc/containerd/config.toml# 将cgroup驱动设为systemd匹配CentOS 7.9 [plugins.io.containerd.grpc.v1.cri.containerd.runtimes.runc] [plugins.io.containerd.grpc.v1.cri.containerd.runtimes.runc.options] SystemdCgroup true # 配置国内镜像加速阿里云 [plugins.io.containerd.grpc.v1.cri.registry.mirrors.docker.io] endpoint [https://your-mirror-id.mirror.aliyuncs.com]注意修改config.toml后必须执行sudo systemctl restart containerd且sudo ctr images pull docker.io/library/nginx:alpine验证镜像拉取是否成功。若报错failed to resolve reference docker.io/library/nginx:alpine说明镜像加速配置错误需检查endpoint格式是否含https://前缀。4.3 kubeadm初始化绕过证书过期的三年有效期方案kubeadm默认证书有效期为1年生产环境必须延长。我们采用kubeadm 1.27的--certificate-validity参数但需配合手动证书续签流程。初始化命令kubeadm init \ --kubernetes-versionv1.27.10 \ --pod-network-cidr10.244.0.0/16 \ --service-cidr10.96.0.0/12 \ --certificate-validity1095 \ --cri-socketunix:///run/containerd/containerd.sock \ --upload-certs关键参数解析--certificate-validity1095证书有效期设为3年1095天避免频繁续签--cri-socket明确指定containerd socket路径防止kubeadm误用docker.sock--upload-certs将Control Plane证书上传至etcd供后续节点加入时自动获取。初始化成功后执行以下命令配置kubectlmkdir -p $HOME/.kube sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config sudo chown $(id -u):$(id -g) $HOME/.kube/config验证Control Plane健康# 检查所有核心组件 kubectl get componentstatuses # 应显示all Healthy注意该命令已弃用仅作快速验证 # 检查etcd状态需进入etcd容器 kubectl -n kube-system exec etcd-master-hostname -- etcdctl \ --cacert /etc/kubernetes/pki/etcd/ca.crt \ --cert /etc/kubernetes/pki/etcd/server.crt \ --key /etc/kubernetes/pki/etcd/server.key \ endpoint health --cluster # 检查API Server连通性 curl -k https://127.0.0.1:6443/healthz # 应返回ok实操心得若kubectl get nodes返回No resources found不要慌。这是正常现象——kubeadm init只创建Control PlaneWorker节点尚未加入。此时kubectl get pods -A应显示coredns处于Pending状态因为没有CNI插件Pod无法分配IP。这是集群搭建的“临界点”接下来必须安装CNI插件才能激活网络。4.4 Calico网络插件安装适配内网环境的定制化改造Calico是生产环境首选CNI但默认YAML不适用于内网。我们下载官方manifest后进行三处关键修改修改步骤# 下载官方YAML国内用户替换为清华源 curl https://docs.projectcalico.org/manifests/calico.yaml -O # 修改1CIDR匹配kubeadm参数 sed -i s/192.168.0.0\/16/10.244.0.0\/16/g calico.yaml # 修改2禁用BGP内网无需路由广播 sed -i /- name: CALICO_IPV4POOL_BGP/a\ value: false calico.yaml # 修改3启用Felix的loose RPF检查解决内网ARP问题 sed -i /- name: FELIX_IGNORELOOSERPF/a\ value: true calico.yaml安装与验证kubectl apply -f calico.yaml # 监控Calico组件启动 watch kubectl get pods -n kube-system | grep calico # 等待所有calico-* Pod变为Running后检查节点状态 kubectl get nodes -o wide # 应显示READY状态 kubectl get pods -A | grep coredns # coredns应变为Running网络连通性终极验证# 在Master节点执行 kubectl run test-pod --imagebusybox:1.35 --rm -it -- sh -c ping -c 3 10.244.1.3 # 在任意Pod内执行DNS解析 kubectl exec -it any-pod -- nslookup kubernetes.default.svc.cluster.local提示若kubectl get nodes显示NotReady首先检查kubectl logs -n kube-system calico-node-xxxxx常见错误是Failed to initialize BPF map此时需确认内核版本≥4.18CentOS 7.9需升级内核或禁用BPF在calico.yaml中添加- name: FELIX_BPFENABLED\n value: false。4.5 Worker节点加入带节点标签和污点的标准化流程Worker节点加入不是简单执行join命令必须注入运维元数据。我们采用以下标准化流程Master节点生成带标签的join命令# 生成join命令并添加节点角色标签 kubeadm token create --print-join-command --ttl 2h /tmp/join.sh sed -i /kubeadm join/a\ --node-name$(hostname -s) \\\n --labelroleworker \\\n --taintnode-role.kubernetes.io/worker:NoSchedule /tmp/join.shWorker节点执行# 执行修改后的join命令需提前在Worker节点安装containerd sh /tmp/join.sh # 加入后立即验证标签和污点 kubectl get nodes --show-labels | grep $(hostname -s) kubectl describe node $(hostname -s) | grep Taints验证多节点调度# 部署测试Deployment强制调度到Worker节点 kubectl create deploy nginx-worker --imagenginx --replicas2 kubectl patch deploy nginx-worker -p {spec:{template:{spec:{nodeSelector:{role:worker}}}}} kubectl get pods -o wide # 所有Pod应运行在Worker节点IP上注意--taintnode-role.kubernetes.io/worker:NoSchedule确保Master节点不会被误调度Pod这是生产环境基线要求。若忘记添加需手动执行kubectl taint nodes node-name node-role.kubernetes.io/worker:NoSchedule。5. 常见问题与排查技巧实录来自17个真实故障现场的速查表5.1 节点NotReady的七种根因与诊断路径节点NotReady是集群搭建期最高频问题但表现相似根因迥异。以下是我在不同环境抓取的真实日志片段及对应解决方案现象关键日志线索根因定位命令解决方案kubectl get nodes显示NotReadykubectl describe node无Eventsjournalctl -u kubelet -n 100 | grep -i cni config输出no valid networks found in /etc/cni/net.dls -l /etc/cni/net.dCalico未安装或YAML未正确apply重新执行kubectl apply -f calico.yaml节点反复Ready/NotReady切换journalctl -u kubelet | grep -i failed to load kubeconfigls /etc/kubernetes/kubelet.confkubelet配置文件丢失从Master节点复制/etc/kubernetes/kubelet.conf到Worker节点kubectl get nodes显示NotReady且InternalIP为空ip addr show | grep inet 无CNI网卡如cali*kubectl get pods -n kube-system | grep calicoCalico Node DaemonSet未调度到该节点检查节点标签是否匹配kubernetes.io/oslinux节点Ready但kubectl get pods显示所有Pod Pendingkubectl get events --sort-by.lastTimestamp | tail -10含0/3 nodes are available: 3 node(s) had taint {node.kubernetes.io/not-ready: }kubectl describe node | grep -A5 Conditions节点Condition中Ready为False检查kubelet服务状态systemctl status kubeletkubectl get nodes显示NotReadyjournalctl -u kubelet含failed to run Kubelet: failed to create kubelet: misconfiguration: kubelet cgroup driver: systemd is different from docker cgroup driver: cgroupfsdocker info | grep Cgroup Drivercat /var/lib/kubelet/config.yaml | grep cgroupDriver统一cgroup驱动修改/var/lib/kubelet/config.yaml中cgroupDriver: systemd重启kubelet节点Ready但无法拉取私有镜像kubectl logs pod-name -c container-name含x509: certificate signed by unknown authorityopenssl s_client -connect registry-domain:443 -showcerts私有镜像仓库证书未导入节点执行cp ca.crt /etc/pki/ca-trust/source/anchors/ update-ca-trustkubectl get nodes显示NotReadyjournalctl -u kubelet含failed to run Kubelet: unable to load client CA file /etc/kubernetes/pki/ca.crt: open /etc/kubernetes/pki/ca.crt: no such file or directoryls /etc/kubernetes/pki/kubeadm init phase upload-certs --upload-certsMaster节点证书未上传至etcd重新执行证书上传命令实操心得kubectl describe node输出的Conditions区块是节点健康度的“心电图”。重点关注Ready、MemoryPressure、DiskPressure、PIDPressure、NetworkUnavailable五项。其中NetworkUnavailable为True时节点永远无法Ready必须优先解决CNI问题。5.2 Pod Pending的四层穿透式排查法Pod Pending状态常被误判为调度器问题实则90%源于底层资源或配置缺陷。我们采用四层穿透法从外到内逐层剥离第一层检查Pod自身配置kubectl describe pod pod-name # 重点看Events末尾 # - 如果含0/3 nodes are available: 1 node(s) had taints that the pod didnt tolerate → 污点不匹配 # - 如果含0/3 nodes are available: 3 Insufficient cpu → 资源不足 # - 如果含no persistent volumes available for this claim → PVC未绑定第二层检查节点资源与污点kubectl describe node node-name # 查看Allocatable资源是否足够注意不是Capacity # 查看Taints是否与Pod tolerations匹配 # 查看Conditions中NetworkUnavailable是否为False第三层检查调度器日志# 获取Scheduler Pod名 kubectl get pods -n kube-system | grep scheduler # 查看调度决策日志 kubectl logs -n kube-system scheduler-pod-name \| grep pod-name # 若无输出说明Scheduler根本未处理该Pod问题在API Server或etcd第四层直连etcd验证Pod对象状态# 进入etcd容器 kubectl -n kube-system exec etcd-master -- sh # 查询Pod对象是否写入etcd ETCDCTL_API3 etcdctl \ --cacert /etc/kubernetes/pki/etcd/ca.crt \ --cert /etc/kubernetes/pki/etcd/server.crt \ --key /etc/kubernetes/pki/etcd/server.key \ get /registry/pods/default/pod-name --prefix --keys-only # 若无返回说明kubectl apply未成功写入etcd检查API Server日志提示当kubectl describe pod显示Events为空时不要放弃。执行kubectl get events --all-namespaces --sort-by.lastTimestamp | grep pod-name因为Events对象有TTL默认1小时可能已被清理。5.3 Service DNS解析失败的链路诊断Service DNS解析失败是微服务调用中断的常见原因但根因分散在多个组件。我们按数据流向逐段验证Step 1确认CoreDNS Pod健康kubectl get pods -n kube-system | grep coredns kubectl logs -n kube-system deploy/coredns | tail -10 # 正常日志应含plugin/loop: Loop (127.0.0.1:53 - :53) detected for zone警告但无ERRORStep 2验证CoreDNS服务端口可达# 在任意Pod内执行 kubectl exec -it pod-name -- sh -c telnet kube-dns.kube-system.svc.cluster.local 53 # 或用nc kubectl exec -it pod-name -- nc -zv kube-dns.kube-system.svc.cluster.local 53Step 3测试DNS解析基础能力# 在Pod内解析集群内Service kubectl exec -it pod-name -- nslookup kubernetes.default.svc.cluster.local # 应返回10.96.0.1kubernetes Service ClusterIP # 解析外部域名验证上游DNS kubectl exec -it pod-name -- nslookup google.comStep 4抓包定位DNS查询路径# 在Pod内启动tcpdump kubectl exec -it pod-name -- tcpdump -i any port 53 -w /tmp/dns.pcap # 触发一次nslookup然后下载pcap文件分析 kubectl cp namespace/pod-name:/tmp/dns.pcap ./dns.pcap # 用Wireshark打开检查 # - 查询是否发往10.96.0.10CoreDNS ClusterIP # - CoreDNS是否返回NXDOMAIN配置错误或REFUSED权限问题Step 5检查CoreDNS配置映射kubectl get configmap -n kube-system coredns -o yaml # 确认forward插件指向正确的上游DNS如114.114.114.114 # 若使用自定义hosts确认hosts插件配置正确注意CoreDNS默认配置中loop插件会检测DNS循环若集群内有其他DNS服务如dnsmasq可能导致CoreDNS拒绝启动。解决方案是禁用loop插件或