策略里没有「拒绝」
一句话总结
NetworkPolicy中没有拒绝的概念。如果板子上没有任何政策,全部是允许的,只要有一个附加,其方向就会被翻转到允许列表中。
为什么要知道这个转变呢?
容器管理的基本值是全部允许。任何命名空间的任何子网都触及所有其他子网。入侵者抓住一个网络子网,就会看到数据库在原地。
基本值翻转的点
NetworkPolicy的运行方式与直观不同。
如果平板电脑上没有任何政策,则全部允许,只要有一个政策附加,平板电脑就会以允许列表方式改变对该方向的允许情况。
所以政策中根本就没有“拒绝”的概念。default-deny以之命名的政策其实只是不允许任何事情的政策。
spec:
podSelector: {} # 이 네임스페이스의 모든 파드
policyTypes: [Ingress] # ingress 만 다룬다
# ingress: 항목이 없다 → 허용하는 것이 하나도 없다
如果不知道这个转换,就会说“只是增加了一个政策,但无关的事情就断了”。
不弄混方向的方法
政策总是附在接收方身上。
| 字段 | 选择 |
|---|---|
podSelector |
受保护的帕德(db) |
ingress.from |
允许的来源(api) |
粘贴在发送的一边的话,语法会通过,也会生成对象,但什么都没有发生。因为没有错误,所以更让人困惑。
各种政策加在一起
如果同一页面上附有多个政策,则为合并集合。后面的政策不会覆盖前面的政策。因此,会发生“为了缩小而添加政策,但反而变得更宽”的情况。为了缩小,必须修改现有政策。
我最常犯的错误
在基本阻止egress的瞬间,**DNS也会一起切断。**因为通过CoreDNS outgoing的53号端口也是egress。
症状是“找不到名称”,CoreDNS很正常,其他命名空间也正常。所以没有人怀疑刚刚添加的网络策略。
第一次插入政策的顺序
从基本屏蔽开始打开的话,那一刻就会全部关闭。是有顺序的。
**1.先看看在通信什么。**在写政策之前,先看看实际的流程。Cilium内部 Hubble,除此之外用conntrack或应用程序日志绘制。
hubble observe --namespace labhub-prod --last 500 -o json | jq -r '"\(.source.namespace)/\(.source.pod_name) → \(.destination.namespace)/\(.destination.pod_name):\(.l4.TCP.destination_port)"' | sort | uniq -c | sort -rn
**2.先输入允许政策。**因为还没有基本阻止,所以什么都没有被阻止。
**3.然后打开基本遮蔽。**这时遗漏的东西就会被发现。
**4. 请务必确认DNS。**使用egress的瞬间也会阻止DNS(53/UDP)。名称查询 如果不行的话,所有东西都会显示为超时,很难找到原因。
egress:
- to:
- namespaceSelector:
matchLabels: {kubernetes.io/metadata.name: kube-system}
podSelector:
matchLabels: {k8s-app: kube-dns}
ports:
- {protocol: UDP, port: 53}
- {protocol: TCP, port: 53}
政策无法阻止的事情
网络政策不是万能的。要知道不能阻止的东西,然后把它送到其他层。
| 无法阻止的事情 | 代替 |
|---|---|
| 同一包裹中的容器之间 | 分割包裹 |
| hostNetwork 板 | 通过板安全禁止 hostNetwork |
| 节点本身发出的流量 | 节点防火墙·安全组 |
| L7(路径·方法) | Cilium L7政策,服务消息 |
| 已经建立的连接 | 政策仅适用于新连接 |
最后一行是陷阱。即使放入政策,正在进行的连接仍然存在。 所以会弹出“添加了政策,但仍然无法通话”。要确认,请重新连接。 要看。
调试顺序
# 1. 이 파드를 고르는 정책이 있나 (없으면 기본 허용)
kubectl get netpol -n <ns> -o json | jq -r '
.items[] | select(.spec.podSelector.matchLabels // {} | to_entries | length > 0) |
"\(.metadata.name): \(.spec.podSelector.matchLabels) \(.spec.policyTypes)"'
# 2. 양쪽 다 열려 있나 — 출발지 egress, 도착지 ingress
# 3. 실제로 막혔는지 확인 (Connection refused 는 정책이 아니다)
kubectl exec -n <ns> <pod> -- nc -zv -w3 <대상> <포트>
3次区分很重要。如果被政策阻挡的话是timeout,如果没有人听的话 是refused。如果出现refused,那不是政策问题。
在实际工作中真正重要的东西
阻止egress时,将DNS一起在同一提交中打开。 通过CoreDNS出去的53号也一起切断egress,症状是“找不到名称”,CoreDNS没有问题,其他命名空间正常。所以没有人怀疑刚刚添加的政策。
**政策总是贴在接收方。**贴在发送方的话,语法会通过,对象也会被创建,但什么也不会发生。因为没有错误,所以会花更长时间。
要缩小,请选择现有政策,不要添加新政策。 同一页上的政策是合并的,后面的政策不会覆盖前面的。如果想缩小,但结果反而变宽,这就是问题的所在。
在下次实习中**直接引发这个事故后请改正。**然后改正时,一起看看打开UDP 53后为什么会变得更糟糕的情况。