网络策略

网络策略(NetworkPolicy)是一种关于 Pod 间及与其他网络端点间所允许的通信规则的规范。

NetworkPolicy 资源使用 标签 选择 Pod,并定义选定 Pod 所允许的通信规则。

前提

网络策略通过网络插件 来实现。要使用网络策略,用户必须使用支持 NetworkPolicy 的网络解决方案。 创建一个资源对象,而没有控制器来使它生效的话,是没有任何作用的。

隔离和非隔离的 Pod

默认情况下,Pod 是非隔离的,它们接受任何来源的流量。

Pod 可以通过相关的网络策略进行隔离。一旦命名空间中有网络策略选择了特定的 Pod, 该 Pod 会拒绝网络策略所不允许的连接。 (命名空间下其他未被网络策略所选择的 Pod 会继续接收所有的流量)

网络策略不会冲突,它们是累积的。 如果任何一个或多个策略选择了一个 Pod, 则该 Pod 受限于这些策略的 ingress/egress 规则的并集。因此评估的顺序并不会影响策略的结果。

NetworkPolicy 资源

查看 NetworkPolicy 来了解完整的资源定义。

下面是一个 NetworkPolicy 的示例:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: test-network-policy
  namespace: default
spec:
  podSelector:
    matchLabels:
      role: db
  policyTypes:
  - Ingress
  - Egress
  ingress:
  - from:
    - ipBlock:
        cidr: 172.17.0.0/16
        except:
        - 172.17.1.0/24
    - namespaceSelector:
        matchLabels:
          project: myproject
    - podSelector:
        matchLabels:
          role: frontend
    ports:
    - protocol: TCP
      port: 6379
  egress:
  - to:
    - ipBlock:
        cidr: 10.0.0.0/24
    ports:
    - protocol: TCP
      port: 5978
说明: 除非选择支持网络策略的网络解决方案,否则将上述示例发送到API服务器没有任何效果。

必填字段: 与所有其他的 Kubernetes 配置一样,NetworkPolicy 需要 apiVersionkindmetadata 字段。 关于配置文件操作的一般信息,请参考 使用 ConfigMap 配置容器, 和对象管理

spec: NetworkPolicy 规约 中包含了在一个命名空间中定义特定网络策略所需的所有信息。

podSelector: 每个 NetworkPolicy 都包括一个 podSelector ,它对该策略所应用的一组 Pod 进行选择。示例中的策略选择带有 "role=db" 标签的 Pod。空的 podSelector 选择命名空间下的所有 Pod。

policyTypes: 每个 NetworkPolicy 都包含一个 policyTypes 列表,其中包含 IngressEgress 或两者兼具。policyTypes 字段表示给定的策略是否应用于进入所选 Pod 的入口流量或者来自所选 Pod 的出口流量,或两者兼有。如果 NetworkPolicy 未指定 policyTypes 则默认情况下始终设置 Ingress,如果 NetworkPolicy 有任何出口规则的话则设置 Egress

ingress: 每个 NetworkPolicy 可包含一个 ingress 规则的白名单列表。每个规则都允许同时匹配 fromports 部分的流量。示例策略中包含一条简单的规则: 它匹配一个单一的端口,来自三个来源中的一个, 第一个通过 ipBlock 指定,第二个通过 namespaceSelector 指定,第三个通过 podSelector 指定。

egress: 每个 NetworkPolicy 可包含一个 egress 规则的白名单列表。每个规则都允许匹配 toport 部分的流量。该示例策略包含一条规则,该规则将单个端口上的流量匹配到 10.0.0.0/24 中的任何目的地。

所以,该网络策略示例:

  1. 隔离 "default" 命名空间下 "role=db" 的 Pod (如果它们不是已经被隔离的话)。
  2. (Ingress 规则)允许以下 Pod 连接到 "default" 命名空间下的带有 “role=db” 标签的所有 Pod 的 6379 TCP 端口:
  • "default" 命名空间下任意带有 "role=frontend" 标签的 Pod
  • 带有 "project=myproject" 标签的任意命名空间中的 Pod
  • IP 地址范围为 172.17.0.0–172.17.0.255 和 172.17.2.0–172.17.255.255(即,除了 172.17.1.0/24 之外的所有 172.17.0.0/16)
  1. (Egress 规则)允许从带有 "role=db" 标签的命名空间下的任何 Pod 到 CIDR 10.0.0.0/24 下 5978 TCP 端口的连接。

查看声明网络策略 来进行更多的示例演练。

选择器 tofrom 的行为

可以在 ingress from 部分或 egress to 部分中指定四种选择器:

podSelector: 这将在与 NetworkPolicy 相同的命名空间中选择特定的 Pod,应将其允许作为入口源或出口目的地。

namespaceSelector: 这将选择特定的命名空间,应将所有 Pod 用作其输入源或输出目的地。

namespaceSelector podSelector: 一个指定 namespaceSelectorpodSelectorto/from 条目选择特定命名空间中的特定 Pod。注意使用正确的 YAML 语法;这项策略:

  ...
  ingress:
  - from:
    - namespaceSelector:
        matchLabels:
          user: alice
      podSelector:
        matchLabels:
          role: client
  ...

from 数组中仅包含一个元素,只允许来自标有 role=client 的 Pod 且该 Pod 所在的命名空间中标有 user=alice 的连接。但是 这项 策略:

  ...
  ingress:
  - from:
    - namespaceSelector:
        matchLabels:
          user: alice
    - podSelector:
        matchLabels:
          role: client
  ...

from 数组中包含两个元素,允许来自本地命名空间中标有 role=client 的 Pod 的连接, 来自任何命名空间中标有 user = alice 的任何 Pod 的连接。

如有疑问,请使用 kubectl describe 查看 Kubernetes 如何解释该策略。

ipBlock: 这将选择特定的 IP CIDR 范围以用作入口源或出口目的地。 这些应该是群集外部 IP,因为 Pod IP 存在时间短暂的且随机产生。

群集的入口和出口机制通常需要重写数据包的源 IP 或目标 IP。在发生这种情况的情况下,不确定在 NetworkPolicy 处理之前还是之后发生,并且对于网络插件,云提供商,Service 实现等的不同组合,其行为可能会有所不同。

在进入的情况下,这意味着在某些情况下,您可以根据实际的原始源 IP 过滤传入的数据包,而在其他情况下,NetworkPolicy 所作用的 源IP 则可能是 LoadBalancer 或 Pod 的节点等。

对于出口,这意味着从 Pod 到被重写为集群外部 IP 的 Service IP 的连接可能会或可能不会受到基于 ipBlock 的策略的约束。

默认策略

默认情况下,如果命名空间中不存在任何策略,则所有进出该命名空间中的 Pod 的流量都被允许。以下示例使您可以更改该命名空间中的默认行为。

默认拒绝所有入口流量

您可以通过创建选择所有容器但不允许任何进入这些容器的入口流量的 NetworkPolicy 来为命名空间创建 "default" 隔离策略。

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default-deny-ingress
spec:
  podSelector: {}
  policyTypes:
  - Ingress

这样可以确保即使容器没有选择其他任何 NetworkPolicy,也仍然可以被隔离。此策略不会更改默认的出口隔离行为。

默认允许所有入口流量

如果要允许所有流量进入某个命名空间中的所有 Pod(即使添加了导致某些 Pod 被视为“隔离”的策略),则可以创建一个策略来明确允许该命名空间中的所有流量。

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-all-ingress
spec:
  podSelector: {}
  ingress:
  - {}
  policyTypes:
  - Ingress

默认拒绝所有出口流量

您可以通过创建选择所有容器但不允许来自这些容器的任何出口流量的 NetworkPolicy 来为命名空间创建 "default" egress 隔离策略。

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default-deny-egress
spec:
  podSelector: {}
  policyTypes:
  - Egress

这样可以确保即使没有被其他任何 NetworkPolicy 选择的 Pod 也不会被允许流出流量。此策略不会更改默认的 ingress 隔离行为。

默认允许所有出口流量

如果要允许来自命名空间中所有 Pod 的所有流量(即使添加了导致某些 Pod 被视为“隔离”的策略),则可以创建一个策略,该策略明确允许该命名空间中的所有出口流量。

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-all-egress
spec:
  podSelector: {}
  egress:
  - {}
  policyTypes:
  - Egress

默认拒绝所有入口和所有出口流量

您可以为命名空间创建 "default" 策略,以通过在该命名空间中创建以下 NetworkPolicy 来阻止所有入站和出站流量。

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default-deny-all
spec:
  podSelector: {}
  policyTypes:
  - Ingress
  - Egress

这样可以确保即使没有被其他任何 NetworkPolicy 选择的 Pod 也不会被允许进入或流出流量。

SCTP 支持

FEATURE STATE: Kubernetes v1.12 [alpha]

要启用此特性,你(或你的集群管理员)需要通过为 API server 指定 --feature-gates=SCTPSupport=true,… 来启用 SCTPSupport 特性门控。 启用该特性开关后,用户可以将 NetworkPolicy 的 protocol 字段设置为 SCTP

说明: 必须使用支持 SCTP 协议网络策略的 CNI 插件。

接下来

  • 查看 声明网络策略 来进行更多的示例演练
  • 有关 NetworkPolicy 资源启用的常见场景的更多信息,请参见 此指南
最后修改 July 31, 2020 at 1:57 PM PST: [zh] Fix links in concepts section (9f7414e73)