用 NetworkPolicy 把通路收窄
目标
从默认拒绝开始,将 NetworkPolicy 逐步收紧为六种形式,尤其要亲手区分 from 项中的 AND/OR 结构。
为什么这很重要
首先需要明确:本实验环境没有能够执行策略的 CNI 数据平面。因此无法确认流量是否真的被阻断,评分只检查对象 spec。 这一限制反而与考试很相似,CKA 大多数题目同样检查清单是否准确。
NetworkPolicy 的思考方式与防火墙不同。一旦有任何一个策略选中了某个 Pod,该 Pod 对应方向(Ingress/Egress)的流量就会变成默认拒绝,只允许策略明确放行的流量通过。策略之间只会叠加,不存在拒绝规则。因此,“一个默认拒绝策略 + 所需数量的允许策略”是标准模式。
阻止 egress 时顺带把 DNS 也阻断,是另一个常见事故。Pod 无法解析 Service 名称时,症状不会表现为网络阻断,而是应用超时,导致诊断耗时更长。
步骤
- 创建 namespace
cka-netpol(标签tier=app)和cka-netpol-client(标签tier=client)。在cka-netpol中创建 Deploymentweb(副本数 2,镜像nginx:1.27,Pod 标签app=web)。 - 在
cka-netpol中创建 NetworkPolicydefault-deny-ingress。podSelector 是空对象,policyTypes 为[Ingress],没有 ingress 规则。 - 创建 NetworkPolicy
allow-frontend。podSelector 为app=web,ingress 的 from 仅包含一个 podSelectorapp=frontend,端口为 TCP 80。 - 创建 NetworkPolicy
allow-client-ns。podSelector 为app=web,ingress 的 from 仅包含一个 namespaceSelectortier=client(不要同时加入 podSelector)。 - 创建 NetworkPolicy
egress-dns-only。podSelector 为app=web,policyTypes 为[Egress],egress 的 to 是 namespaceSelectorkubernetes.io/metadata.name=kube-system,端口包含 UDP 53 和 TCP 53 两项。 - 创建 NetworkPolicy
allow-cidr。podSelector 为app=web,ingress 的 from 是 ipBlock cidr10.0.0.0/16,except 中加入10.0.5.0/24。 - 创建 NetworkPolicy
web-final。podSelector 为app=web,policyTypes 为[Ingress, Egress]。ingress 的 from 要在同一个条目中同时设置 namespaceSelectortier=client和 podSelectorapp=frontend,端口为 TCP 8080。egress 的 to 是 ipBlock cidr0.0.0.0/0,except 为169.254.169.254/32,端口为 TCP 443。
参考
- 每个 namespace 都会自动带有
kubernetes.io/metadata.name标签,选择 kube-system 时非常有用。 - 使用
kubectl get netpol <이름> -n cka-netpol -o yaml重新读取保存后的结构,就能直观看出 AND/OR 关系。 - 常见错误 1:在第 7 步将 from 拆成两个条目。这样会变成 OR,导致 client namespace 中的所有 Pod 都被放行。
- 常见错误 2:将
169.254.169.254/32写成单独的 to 条目,而不是 except。except 必须位于 ipBlock 内。
准备目标与流量来源
创建 namespace cka-netpol(标签 tier=app)和 cka-netpol-client(标签 tier=client)。在 cka-netpol 中创建 Deployment web(副本数 2,镜像 nginx:1.27,Pod 标签 app=web)。
namespace 标签是后续 namespaceSelector 用来选择对象的键。Pod 标签也必须准确设置。
默认拒绝策略
在 cka-netpol 中创建 NetworkPolicy default-deny-ingress。podSelector 是空对象,policyTypes 为 [Ingress],没有 ingress 规则。
将 podSelector 设为空对象,就会选中该 namespace 中的所有 Pod。不写任何规则,意味着全部拒绝。
只允许同一 namespace 中的 Pod
创建 NetworkPolicy allow-frontend。podSelector 为 app=web,ingress 的 from 仅包含一个 podSelector app=frontend,端口为 TCP 80。
from 条目中只使用 podSelector 时,范围会限定在策略所在的 namespace 内。还必须指定端口。
允许另一个 namespace 中的全部 Pod
创建 NetworkPolicy allow-client-ns。podSelector 为 app=web,ingress 的 from 仅包含一个 namespaceSelector tier=client(不要同时加入 podSelector)。
namespaceSelector 检查 namespace 上的标签。本步骤需要允许该 namespace 中的全部 Pod,因此不要同时加入 podSelector。
阻止出站流量,仅保留 DNS
创建 NetworkPolicy egress-dns-only。podSelector 为 app=web,policyTypes 为 [Egress],egress 的 to 是 namespaceSelector kubernetes.io/metadata.name=kube-system,端口包含 UDP 53 和 TCP 53 两项。
每个 namespace 都会自动带有一个值与其名称相同的标签。DNS 有时只允许 UDP 并不足够。
按 CIDR 允许并排除部分网段
创建 NetworkPolicy allow-cidr。podSelector 为 app=web,ingress 的 from 是 ipBlock cidr 10.0.0.0/16,except 中加入 10.0.5.0/24。
ipBlock 包含 cidr 和 except。except 的网段必须位于 cidr 范围内。
综合:AND 条件与元数据网段阻断
创建 NetworkPolicy web-final。podSelector 为 app=web,policyTypes 为 [Ingress, Egress]。ingress 的 from 要在同一个条目中同时设置 namespaceSelector tier=client 和 podSelector app=frontend,端口为 TCP 8080。egress 的 to 是 ipBlock cidr 0.0.0.0/0,except 为 169.254.169.254/32,端口为 TCP 443。
将 from 拆成两个条目时是 OR,在同一条目中同时使用两个选择器时是 AND。一个连字符的位置就会改变含义。