43

浅析 Kubernetes原生NetworkPolicy 网络策略,让更安全的容器运行环境唾手可得

 4 years ago
source link: https://www.tuicool.com/articles/rUrQ3qm
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

vaai2mN.jpg!web

k8s中的网络策略主要分为原生 NetworkPolicy 和第三方网络插件提供的网络策略。本文将主要分析原生Networkpolicy的网络策略。

什么是网络策略

网络策略(NetworkPolicy)是一种关于 Pod 间及 Pod 与其他网络端点间所允许的通信规则的规范。NetworkPolicy 资源使用标签选择 Pod,并定义选定 Pod 所允许的通信规则。

k8s中的网络策略由实现了[CNI接口](https://github.com/containernetworking/cni/blob/master/SPEC.md#container-networking-interface-specification)的网络插件提供,网络插件监听集群中 NetworkPolicy 资源的创建/删除/更新事件生成对应的规则来控制 Pod 的流量是否放行。

常见的支持 NetworkPolicy 的网络插件有:

- Calico

- Cilium

- Kube-router

- Romana

- Weave Net

默认情况下 Pod 间及 Pod 与其他网络端点间的访问是没有限制的。

如下是一个 NetworkPolicy 定义的例子,该策略的含义是阻止所有流量访问有`app=web`这个 label 的 Pod。

B77b2qa.png!web

经常有人会问网络策略要怎么写,或者是这个网络策略代表了什么含义。笔者认为这个问题主要是因为使用者不了解网络策略的省缺行为。

NetworkPolicy 字段含义

NetworkPolicy 这个资源属于命名空间级别的,因此metadata 中的 namespace 不可省略,否则只会对default 命名空间下的满足条件的 Pod 生效。

下面介绍下 NetworkPolicy 中各字段的含义,并说明各字段省缺值及其含义,主要看 [Spec](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.14/#networkpolicyspec-v1-networking-k8s-io) 中的字段,

podSelector : 必填字段,Pod 的标签选择器,表示该网络策略作用于哪些 Pod。如果为空`{}`则表示选中本命名空间下所有 Pod。

policyTypes : 可选字段,字符串,策略规则类型, 表示该网络策略中包含哪些类型的策略,可选为"Ingress", "Egress", 或 "Ingress,Egress"。未填时,这个值依据下面的 ingress 和 egress 来定。如果该字段未设置且下面只出现了 ingress,则对 egress 不做限制。如果填了这个值,同时后续没有设定对应的规则,则认为设定的规则对应的流量全部禁止。例如:

Jf6FveF.png!web

该规则就限制了所有 Pod 的出流量。

ingress: 可选字段,数组,入站规则。互相间为或的关系,满足其中一条则放行。

  • ports : 可选字段,数组,放行端口信息。互相间为或的关系,如果为空表示端口不受约束,如果非空,则表示除了出现的端口放行,其他未指定的端口都禁止。

-port: 可选字段,数字,协议端口号。如果不写,表示协议所有端口。

-protocol: 可选字段,字符串,协议。允许取值为 TCP,UDP,SCTP。省缺为 TCP。

  • from: 可选字段,数组,放行源地址信息。互相间为或的关系,如果为空表示不约束源地址,如果非空,则表示除了出现的源地址放行外,其他源地址都禁止。

-ipBlock: 可选字段,放行 ip 段。

cidr: 标准 cidr,除了指定的cidr放行外其他都禁止。

except: 标准 cidr 字符串数组,表示前面cidr 中的放行的 cidr 段需要再排除掉 except 中指定的。

-namespaceSelector: 可选字段,namespace 的标签选择器,表示放行集群中的哪些命名空间中过来的流量。如果为空`{}`或未出现则表示选中所有命名空间。

-podSelector: 可选字段,Pod 的标签选择器,表示放行哪些 Pod 过来的流量,默认情况下从NetworkPolicy 同命名空间下的 Pod 中做筛选,如果前面设定了`namespaceSelector`则从符合条件的命名空间中的 Pod 中做筛选。如果为空`{}`则表示选中满足`namespaceSelector` 条件的所有 Pod。

egress: 可选字段,数组,出站规则。互相间为或的关系,满足其中一条就放行。

  • ports: 可选字段,数组,放行端口信息。互相间为或的关系,如果为空表示端口不受约束,如果非空,则表示除了出现的端口放行,其他未指定的端口都禁止。(详细字段同 ingress 中的 ports)

  • to: 可选字段,数组,放行目的地址信息。互相间为或的关系,如果为空表示不约束目的,如果非空,则表示除了出现的目的地址放行外,其他目的地址都禁止。(详细字段同ingress 中的 from)

介绍完 [Spec](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.14/#networkpolicyspec-v1-networking-k8s-io) 中各字段的含义及其默认行为后,做个简单的小结,NetworkPolicy 定义了放行规则,规则间是或的关系,只要命中其中一条规则就认为流量可以放行。

下面以一个[kubernetes官网](https://kubernetes.io/docs/concepts/services-networking/network-policies/#behavior-of-to-and-from-selectors)中的例子来回顾下前面的知识。

uIBz2qN.jpg!web

首先该规则指定了命名空间为 default, 选择了其中所有包含 `role=db` 这个 label 的 Pod,定义了入站流量规则与出站流量规则。

对于入站流量,放行源地址来自 cidr 172.17.0.0/16 除了 172.17.1.0/24 之外的流量,放行来自有`project=myproject` 这个label的namespace中的流量,放行 default 命名空间下有 label `role=frontend` 的 Pod 的流量,并限定这些流量只能访问到 `role=db` 这个 label 的 Pod 的 TCP 6379端口。

对于出站流量,只放行其访问目的地址属于 cidr 10.0.0.0/24 中,且端口为 TCP 5978的流量。

需要注意的是 NetworkPolicy 选中的 Pod 只能是与 NetworkPolicy 同处一个 namespace 中的 Pod,因此对于有些规则可能需要在多个命名空间中分别设置。或者使用非原生的网络策略定义,例如 Calico 中的 [GlobalNetworkPolicy](https://docs.projectcalico.org/v3.7/reference/calicoctl/resources/globalnetworkpolicy)。

NetworkPolicy 变更历史

v1.6 以及以前的版本需要在 kube-apiserver 中开启 extensions/v1beta1/networkpolicies;

v1.7 版本 Network Policy 已经 GA,API 版本为 networking.k8s.io/v1;

v1.8 版本新增 Egress 和 IPBlock 的支持;

- 推荐观看[Securing Cluster Networking with Network Policies - Ahmet Balkan, Google](https://www.youtube.com/watch?v=3gGpMmYeEO8)

- 一些常见的策略样例[ahmetb/kubernetes-network-policy-recipes](https://github.com/ahmetb/kubernetes-network-policy-recipes)


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK