Ambient 和 Kubernetes NetworkPolicy

Kubernetes NetworkPolicy 允许您控制第 4 层流量如何到达您的 Pod。

NetworkPolicy 通常由集群中安装的 CNI 强制执行。Istio 不是 CNI,也不强制执行或管理 NetworkPolicy,并且在所有情况下都尊重它 - ambient 不会并且永远不会绕过 Kubernetes NetworkPolicy 的强制执行。

这意味着可以创建一个 Kubernetes NetworkPolicy 来阻止 Istio 流量或以其他方式妨碍 Istio 功能,因此在将 NetworkPolicy 和 ambient 结合使用时,需要牢记一些事项。

Ambient 流量覆盖和 Kubernetes NetworkPolicy

将应用程序添加到 ambient 网格后,ambient 的安全 L4 覆盖网络将在端口 15008 上在 Pod 之间隧道传输流量。一旦安全流量进入目标 Pod 且目标端口为 15008,流量将被代理回原始目标端口。

但是,NetworkPolicy 在主机上、Pod 外部强制执行。这意味着,如果已存在 NetworkPolicy(例如,将拒绝所有传入到 ambient Pod 上的除 443 以外的所有端口的流量),则需要为端口 15008 添加一个例外。

例如,以下 NetworkPolicy 将阻止传入到端口 15008 上 my-appHBONE 流量

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
spec:
  ingress:
  - ports:
    - port: 9090
      protocol: TCP
  podSelector:
    matchLabels:
      app.kubernetes.io/name: my-app

并且应更改为

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
spec:
  ingress:
  - ports:
    - port: 8080
      protocol: TCP
    - port: 15008
      protocol: TCP
  podSelector:
    matchLabels:
      app.kubernetes.io/name: my-app

如果 my-app 被添加到 ambient 网格中。

Ambient、健康探测和 Kubernetes NetworkPolicy

Kubernetes 健康检查探针提出了一个问题,并为 Kubernetes 流量策略总体上创建了一个特殊情况。它们源自作为节点上进程运行的 kubelet,而不是集群中的其他 Pod。它们是明文且不安全的。kubelet 或 Kubernetes 节点通常都没有自己的加密身份,因此无法进行访问控制。仅仅允许健康检查端口上的所有流量通过是不够的,因为恶意流量可以像 kubelet 一样轻松地使用该端口。此外,许多应用程序使用相同的端口进行健康检查和合法应用程序流量,因此简单的基于端口的允许是不可接受的。

各种 CNI 实现以不同的方式解决此问题,并试图通过静默地将 kubelet 健康检查排除在正常的策略执行之外,或为其配置策略例外来解决此问题。

在 Istio ambient 中,此问题通过结合使用 iptables 规则和源网络地址转换 (SNAT) 来解决,以仅重写可证明源自本地节点且具有固定链路本地 IP 的数据包,以便 Istio 策略执行可以显式地将它们忽略为不安全的健康检查流量。链路本地 IP 被选为默认值,因为它们通常被忽略用于入口-出口控制,并且 根据 IETF 标准 无法在本地子网之外路由。

将 Pod 添加到 ambient 网格时,此行为将透明地启用,并且默认情况下,ambient 使用链路本地地址 169.254.7.127 来识别并正确允许 kubelet 健康检查数据包。

但是,如果工作负载、命名空间或集群具有预先存在的入口或出口 NetworkPolicy,则根据您使用的 CNI,具有此链路本地地址的数据包可能会被显式 NetworkPolicy 阻止,这会导致在将 Pod 添加到 ambient 网格时,应用程序 Pod 健康检查开始失败。

例如,在命名空间中应用以下 NetworkPolicy 将阻止所有流量(Istio 或其他流量)到 my-app Pod,包括 kubelet 健康检查。根据您的 CNI,kubelet 探针和链路本地地址可能会被此策略忽略,或者会被其阻止

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: deny-ingress
spec:
  podSelector:
    matchLabels:
      app.kubernetes.io/name: my-app
  policyTypes:
  - Ingress

一旦 Pod 注册到 ambient 网格中,健康检查数据包将开始通过 SNAT 分配链路本地地址,这意味着健康检查可能会开始被您的 CNI 的 NetworkPolicy 实现阻止。为了允许 ambient 健康检查绕过 NetworkPolicy,请通过允许列出 ambient 用于此流量的链路本地地址来显式允许来自主机节点到 Pod 的流量

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: deny-ingress-allow-kubelet-healthprobes
spec:
  podSelector:
    matchLabels:
      app.kubernetes.io/name: my-app
  ingress:
    - from:
      - ipBlock:
          cidr: 169.254.7.127/32
这些信息是否有用?
您是否有任何改进建议?

感谢您的反馈!