ping是工作在网络层ICMP 协议的命令它只认主机名或 IP 地址不认 URL。 gitlab-cloud.com —— 这是主机名 ✅ https://gitlab-cloud.com —— 这是 URL前面的 https:// 是应用层协议ping 不理解这个前缀所以把整个字符串当成 一个主机名去做 DNS 解析自然就Name or service not knownS 列Z → 僵尸进程defunct 要kill 掉它的父进程 S 列D → 不可中断睡眠通常在等 IOkill 不掉 修复IO问题或者重启机器。 如果 IO 永远不回来NFS 服务器挂了、磁盘坏了这个进程就永远卡着只能重启机器。 孤儿进程 正常运行父已死 能killD 进程问题sudops-eopid,stat,wchan:30,cmd|grep-Edf|strace|grep-vgrepdf-h卡死使用stracedf-h查到挂载目录卡死 pod 挂载了 /data/k8s-volumes, nfs 服务端停了客户端这边挂载关系还在 这时只要访问这个路径客户端发送 RPC 调用给服务端服务端不回复就会一直等待进程进入 D 状态直到IO 完成 使用 Ctrl C,kill等用户态的命令发 SIGINT[sɪgɪnt]信号用户态命令进不去因为 D 进程在内核态的 等一个IO 完成 为啥这次能kill掉因为这个 nfs 是一个可杀的状态 rpc_wait_bit_killableLinux 内核给 NFS 专门加了一种可杀的 D 状态 CtrlCSIGINT→ 无效killpidSIGTERM→ 无效kill-9pidSIGKILL→ 有效 ✅ 否则只能等 I/O 返回或者重启。nfs 挂载有两种语义 hard mountserver 不回就永远等。这样会拖垮整个节点好处是数据不因网络波动而丢失。 用于写重要数据 soft mountserver挂了客户端还能动坏处是写入操作可能在网络抖动时拿到错误。 用于读数据解决方案NFS server 做高可用keepalived DRBD或者换成分布式存储如 Ceph/Longhorn 监控 NFS server 的可达性server 挂了先告警别等业务发现 K8s 里尽量用 CSI driver 而不是直接 hostPath NFSCSI 有更完善的超时和重试二、iptables REJECT 老 server IP 是什么操作卡住然后人为告诉它到 nfs server 不通从而从 D 状态退出。背景你 NFS 客户端卡住的本质是内核 RPC 代码在等 server 回包。TCP 连接可能还半死不活地挂着内核不会主动放弃——除非它收到一个明确的失败信号。iptables REJECT就是人为制造这个失败信号。做法# 假设老 NFS server 是 192.168.1.100sudoiptables-IOUTPUT-d192.168.1.100-jREJECT --reject-with icmp-host-unreachable这条规则说“凡是发给 192.168.1.100 的包内核自己直接返回一个 ICMP host unreachable 错误不要真的发出去。”效果内核 RPC 代码下一次重试发包时立刻拿到目的不可达错误RPC 层把错误往上抛NFS 客户端层标记这次调用失败在rpc_wait_bit_killable里睡觉的进程被唤醒拿到 EIO进程从 D 状态退出你的 kill 也能生效了和 DROP 的区别DROP是悄悄丢包内核还以为只是网络慢会继续等、继续重试REJECT是明确告诉内核这条路不通内核立刻放弃。所以救 NFS 卡死必须用 REJECT 不能用 DROP。用完要清理掉sudoiptables-DOUTPUT-d192.168.1.100-jREJECT --reject-with icmp-host-unreachable这招是最后的大杀器当kill -9也不灵比如 wchan 不是 killable 的又不想重启节点时用它几乎百发百中。三、umount -l 在 kill -9 之前有什么用第一止血——阻止新进程继续踩坑。你不 umount 的话之后任何一个df、ls /、监控脚本、kubelet 健康检查、bash 补全、甚至tab键自动补全只要路径扫到/data/k8s-volumes又会新增一个 D 进程。越积越多节点越来越糟。umount -l一执行挂载点从目录树里消失新进程访问/data/k8s-volumes就是普通的空目录或者 ENOENT不再走 NFS不会再卡。相当于先把伤口按住不让新的血流出来。所以正确的顺序是先umount -l止血 → 再kill -9救人 → 最后挂载关系自动清理干净。五、CSI 更完善的超时和重试意味着什么先澄清CSI 也不能完全消除 D 状态的可能。只要底层还是 NFS 协议、还是 hard mountserver 挂了内核态该卡还是会卡——这是 Linux VFS 层和 NFS 客户端的行为CSI 在用户态管不到。CSI 的价值在于挂载和生命周期管理做得更体面具体体现在挂载参数可以精细配置。CSI driver比如 nfs-csi-driver、csi-driver-nfs在 StorageClass 里明确声明mountOptions: [soft, timeo50, retrans3, ...]每个 PV 挂载时自动带上不用你到每个节点改 fstab。比手动挂载一致性强得多。挂载操作本身带超时和重试。kubelet 调用 CSI NodePublishVolume 来挂载CSI driver 在这一步会设置合理超时挂不上就返回错误给 kubelet而不是让 mount 进程永远卡着。挂载失败 Pod 会进 ContainerCreating 但至少不会把 kubelet 拖死。Pod 生命周期解耦。CSI 有 NodeUnpublish/NodeUnstage 这些明确步骤Pod 删除时能按顺序清理。相比 in-tree 的老 NFS 插件或者 hostPath 手工挂载异常处理路径清晰很多。可以配合mountPropagation和独立 mount namespace。现代 CSI driver 挂载发生在 driver Pod 的 mount namespace 里即使出问题也相对隔离不像 hostPath 手动挂载那样直接污染宿主机根命名空间。但注意所有这些都是减少发生概率和缩小爆炸半径不是彻底消除。真正的终极解法是在挂载参数上用 soft 合理超时。CSI 只是让这件事变得容易配置和一致执行。如果你想彻底不再碰 NFS 这类有状态网络文件系统的坑可以考虑用 Longhorn、OpenEBS、Rook-Ceph 这种云原生分布式块存储走 iSCSI 或 RBD客户端行为比 NFS 好控制用对象存储S3/MinIO 应用层访问完全绕开文件系统挂载如果必须 NFSserver 端做 HAPacemaker Keepalived 双机或 Ganesha Ceph 后端PXE先跟厂商要过所有的mac地址然后服务器都连好带扳手的网口和业务网网卡管理节点装好DHCP服务TFTP服务HTTP服务dhcp就是BMC dhcp服务 mac地址和BMC还有PXE dhcp服务 业务口的mac和业务ip一一对应dhcp里面还附带上了TFTP服务器的地址。上电后所有BMC 都获得了ip通过 BMC 远程配置 BIOS 一次性 PXE 启动(最常用)ipmitool... chassis bootdev pxeoptionsefiboot 只影响下一次启动之后自动恢复原来的启动顺序 硬盘优先 这样装完系统重启后就自动从硬盘启动了不会再进 PXE并开机然后在UEFI阶段通过PXE网络启动业务口发dhcp请求获得ip, 顺带也获得了TFTP地址主动从TFTP服务器拉取grub.efi 引导加载器UEFI 固件程序, 进入grub后主动从TFTP服务器拉取 grub.cfg grub.efi启动后第一件事就是读取grub.cfg, 告诉grub.efi,内核在哪初始img在哪启动参数是kickstart的http链接 ,压缩的 linux内核文件和初始img 内核启动初始img里的anaconda,通过http服务拉取下来kickstart按照kickstart里面的内容拉取一 个个rpm包在目标机器上组成完整的 rocky linux9系统按照kickstart 配置好操作系统然后重启硬盘启动进入系统BMC 管理口就是标着扳手的那个网口 PXE 服务器上需要跑4个服务:1. DHCP 服务器: 给 PXE 客户端分配 IP 和告知 TFTP 地址2. TFTP 服务器: 提供引导文件(grubx64.efi, vmlinuz, initrd.img)3. HTTP 服务器: 提供 kickstart 文件和安装源(RPM 包)4. DNS 服务器(可选): 给装好的机器分配主机名 通常用一台管理节点跑所有这些服务 这台管理节点本身需要先手动装好系统(U 盘装或 BMC 挂载 ISO)实际流程是:1. 管理节点配好 DHCP 服务器并启动2.100台机器接好电源线和管理网线3.100台机器通电(不需要开机只要 PDU 通电)4. BMC 自动上电(BMC 只要有电就工作不需要按开机键)5. BMC 的网卡自动发 DHCP 请求6. DHCP 服务器自动响应分配 IP7. 几分钟后100 台机器的 BMC 都有了 IPkickstart 就是一份装系统的完整指令: - 磁盘怎么分区 (多大的 /boot, /, /var, swap) - 装哪些软件包 (core, chrony, vim...) - root 密码是什么 - 创建什么用户 - 网络怎么配 (DHCP 还是静态 IP) - 时区、语言、键盘 - 防火墙和 SELinux 开不开 - 装完后执行什么脚本 (%post 段: 配 bond、改主机名、写 yum 源...) - 装完后重启还是关机 本质上就是把你手动装系统时在图形界面里点的每一个选项写成文本。BMC、BIOS、UEFI、GRUB、操作系统之间的关系这几个东西是不同层次的从底层到上层: ┌─────────────────────────────────────────────────────────┐ │ │ │ 层次5: 操作系统(Rocky Linux9)│ │ 你日常用的系统跑 K8s、训练任务等 │ │ 存在硬盘上 │ │ │ ├─────────────────────────────────────────────────────────┤ │ │ │ 层次4: GRUB(grubx64.efi)│ │ 引导加载器(bootloader)│ │ 职责: 从硬盘(或网络)加载操作系统内核 │ │ 显示启动菜单:选择要启动的系统│ │ 存在硬盘的 EFI 分区(/boot/efi)或 TFTP 服务器上 │ │ │ ├─────────────────────────────────────────────────────────┤ │ │ │ 层次3: UEFI 固件 │ │ 存在主板的 SPI Flash 芯片上(不在硬盘上)│ │ 职责: │ │ - 开机后第一个运行的程序 │ │ - 初始化 CPU、内存、PCIe 设备(GPU、网卡、NVMe)│ │ - 提供 BIOS Setup 界面(按 F2/Del 进入的那个)│ │ - 按启动顺序找到 GRUB 并执行它 │ │ - 如果启动项是 PXE就走网络启动流程 │ │ │ │ UEFI 和 BIOS 的关系: │ │ BIOS 是老标准(1980年代)16 位功能有限 │ │ UEFI 是新标准(2005年)64 位支持大硬盘、安全启动│ │ 现在的服务器都是 UEFI但大家习惯把 UEFI 设置界面 │ │ 还是叫BIOS 设置或进 BIOS│ │ 严格来说应该叫UEFI Setup│ │ │ ├─────────────────────────────────────────────────────────┤ │ │ │ 层次2: BMC 固件 │ │ 独立的芯片有自己的 CPU 和操作系统(通常是嵌入式 Linux)│ │ 和主 CPU 完全独立通电就运行 │ │ 职责: │ │ - 远程开关机(不需要去机房按按钮)│ │ - 远程控制台(看到屏幕输出就像接了显示器)│ │ - 硬件监控(温度、风扇、电压、硬盘状态)│ │ - 远程挂载 ISO(虚拟光驱)│ │ - 修改 UEFI/BIOS 设置(不需要进 BIOS 界面)│ │ - 收集硬件日志(SEL, System Event Log)│ │ │ │ BMC 不参与操作系统的运行 │ │ 操作系统跑起来后BMC 还在后台默默监控硬件 │ │ │ ├─────────────────────────────────────────────────────────┤ │ │ │ 层次1: 硬件 │ │ CPU、内存、GPU、NVMe、网卡、主板 │ │ │ └─────────────────────────────────────────────────────────┘谁发起的 DHCP 请求UEFI 固件发起的不是操作系统此时操作系统还不存在。 UEFI 固件里内置了一个 PXE 客户端(网卡固件的一部分)启动顺序轮到 PXE 时: UEFI 对业务网卡说:你去发 DHCP 请求网卡发出 DHCP Discover 广播包 这个广播包里带了: - 自己的 MAC 地址 - 一个标记:我是 PXE 客户端我要网络启动完全自动不需要人干预 前提: BIOS 里启用了这个网口的 PXE 功能TFTP 服务器地址怎么知道的DHCP 服务器告诉它的塞在 DHCP 响应里一起返回。 DHCP 响应里包含的信息: - 你的 IP:10.0.1.11 - 子网掩码:255.255.255.0 - 网关:10.0.1.1 - TFTP 服务器地址:10.0.1.5 ← 就是 dhcpd.conf 里的 next-server - 要下载的文件名: grubx64.efi ← 就是 dhcpd.conf 里的 filename 对应的 DHCP 配置: next-server10.0.1.5;# TFTP 在哪filenamegrubx64.efi;# 下载哪个文件所以机器不需要知道TFTP 在哪 它只是问 DHCP 要 IPDHCP 顺便告诉它:你的 IP 是这个另外你去 10.0.1.5 用 TFTP 下载 grubx64.efi 来启动Anaconda 哪来的Anaconda 是 Red Hat 系 Linux (RHEL/CentOS/Rocky/Fedora) 的安装程序。 不是 Python 的那个 Anaconda。 它藏在 initrd.img 里。 PXE 下载了 vmlinuz initrd.img → 内核启动 → 解压 initrd.img → initrd 里面就是一个迷你 Linux 系统 Anaconda 安装程序 → Anaconda 读取 kickstart 文件 → 自动分区、装包、配置网络 → 装完重启 → Anaconda 的使命结束 你手动用 ISO 装 Rocky Linux 时看到的图形安装界面就是 Anaconda。 kickstart 就是把你在图形界面里点的那些选项写成文本文件实现无人值守安装。TFTP 是什么那三个文件干什么TFTP (Trivial File Transfer Protocol): 极简的文件传输协议UDP 端口 69 没有认证没有目录列表只能读写文件 为什么用它: UEFI 固件里内置了 TFTP 客户端不需要操作系统支持 HTTP 客户端太复杂UEFI 固件塞不下 三个文件: grubx64.efi → 引导加载器 (GRUB) UEFI 下载并执行它 它再去下载内核和 initrd 相当于一个中间人知道怎么加载操作系统 vmlinuz → Linux 内核 (压缩的) 操作系统的核心管理 CPU/内存/设备 GRUB 把它加载到内存并跳转执行 initrd.img → 初始内存盘 (Initial RAM Disk) 一个临时的迷你文件系统包含: - 磁盘驱动、网卡驱动、文件系统驱动 - Anaconda 安装程序 内核启动后先用它装完系统后就不需要了 执行顺序: UEFI → grubx64.efi → vmlinuz initrd.img → Anaconda → 装系统