LabHub
学习 学习路径 课程

LFCS — Linux 基金会认证系统管理员

名字变成地址的路,以及地址被改掉的那天

在 LabHub 中继续学习

一句话总结

网络问题都被报告为“不可用”,实际却终止在名称解析、路由、socket三个区段之一。不说明属于哪个区段,就称不上诊断。

概念图: 名称解析、路由、socket · 按照什么顺序询问哪些位置 · getent hosts 会走完整条路径,dig 则只查看 DNS。 · 最多只会使用 3 个

为什么需要了解这一点

curl 失败了。此时立即怀疑 DNS,只对了一半。在 Linux host 中,名称解析并非只由 DNS 完成。首先由 /etc/nsswitch.confhosts: 行决定按照什么顺序询问哪些位置。通常是 files dns,所以 /etc/hosts 会先于 DNS 回答。之后才由 /etc/resolv.conf 决定询问哪台 server、附加哪个 search domain。

这种结构也决定了诊断工具的选择方式。getent hosts 会走完整条路径,dig 则只查看 DNS。 两者结果不同时,问题不在 DNS server,而在 stub resolver 区段。这一句话能让故障会议缩短 5 分钟。

/etc/resolv.conf 中有几个值需要记住。nameserver 最多只会使用 3 个options timeout 默认为 5 秒,options attempts 默认为 2 次。因此第一台 nameserver 停止工作时,按默认值计算,用户会完整感受到 5 秒延迟——这就是已经配置冗余却仍然缓慢的原因。options ndots 是一个阈值:名称至少包含多少个点,才不会附加 search domain,而是先按 absolute name 查询;默认值为 1。在 container 环境中,如果该值设置得很大,解析一个外部名称前会先产生多次失败查询。

工作原理

routing table 不是从上向下遍历的列表,而是最长 prefix 获胜的查询。 如果同时存在 10.0.0.0/240.0.0.0/0,发往 10.0.0.5 的数据包永远走前一条。default route 的 prefix length 为 0,也就是“没有其他匹配项时”使用的路径。在 ip route 输出中,via 是 next hop,dev 是出口 device,src 是用作 source address 的值。

socket state 本身就是诊断信息。

状态 含义 大量出现时表示
LISTEN server 等待连接 正常
ESTABLISHED 双向连接已建立 正常。数量接近上限时有问题
SYN-SENT 已发送连接请求,等待响应 对端不存在或中途被丢弃
TIME-WAIT 主动关闭的一方等待最后数据包 正在大量创建和关闭短连接
CLOSE-WAIT 对端已关闭,本端尚未关闭 应用程序缺陷的信号

大量 TIME-WAIT 通常是正常的。它会留在先断开连接的一方,用于防止迟到的数据包污染新连接。相反,CLOSE-WAIT 不断累积表示代码没有关闭 socket,性质完全不同。

实际工作中的表现

有一天,作者的整个 home lab cluster 都停止响应。日志只不断重复 dial tcp 10.0.0.111:6443: connect: no route to host。诊断 5 分钟便结束了——查看 ip -4 addr show 后发现 control plane node 的地址从 .111 变成了 .120,输出还带有 scope global dynamic。它在 DHCP lease 更新过程中获得了不同地址。

决定性证据在 certificate 中。apiserver certificate 的 SAN 列表只有 10.0.0.111,没有 .120。所以 etcd 与 kube-apiserver 试图绑定不存在的 .111,失败后陷入重启循环;kube-scheduler 与 controller-manager 绑定到 127.0.0.1,所以进程仍然存活,却什么也做不了。仅一个地址发生变化,就让整个 7 节点平台停止运行。

防止再次发生的方法,是通过 netplan 固定 static address。为 interface 设置 dhcp4: false,直接指定 address、default route 和 nameserver。但仅此还不够。 cloud-init 会在启动时重新生成并覆盖网络设置,所以还必须加入下面这一行。

echo 'network: {config: disabled}' > /etc/cloud/cloud.cfg.d/99-disable-network-config.cfg

除此之外,还要在 router 侧为相应 MAC 设置 DHCP reservation,或把该地址从 pool 中移除。只固定 host,其他 device 仍可能租到同一地址并产生冲突。三项全部完成才称得上“固定”。应用后,ip addr 输出中的 dynamic 标记消失,就是确认信号。

还有一个教训。该 cluster 的 controlPlaneEndpoint 不是 VIP 或 DNS name,而是固定为某个 node 的物理 IP。因此,后来即使把 control plane 扩展到 3 台并形成 etcd quorum,只要这一台停止工作,哪怕另外两台正常,所有 client 也找不到入口。如果不对地址进行间接化,冗余只能提高数据可用性,访问可用性仍保持不变。

下个练习将做什么

亲自编写 netplan static address 文件和 cloud-init 禁用文件。在 /etc/hosts 中添加条目,通过 getent 确认实际走这条路径,再读取 /etc/resolv.conf/etc/nsswitch.conf 生成摘要。启动一个 listener,用 ss 观察 socket,并从 ip route 中解析 default route。最后以文档形式设计 firewall rule,确认规则顺序为什么事关成败。该环境中禁用了 iptablesping,因此 rule application 与 reachability check 只作为概念处理。