阅读 245

K8S的NetworkPolicy

K8S的NetworkPolicy是定义一组POD之间网络连接的规则,默认情况POD之间是允许所有流量的进入和进出。

NetworPolicy讲解

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
复制代码

必填字段: 与所有其他的 Kubernetes 配置一样,NetworkPolicy 需要 apiVersion、kind 和 metadata 字段。

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

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

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

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

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

所以,该网络策略示例:

  • 隔离 "default" 命名空间下 "role=db" 的 Pod (如果它们不是已经被隔离的话)。
  • (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)
  • (Egress 规则)允许从带有 "role=db" 标签的命名空间下的任何 Pod 到 CIDR 10.0.0.0/24 下 5978 TCP 端口的连接。

选择器 to 和 from 的行为

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

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

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

namespaceSelector 和 podSelector: 一个指定 namespaceSelector 和 podSelector 的 to/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 的策略的约束。

demo

  • networkpolicy
[root@node43 networkpolicy]# cat networkpolicy.yaml 
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: test-network-policy
  namespace: default
spec:
  podSelector:
    matchLabels:
      app: myapp
  policyTypes:
  - Ingress
  ingress:
  - from:
    - podSelector:
        matchLabels:
          role: test
复制代码
  • 标签带有role:test的pod
[root@node43 networkpolicy]# cat centos.yaml 
apiVersion: v1
kind: Pod
metadata:
  name: networkpolicy-test 
  labels:
    role: test
spec:
  containers:
  - image: centos:7.5.1804 
    name: centos 
    command: [ "sleep", "1000000" ]
    imagePullPolicy: "IfNotPresent"
复制代码
  • 标签不带role:test的pod
[root@node43 networkpolicy]# cat unnework-centos.yaml 
apiVersion: v1
kind: Pod
metadata:
  name: unnetworkpolicy-test 
  labels:
    role: unnetwork
spec:
  containers:
  - image: centos:7.5.1804 
    name: centos 
    command: [ "sleep", "1000000" ]
    imagePullPolicy: "IfNotPresent"
复制代码
  • 测试
[root@node43 networkpolicy]# kubectl  get pod --show-labels | grep role
networkpolicy-test                        1/1     Running     0          3h53m   role=test
unnetworkpolicy-test                      1/1     Running     0          3h41m   role=unnetwork

[root@node43 networkpolicy]# kubectl  exec -it networkpolicy-test curl 10.42.0.14
Hello MyApp | Version: v2 | <a href="hostname.html">Pod Name</a>

[root@node43 networkpolicy]# kubectl  exec -it unnetworkpolicy-test curl 10.42.0.14
curl: (7) Failed connect to 10.42.0.14:80; Connection timed out
复制代码

podSelector上再添加新的labes,如下

...
ingress:
  - from:
    - podSelector:
        matchLabels:
          role: test     
    - podSelector:
        matchLabels:
          role: unnetwork 
复制代码

测试结果如下:

[root@node43 networkpolicy]# kubectl  exec -it unnetworkpolicy-test curl 10.42.0.14
Hello MyApp | Version: v2 | <a href="hostname.html">Pod Name</a>
复制代码

在条件ports的显示,如下:

ingress:
  - from:
    - podSelector:
        matchLabels:
          role: test
    - podSelector:
        matchLabels:
          role: unnetwork
    ports:
    - protocol: TCP
      port: 8080
复制代码

测试结果如下:

[root@node43 networkpolicy]# kubectl  exec -it unnetworkpolicy-test curl 10.42.0.14
^Ccommand terminated with exit code 130
[root@node43 networkpolicy]# kubectl  exec -it networkpolicy-test curl 10.42.0.14
^Ccommand terminated with exit code 130
[root@node43 networkpolicy]# 
复制代码

无论是role=test或是role=unnetwork都不能访问,因为只允许访问标签为app=myapp pod的8080端口

后记

NetworkPolicy属于namespace下面的资源,在同一个namespace下可以定义多个networkpolicy,但是以最为严格的策略为准。

比如,策略A允许所有的ingress流量,策略B不允许所有的ingress流量,则以策略B为准,所有流量将不能进入。

文章分类
后端
文章标签