面向安全专业人员的 Kubernetes 网络策略简介

面向安全专业人员的 Kubernetes 网络策略简介

笔记。 翻译。:本文作者 Reuven Harrison 拥有 20 多年的软件开发经验,如今是 Tufin(一家创建安全策略管理解决方案的公司)的 CTO 和联合创始人。 虽然他将 Kubernetes 网络策略视为集群中网络分段的相当强大的工具,但他也认为它们在实践中并不那么容易使用。 该材料(相当大量)旨在提高专家对此问题的认识,并帮助他们创建必要的配置。

如今,许多公司越来越多地选择 Kubernetes 来运行他们的应用程序。 人们对这款软件的兴趣如此之高,以至于有些人将 Kubernetes 称为“数据中心的新操作系统”。 渐渐地,Kubernetes(或 k8s)开始被视为业务的关键部分,这需要组织成熟的业务流程,包括网络安全。

对于对使用 Kubernetes 感到困惑的安全专业人士来说,真正的启示可能是该平台的默认策略:允许一切。

本指南将帮助您了解网络策略的内部结构; 了解它们与常规防火墙规则有何不同。 它还将涵盖一些陷阱并提供建议,以帮助保护 Kubernetes 上的应用程序。

Kubernetes 网络策略

Kubernetes 网络策略机制允许您在网络层(OSI 模型中的第三层)管理部署在平台上的应用程序的交互。 网络策略缺乏现代防火墙的一些高级功能,例如 OSI 第 7 层实施和威胁检测,但它们提供了基本的网络安全级别,这是一个很好的起点。

网络策略控制 Pod 之间的通信

Kubernetes 中的工作负载分布在 Pod 之间,Pod 由部署在一起的一个或多个容器组成。 Kubernetes 为每个 Pod 分配一个可从其他 Pod 访问的 IP 地址。 Kubernetes 网络策略为 Pod 组设置访问权限,其方式与云中的安全组用于控制对虚拟机实例的访问的方式相同。

定义网络策略

与其他 Kubernetes 资源一样,网络策略在 YAML 中指定。 在下面的示例中,应用程序 balance 进入 postgres:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default.postgres
  namespace: default
spec:
  podSelector:
    matchLabels:
      app: postgres
  ingress:
  - from:
    - podSelector:
        matchLabels:
          app: balance
  policyTypes:
  - Ingress

面向安全专业人员的 Kubernetes 网络策略简介

(笔记。 翻译。:与所有后续类似的屏幕截图一样,该屏幕截图不是使用本机 Kubernetes 工具创建的,而是使用 Tufin Orca 工具创建的,该工具由原始文章作者的公司开发,在材料末尾提到。)

要定义您自己的网络策略,您需要 YAML 的基本知识。 这种语言基于缩进(由空格而不是制表符指定)。 缩进元素属于其上方最近的缩进元素。 新列表元素以连字符开头,所有其他元素均具有以下形式 核心价值.

在 YAML 中描述了策略后,使用 Kubectl在集群中创建它:

kubectl create -f policy.yaml

网络策略规范

Kubernetes网络策略规范包括四个要素:

  1. podSelector:定义受此策略影响的 Pod(目标)- 必需;
  2. policyTypes:指示其中包含哪些类型的策略:入口和/或出口 - 可选,但我建议在所有情况下明确指定它;
  3. ingress: 定义允许的 传入 目标 Pod 的流量 - 可选;
  4. egress: 定义允许的 外向的 来自目标 Pod 的流量是可选的。

示例取自 Kubernetes 网站(我替换为 roleapp),显示了如何使用所有四个元素:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: test-network-policy
  namespace: default
spec:
  podSelector:    # <<<
    matchLabels:
      app: 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

面向安全专业人员的 Kubernetes 网络策略简介
面向安全专业人员的 Kubernetes 网络策略简介

请注意,不必包含所有四个元素。 这只是强制性的 podSelector,可以根据需要使用其他参数。

如果你省略 policyTypes,该政策解读如下:

  • 默认情况下,假设它定义了入口侧。 如果策略没有明确说明这一点,系统将假设所有流量都被禁止。
  • 出口侧的行为将由相应出口参数的存在或不存在来确定。

为了避免错误,我建议 始终明确表达 policyTypes.

根据上面的逻辑,如果参数 ingress 和/或 egress 省略,策略将拒绝所有流量(请参阅下面的“剥离规则”)。

默认策略是允许

如果未定义策略,Kubernetes 默认允许所有流量。 所有 Pod 之间都可以自由交换信息。 从安全角度来看,这似乎有悖常理,但请记住,Kubernetes 最初是由开发人员设计的,旨在实现应用程序的互操作性。 网络策略是后来添加的。

命名空间

命名空间是 Kubernetes 的协作机制。 它们旨在将逻辑环境彼此隔离,同时默认允许空间之间进行通信。

与大多数 Kubernetes 组件一样,网络策略存在于特定的命名空间中。 在街区里 metadata 您可以指定策略属于哪个空间:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: test-network-policy
  namespace: my-namespace  # <<<
spec:
...

如果元数据中没有显式指定命名空间,系统将使用 kubectl 中指定的命名空间(默认情况下) namespace=default):

kubectl apply -n my-namespace -f namespace.yaml

我推荐 显式指定命名空间,除非您正在编写同时针对多个命名空间的策略。

主要 元素 podSelector 策略中的 会从该策略所属的命名空间中选择 pod(拒绝访问其他命名空间的 pod)。

同样,podSelector 在入口和出口块中 只能从自己的命名空间中选择 pod,当然除非您将它们与 namespaceSelector (这将在“按名称空间和 Pod 过滤”部分中讨论)。

策略命名规则

策略名称在同一命名空间内是唯一的。 同一空间中不能存在两个同名的策略,但不同空间中可以存在同名的策略。 当您想要跨多个空间重新应用相同的策略时,这非常有用。

我特别喜欢其中一种命名方法。 它由命名空间名称与目标 Pod 的组合组成。 例如:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default.postgres  # <<<
  namespace: default
spec:
  podSelector:
    matchLabels:
      app: postgres
  ingress:
  - from:
    - podSelector:
        matchLabels:
          app: admin
  policyTypes:
  - Ingress

面向安全专业人员的 Kubernetes 网络策略简介

标签

您可以将自定义标签附加到 Kubernetes 对象,例如 pod 和命名空间。 标签 (标签 - 标签)相当于云中的标签。 Kubernetes网络策略使用标签来选择 豆荚它们适用于:

podSelector:
  matchLabels:
    role: db

… 或者 命名空间它们适用于其中。 此示例选择命名空间中具有相应标签的所有 pod:

namespaceSelector:
  matchLabels:
    project: myproject

一、注意事项:使用时 namespaceSelector 确保您选择的命名空间包含正确的标签。 请注意,内置命名空间,例如 default и kube-system,默认情况下不包含标签。

您可以向空间添加标签,如下所示:

kubectl label namespace default namespace=default

同时,节中的命名空间 metadata 应该指实际的空间名称,而不是标签:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: test-network-policy
  namespace: default   # <<<
spec:
...

来源和目的地

防火墙策略由具有源和目的地的规则组成。 Kubernetes 网络策略是针对目标(它们所应用的一组 Pod)定义的,然后为入口和/或出口流量设置规则。 在我们的示例中,策略的目标将是命名空间中的所有 Pod default 带标签 带钥匙 app 和意义 db:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: test-network-policy
  namespace: default
spec:
  podSelector:
    matchLabels:
      app: 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

面向安全专业人员的 Kubernetes 网络策略简介
面向安全专业人员的 Kubernetes 网络策略简介

小节 ingress 在此策略中,打开到目标 Pod 的传入流量。 换句话说,ingress 是源,target 是相应的目的地。 同样,出口是目的地,目标是源。

面向安全专业人员的 Kubernetes 网络策略简介

这相当于两条防火墙规则:Ingress→Target; 目标 → 出口。

出口和 DNS(重要!)

通过限制传出流量, 特别注意DNS - Kubernetes 使用此服务将服务映射到 IP 地址。 例如,以下策略将不起作用,因为您没有允许该应用程序 balance 访问DNS:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default.balance
  namespace: default
spec:
  podSelector:
    matchLabels:
      app: balance
  egress:
  - to:
    - podSelector:
        matchLabels:
          app: postgres
  policyTypes:
  - Egress

面向安全专业人员的 Kubernetes 网络策略简介

您可以通过打开对 DNS 服务的访问来修复它:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default.balance
  namespace: default
spec:
  podSelector:
    matchLabels:
      app: balance
  egress:
  - to:
    - podSelector:
        matchLabels:
          app: postgres
  - to:               # <<<
    ports:            # <<<
    - protocol: UDP   # <<<
      port: 53        # <<<
  policyTypes:
  - Egress

面向安全专业人员的 Kubernetes 网络策略简介

最后一个元素 to 为空,因此它间接选择 所有命名空间中的所有 pod,允许 balance 将 DNS 查询发送到适当的 Kubernetes 服务(通常在空间中运行) kube-system).

这种方法有效,但是 过于宽容和缺乏安全感,因为它允许将 DNS 查询定向到集群外部。

您可以通过三个连续步骤来改进它。

1.仅允许DNS查询 通过添加聚类 namespaceSelector:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default.balance
  namespace: default
spec:
  podSelector:
    matchLabels:
      app: balance
  egress:
  - to:
    - podSelector:
        matchLabels:
          app: postgres
  - to:
    - namespaceSelector: {} # <<<
    ports:
    - protocol: UDP
      port: 53
  policyTypes:
  - Egress

面向安全专业人员的 Kubernetes 网络策略简介

2. 仅允许命名空间内的 DNS 查询 kube-system.

为此,您需要向命名空间添加标签 kube-system: kubectl label namespace kube-system namespace=kube-system - 并将其写在政策中使用 namespaceSelector:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default.balance
  namespace: default
spec:
  podSelector:
    matchLabels:
      app: balance
  egress:
  - to:
    - podSelector:
        matchLabels:
          app: postgres
  - to:
    - namespaceSelector:         # <<<
        matchLabels:             # <<<
          namespace: kube-system # <<<
    ports:
    - protocol: UDP
      port: 53
  policyTypes:
  - Egress

面向安全专业人员的 Kubernetes 网络策略简介

3. 偏执的人可以更进一步,将 DNS 查询限制到特定的 DNS 服务 kube-system。 “按命名空间和 Pod 过滤”部分将告诉您如何实现这一点。

另一种选择是在命名空间级别解析 DNS。 在这种情况下,不需要为每个服务都打开:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default.dns
  namespace: default
spec:
  podSelector: {} # <<<
  egress:
  - to:
    - namespaceSelector: {}
    ports:
    - protocol: UDP
      port: 53
  policyTypes:
  - Egress

无效 podSelector 选择命名空间中的所有 Pod。

面向安全专业人员的 Kubernetes 网络策略简介

第一场比赛和规则顺序

在传统防火墙中,对数据包的操作(允许或拒绝)由它满足的第一条规则确定。 在 Kubernetes 中,策略的顺序并不重要。

默认情况下,在没有设置策略的情况下,Pod 之间是允许通信的,Pod 之间可以自由地交换信息。 一旦开始制定策略,根据选择它的所有策略的析取(逻辑或),至少受其中一个策略影响的每个 pod 都会被隔离。 不受任何政策影响的 Pod 保持开放状态。

您可以使用剥离规则更改此行为。

剥离规则(“拒绝”)

防火墙策略通常会拒绝任何未明确允许的流量。

Kubernetes 中没有拒绝操作但是,通过选择一组空的源 Pod(入口),可以使用常规(宽松)策略来实现类似的效果:

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

面向安全专业人员的 Kubernetes 网络策略简介

此策略选择命名空间中的所有 pod,并保留未定义的入口,拒绝所有传入流量。

以类似的方式,您可以限制来自命名空间的所有传出流量:

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

面向安全专业人员的 Kubernetes 网络策略简介

请注意 任何允许流量流向命名空间中 pod 的其他策略将优先于此规则 (类似于在防火墙配置中在拒绝规则之前添加允许规则)。

允许一切(任何-任何-任何-允许)

要创建“全部允许”策略,您需要在上面的“拒绝”策略中补充一个空元素 ingress:

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

面向安全专业人员的 Kubernetes 网络策略简介

它允许从以下位置访问 所有命名空间(和所有 IP)中的所有 pod 到命名空间中的任何 pod default。 此行为默认启用,因此通常不需要进一步定义。 但是,有时您可能需要暂时禁用某些特定权限来诊断问题。

规则可以缩小到只允许访问 一组特定的 Pod (app:balance) 在命名空间中 default:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-all-to-balance
  namespace: default
spec:
  podSelector:
    matchLabels:
      app: balance
  ingress: 
  - {}
  policyTypes:
  - Ingress

面向安全专业人员的 Kubernetes 网络策略简介

以下策略允许所有入口和出口流量,包括访问集群外部的任何 IP:

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

面向安全专业人员的 Kubernetes 网络策略简介
面向安全专业人员的 Kubernetes 网络策略简介

结合多种策略

使用逻辑或在三个级别上组合策略; 每个 Pod 的权限都是根据影响它的所有策略的分离来设置的:

1. 在田野里 from и to 可以定义三种类型的元素(所有这些元素都使用 OR 组合):

  • namespaceSelector — 选择整个命名空间;
  • podSelector — 选择 Pod;
  • ipBlock — 选择一个子网。

此外,小节中元素的数量(甚至相同的元素) from/to 不限。 所有这些都将通过逻辑“或”组合起来。

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default.postgres
  namespace: default
spec:
  ingress:
  - from:
    - podSelector:
        matchLabels:
          app: indexer
    - podSelector:
        matchLabels:
          app: admin
  podSelector:
    matchLabels:
      app: postgres
  policyTypes:
  - Ingress

面向安全专业人员的 Kubernetes 网络策略简介

2. 政策部分内部 ingress 可以有很多元素 from (通过逻辑或组合)。 同样,节 egress 可能包含许多元素 to (也可以通过析取组合):

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default.postgres
  namespace: default
spec:
  ingress:
  - from:
    - podSelector:
        matchLabels:
          app: indexer
  - from:
    - podSelector:
        matchLabels:
          app: admin
  podSelector:
    matchLabels:
      app: postgres
  policyTypes:
  - Ingress

面向安全专业人员的 Kubernetes 网络策略简介

3.不同的策略也可以用逻辑OR组合

但将它们结合起来时,有一个限制: 我有 克里斯库尼: Kubernetes 只能将不同的策略结合起来 policyTypes (Ingress или Egress)。 定义入口(或出口)的策略将相互覆盖。

命名空间之间的关系

默认情况下,允许命名空间之间的信息共享。 这可以通过使用拒绝策略来更改,该策略将限制传出和/或传入命名空间的流量(请参阅上面的“剥离规则”)。

一旦您阻止了对命名空间的访问(请参阅上面的“剥离规则”),您可以通过允许来自特定命名空间的连接来对拒绝策略进行例外处理: namespaceSelector:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: database.postgres
  namespace: database
spec:
  podSelector:
    matchLabels:
      app: postgres
  ingress:
  - from:
    - namespaceSelector: # <<<
        matchLabels:
          namespace: default
  policyTypes:
  - Ingress

面向安全专业人员的 Kubernetes 网络策略简介

结果,命名空间中的所有 pod default 将有权访问 pod postgres 在命名空间中 database。 但是,如果您想开放访问权限怎么办? postgres 仅命名空间中的特定 pod default?

按命名空间和 Pod 过滤

Kubernetes 1.11 及更高版本允许您组合运算符 namespaceSelector и podSelector 使用逻辑与。它看起来像这样:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: database.postgres
  namespace: database
spec:
  podSelector:
    matchLabels:
      app: postgres
  ingress:
  - from:
    - namespaceSelector:
        matchLabels:
          namespace: default
      podSelector: # <<<
        matchLabels:
          app: admin
  policyTypes:
  - Ingress

面向安全专业人员的 Kubernetes 网络策略简介

为什么这被解释为 AND 而不是通常的 OR?

请注意, podSelector 不以连字符开头。 在 YAML 中这意味着 podSelector 并站在他面前 namespaceSelector 引用相同的列表元素。 因此,它们通过逻辑 AND 进行组合。

前面加一个连字符 podSelector 将导致出现一个新的列表元素,该元素将与前一个元素合并 namespaceSelector 使用逻辑或。

选择具有特定标签的 Pod 在所有命名空间中, 输入空白 namespaceSelector:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: database.postgres
  namespace: database
spec:
  podSelector:
    matchLabels:
      app: postgres
  ingress:
  - from:
    - namespaceSelector: {}
      podSelector:
        matchLabels:
          app: admin
  policyTypes:
  - Ingress

面向安全专业人员的 Kubernetes 网络策略简介

多个厂牌与I联手

具有多个对象(主机、网络、组)的防火墙的规则使用逻辑“或”进行组合。 如果数据包源匹配,则以下规则将起作用 Host_1Host_2:

| Source | Destination | Service | Action |
| ----------------------------------------|
| Host_1 | Subnet_A    | HTTPS   | Allow  |
| Host_2 |             |         |        |
| ----------------------------------------|

相反,在 Kubernetes 中的各种标签 podSelector или namespaceSelector 用逻辑 AND 组合。例如,以下规则将选择具有两个标签的 pod, role=db И version=v2:

podSelector:
  matchLabels:
    role: db
    version: v2

相同的逻辑适用于所有类型的运算符:策略目标选择器、pod 选择器和命名空间选择器。

子网和 IP 地址 (IPBlock)

防火墙使用 VLAN、IP 地址和子网来划分网络。

在 Kubernetes 中,IP 地址会自动分配给 pod,并且可能会经常更改,因此标签用于在网络策略中选择 pod 和命名空间。

子网(ipBlocks)在管理传入(入口)或传出(出口)外部(南北)连接时使用。 例如,此策略向命名空间中的所有 pod 开放 default 访问Google DNS服务:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: egress-dns
  namespace: default
spec:
  podSelector: {}
  policyTypes:
  - Egress
  egress:
  - to:
    - ipBlock:
        cidr: 8.8.8.8/32
    ports:
    - protocol: UDP
      port: 53

面向安全专业人员的 Kubernetes 网络策略简介

此示例中的空 pod 选择器意味着“选择命名空间中的所有 pod”。

该策略仅允许访问8.8.8.8; 禁止访问任何其他IP。 因此,本质上,您已经阻止了对内部 Kubernetes DNS 服务的访问。 如果您仍想打开它,请明确指出。

平时 ipBlocks и podSelectors 是互斥的,因为 Pod 的内部 IP 地址不用于 ipBlocks。 通过指示 内部 IP Pod,您实际上将允许使用这些地址与 pod 进行连接。 在实践中,您不知道要使用哪个 IP 地址,这就是为什么它们不应该用于选择 pod。

作为反例,以下策略包含所有 IP,因此允许访问所有其他 Pod:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: egress-any
  namespace: default
spec:
  podSelector: {}
  policyTypes:
  - Egress
  egress:
  - to:
    - ipBlock:
        cidr: 0.0.0.0/0

面向安全专业人员的 Kubernetes 网络策略简介

您只能开放对外部IP的访问,不包括Pod的内部IP地址。 例如,如果您的 Pod 的子网是 10.16.0.0/14:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: egress-any
  namespace: default
spec:
  podSelector: {}
  policyTypes:
  - Egress
  egress:
  - to:
    - ipBlock:
        cidr: 0.0.0.0/0
        except:
        - 10.16.0.0/14

面向安全专业人员的 Kubernetes 网络策略简介

端口和协议

通常 Pod 会监听一个端口。 这意味着您可以简单地不在策略中指定端口号并将所有内容保留为默认值。 但是,建议尽可能限制策略,因此在某些情况下您仍然可以指定端口:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default.postgres
  namespace: default
spec:
  ingress:
  - from:
    - podSelector:
        matchLabels:
          app: indexer
    - podSelector:
        matchLabels:
          app: admin
    ports:             # <<<
      - port: 443      # <<<
        protocol: TCP  # <<<
      - port: 80       # <<<
        protocol: TCP  # <<<
  podSelector:
    matchLabels:
      app: postgres
  policyTypes:
  - Ingress

面向安全专业人员的 Kubernetes 网络策略简介

请注意选择器 ports 适用于块中的所有元素 to или from, 其中包含。 要为不同的元素集指定不同的端口,请拆分 ingress или egress 分为几个小节 to или from 并在每个寄存器中您的端口:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default.postgres
  namespace: default
spec:
  ingress:
  - from:
    - podSelector:
        matchLabels:
          app: indexer
    ports:             # <<<
     - port: 443       # <<<
       protocol: TCP   # <<<
  - from:
    - podSelector:
        matchLabels:
          app: admin
    ports:             # <<<
     - port: 80        # <<<
       protocol: TCP   # <<<
  podSelector:
    matchLabels:
      app: postgres
  policyTypes:
  - Ingress

面向安全专业人员的 Kubernetes 网络策略简介

默认端口操作:

  • 如果完全省略端口定义(ports),这意味着所有协议和所有端口;
  • 如果省略协议定义(protocol),这表示 TCP;
  • 如果省略端口定义 (port),这意味着所有端口。

最佳实践:不要依赖默认值,明确指定您需要的内容。

请注意,您必须使用 Pod 端口,而不是服务端口(下一段将详细介绍)。

是否为 Pod 或服务定义了策略?

通常,Kubernetes 中的 Pod 通过服务相互访问 - 一个虚拟负载均衡器,它将流量重定向到实现该服务的 Pod。 您可能认为网络策略控制对服务的访问,但事实并非如此。 Kubernetes 网络策略适用于 pod 端口,而不是服务端口。

例如,如果服务侦听端口 80,但将流量重定向到其 pod 的端口 8080,则必须在网络策略中准确指定 8080。

这样的机制应该被认为是次优的:如果服务的内部结构(pod 监听的端口)发生变化,则网络策略将必须更新。

使用服务网格的新架构方法 (例如,请参阅下面有关 Istio 的内容 - 大约翻译) 让您能够应对这个问题。

是否需要同时注册Ingress和Egress?

简而言之,答案是肯定的,为了让 pod A 与 pod B 通信,必须允许它创建传出连接(为此,您需要配置出口策略),并且 pod B 必须能够接受传入连接(因此,为此,您需要一个入口策略)。策略)。

然而,实际上,您可以依靠默认策略来允许一个或两个方向的连接。

如果有一些 pod- 将被一个或多个选择 出口-政客们,对其施加的限制将由他们的分离决定。 在这种情况下,您需要明确允许连接到 pod -致收件人。 如果某个 Pod 未被任何策略选择,则默认允许其传出(出口)流量。

同样,pod 的命运是收件人,由一个或多个选择 进入——政治家,将由他们的脱节决定。 在这种情况下,您必须明确允许它接收来自源 Pod 的流量。 如果某个 Pod 未被任何策略选择,则默认情况下允许该 Pod 的所有入口流量。

请参阅下面的有状态或无状态。

日志

Kubernetes 网络策略无法记录流量。 这使得很难确定策略是否按预期发挥作用,并使安全分析变得非常复杂。

控制外部服务的流量

Kubernetes 网络策略不允许您在出口部分指定完全限定域名 (DNS)。 当尝试限制流向没有固定 IP 地址的外部目标(例如 aws.com)时,这一事实会带来极大的不便。

政策检查

防火墙会警告您甚至拒绝接受错误的策略。 Kubernetes 也做了一些验证。 当通过 kubectl 设置网络策略时,Kubernetes 可能会声明它不正确并拒绝接受。 在其他情况下,Kubernetes 将采用该策略并填写缺失的详细信息。 可以使用以下命令查看它们:

kubernetes get networkpolicy <policy-name> -o yaml

请记住,Kubernetes 验证系统并非绝对可靠,可能会遗漏某些类型的错误。

执行

Kubernetes 本身并不实现网络策略,而只是一个 API 网关,它将控制负担委托给称为容器网络接口 (CNI) 的底层系统。 在 Kubernetes 集群上设置策略而不分配适当的 CNI 与在防火墙管理服务器上创建策略而不将其安装在防火墙上相同。 您需要确保拥有合适的 CNI,或者在 Kubernetes 平台的情况下,托管在云中 (您可以看到提供商列表 这里 — 大约。 译),启用将为您设置 CNI 的网络策略。

请注意,如果您在没有适当的辅助 CNI 的情况下设置网络策略,Kubernetes 不会向您发出警告。

有状态还是无状态?

我遇到的所有 Kubernetes CNI 都是有状态的(例如,Calico 使用 Linux conntrack)。 这允许 Pod 接收其发起的 TCP 连接上的响应,而无需重新建立它。 但是,我不知道 Kubernetes 标准可以保证状态性。

高级安全策略管理

以下是改进 Kubernetes 中安全策略执行的一些方法:

  1. Service Mesh 架构模式使用 sidecar 容器在服务级别提供详细的遥测和流量控制。 我们可以举个例子 Istio.
  2. 一些 CNI 供应商已经扩展了他们的工具,使其超出了 Kubernetes 网络策略的范围。
  3. 图芬虎鲸 提供 Kubernetes 网络策略的可见性和自动化。

Tufin Orca 包管理 Kubernetes 网络策略(也是上面屏幕截图的来源)。

更多信息

结论

Kubernetes 网络策略提供了一套很好的工具来分割集群,但它们并不直观,并且有很多微妙之处。 由于这种复杂性,我相信许多现有的集群策略都存在缺陷。 此问题的可能解决方案包括自动化策略定义或使用其他分段工具。

我希望本指南有助于澄清一些问题并解决您可能遇到的问题。

译者PS

另请阅读我们的博客:

来源: habr.com

添加评论