LabHub
学习 学习路径 课程

Kubernetes 网络 — 在真集群上

策略里没有「拒绝」

在 LabHub 中继续学习

一句话总结

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后为什么会变得更糟糕的情况。