为什么必须放行 DNS
NetworkPolicy 的出向策略是白名单:Pod 一旦被带 Egress 的策略选中,除显式放行的目标外,向任何地址发起的连接都会被丢弃,其中也包括发往集群 DNS 服务的 53 端口查询。这个疏漏的后果极具迷惑性——应用报的是「数据库连不上」「外部接口超时」,而根因是域名根本没解析出来。因此启用出向限制时,放行 DNS 必须与主策略同时上线。
基本信息
| 放行目标 | kube-system 中的 DNS 服务(标签 k8s-app: kube-dns) |
|---|---|
| 协议端口 | UDP 53 与 TCP 53 都要放行 |
| 选择方式 | namespaceSelector 配 podSelector,避免写死地址 |
| 验证手段 | 容器内解析集群服务名与外部域名各一次 |
| 常见误判 | 把解析失败当成网络不通或中间件故障 |
放行 DNS 的标准写法
放行 DNS 的标准写法
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-dns-egress
namespace: prod
spec:
podSelector: {}
policyTypes: ['Egress']
egress:
- to:
- namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: kube-system # 命名空间标签,集群自带的稳定标识
podSelector:
matchLabels:
k8s-app: kube-dns # 指向 DNS 服务的工作负载
ports:
- {protocol: UDP, port: 53}
- {protocol: TCP, port: 53}典型使用场景
- 上线出向限制:在默认拒绝之前先准备好 DNS 放行,避免业务同时失去解析能力
- 排查应用报错:应用说连接超时,先确认解析是否成功,再谈连接层
- 多命名空间治理:为每个命名空间准备统一的 DNS 放行策略模板,减少逐环境重写
- DNS 组件迁移:从 kube-dns 换到 CoreDNS 或更换标签时,同步更新选择器
- 性能优化:放行后仍解析缓慢,属于解析行为层面的调优,与策略无关
验证解析是否真的通了
验证解析是否真的通了
kubectl exec -it web-x -n prod -- nslookup kubernetes.default # 集群内服务名
kubectl exec -it web-x -n prod -- nslookup api.example.com # 外部域名
kubectl exec -it web-x -n prod -- cat /etc/resolv.conf # 确认解析器地址与 search 域
kubectl -n kube-system logs -l k8s-app=kube-dns --tail=30 | grep -i -E 'deny|refused|blocked'
kubectl get networkpolicy -n prod # 复核命名空间内全部策略现象与判定
| 现象 | 可能原因 | 判定方法 |
|---|---|---|
| 集群内服务名解析失败 | 未放行 DNS 出向 | 换用 Pod IP 直连是否可达,可达即解析问题 |
| 外部域名解析失败但内网正常 | 上游 DNS 转发被拦 | 解析器地址与 DNS 组件的上游配置 |
| 偶发解析失败 | 只放行 UDP 53,大响应被截断后 TCP 重试被拒 | 补放 TCP 53 后观察是否消失 |
| Pod 启动后一律解析失败 | DNS 服务本身未就绪 | 查看 DNS 组件副本与日志 |
kube-system 命名空间自带 kubernetes.io/metadata.name 标签,可直接用命名空间选择器定位,比写死 ClusterIP 稳——DNS 服务重建后地址会变,写死的选择器会立刻失效。
UDP 53 是常规查询通道,响应超过单包限制时解析器会改用 TCP 53 重试。只放 UDP 的策略在正常情况下看不出问题,遇到大响应或 DNSSEC 类查询就会偶发失败,属于难以复现的隐性故障。