k8s- 使用 Network Policies 实现网络隔离
一、需求
Kubernetes 的命名空间主要用于组织和隔离资源,但默认情况下,不同命名空间中的 Pod 之间是可以相互通信的。为了实现更严格的网络隔离,同一套 k8s 需要根据不同的命名空间进行网络环境隔离,例如开发(dev01)测试(test01)环境。Network Policies 是 Kubernetes 提供的一种机制,用于控制 Pod 间的网络流量。你可以为每个命名空间定义 Network Policies 来限制 Pod 之间的通信。
二、相关解释
spec.PodSelector
它是 pod 选择器,基于标签选择与 Network Policy 处于同一 namespace 下的 pod,如果 pod 被选中,则对其应用 Network Policy 中定义的规则。此为可选字段,当没有此字段时,表示选中所有 pod。
spec.PolicyTypes
Network Policy 定义的规则可以分成两种,一种是入 pod 的 Ingress 规则,一种是出 pod 的 Egress 规则。本字段可以看作是一个开关,如果其中包含 Ingress,则 Ingress 部分定义的规则生效,如果是 Egress 则 Egress 部分定义的规则生效,如果都包含则全部生效。当然此字段也可选,如果没有指定的话,则默认 Ingress 生效,如果 Egress 部分有定义的话,Egress 才生效。怎么理解这句话,下文会提到,没有明确定义 Ingress、Egress 部分,它也是一种规则,默认规则而非没有规则。
spec.ingress 与 spec.egress
spec.ingress
和 spec.egress
字段分别用于定义允许进入 Pod 的流量规则和允许离开 Pod 的流量规则。下面详细解释这两个字段的结构和包含的子项。
spec.ingress
结构
spec.egress
结构
示例
假设你有一个 NetworkPolicy,它允许 Pod 接收来自 CIDR 地址范围 192.168.1.0/24
的流量,并允许 Pod 发送流量到 CIDR 地址范围 10.0.0.0/8
,同时只允许通过 TCP 协议的端口 80 和 443 进行通信。
注意事项
适用性: 该 NetworkPolicy 适用于
my-namespace
命名空间中的所有 Pod。流量控制: 控制了 Ingress 和 Egress 流量。
CIDR 地址范围:
192.168.1.0/24
和10.0.0.0/8
通常用于私有网络。端口控制: 只允许通过 TCP 协议的端口 80 和 443 进行通信。
三、测试规划
1、创建命名空间
2、创建 pod 和 nodeport
3、应用策略之前测试
4、创建网络策略 1-pod 隔离
5、创建网络策略 2-命名空间隔离
6、创建网络策略 3-业务命名空间隔离
四、具体实施
1、创建命名空间
创建测试使用的 3 个命名空间 sub1,sub2,sub3。
如果后面的网络策略使用到namespaceSelector,在创建命名空间时需要带label,也可在需要时手动添加label。
如果使用的是私有仓库,注意 ns 要创建 docker-secret。
2、创建 pod 和 nodeport
2.1、sub1 创建 sub1-pod1 和 sub1-pod1-nodeport,sub1-pod2;
2.2、sub2 创建 sub2-pod1 和 sub2-pod1-nodeport,sub2-pod2;
2.3、sub3 创建 sub3-pod1;
查看创建的资源
3、应用策略之前测试
在应用网络策略之前测试各 pod 之间、pod 和外网之间是否可以通信。
sub1-pod1 ping sub1-pod2、sub2-pod1、sub3-pod1、qq.com
外部节点 ping sub1-pod1-nodeport、sub2-pod1-nodeport
取 k8s 集群任一节点 ip 10.34.106.14
总结:通过以上测试证明未加网络策略之前 pod 之间,pod 外网之间都是互通的。
4、创建网络策略 1-pod 隔离
策略描述:在 sub1 中创建策略,使 sub1 中 pod 之间无法通信且和其他命名空间 pod 也无法通信,只能进出外网。测试流程:
4.1、sub1-pod1、sub1-pod2、sub2-pod1 三者之间互 ping 不通;
4.2、sub1-pod1、sub1-pod2 可以 ping 通外网(包含域名),外网也能和 sub1-pod1-nodeport 通信;
本 k8s 集群 pod cidr 为:10.243.0.0/16
解释:
podSelector
:{}
表示选择命名空间中的所有 Pod。ingress
: 定义了进入命名空间的流量控制规则。from
: 表示允许来自哪些来源的流量。ipBlock
: 表示允许来自除了10.243.0.0/16
CIDR 地址范围之外的所有 IP 地址的流量。egress
: 定义了离开命名空间的流量控制规则。to
: 表示允许流向哪些目的地的流量。ipBlock
: 表示允许流向除了10.243.0.0/16
CIDR 地址范围之外的所有 IP 地址的流量。policyTypes
: 指定 NetworkPolicy 控制的流量类型,这里包括Ingress
和Egress
。
效果:
Ingress: 允许所有来源的流量,除了 CIDR 地址范围
10.243.0.0/16
。Egress: 允许流向所有目的地的流量,除了 CIDR 地址范围
10.243.0.0/16
。
测试:
创建策略
sub1-pod1 ping sub1-pod2 和 sub2-pod1 (不通)
sub2-pod1 ping sub1-pod1 和 sub1-pod2(不通)
sub1-pod1 ping 外网 ip(通)
sub1-pod1 ping 域名(不通)-- 因为域名解析服务 dns 在 kube-system 空间,而 sub1 屏蔽了所有空间,下面示例可解决。
外部访问 sub1-pod1-nodeport(通)
取 k8s 集群任一节点 ip 10.34.106.14
5、创建网络策略 2-命名空间隔离
策略描述:在 sub2 中创建策略,使 sub2 中 pod 之间可以通信但和其他命名空间 pod 无法通信,也能进出外网。测试流程:
5.1、sub2-pod1 和 sub2-pod2 之间互 ping 可通;
5.2、sub2-pod1、sub2-pod2 和 sub3-pod1 之间互 ping 不通;
5.3、sub2-pod1、sub2-pod2 可以 ping 通外网(包含域名),外网也能和 sub2-pod1-nodeport 通信;
解释
podSelector
:{}
表示选择命名空间中的所有 Pod。ingress
: 定义了进入命名空间的流量控制规则。from
: 表示允许来自哪些来源的流量。ipBlock
: 表示允许来自除了10.243.0.0/16
CIDR 地址范围之外的所有 IP 地址的流量。namespaceSelector
: 表示允许来自具有标签ns=sub2
的命名空间中的 Pod 的流量。from
字段中的podSelector: {}
表示允许来自同一命名空间中的所有 Pod 的流量。egress
: 定义了离开命名空间的流量控制规则。to
: 表示允许流向哪些目的地的流量。ipBlock
: 表示允许流向除了10.243.0.0/16
CIDR 地址范围之外的所有 IP 地址的流量。namespaceSelector
: 表示允许流向具有标签ns=sub2
的命名空间中的 Pod 的流量。to 字段中的podSelector: {}
表示允许流向同一命名空间中的所有 Pod 的流量。policyTypes
: 指定 NetworkPolicy 控制的流量类型,这里包括Ingress
和Egress
。
效果
Ingress: 允许所有来源的流量,除了 CIDR 地址范围
10.243.0.0/16
和来自其他命名空间的流量,如果使用 namespaceSelector 则允许进入命名空间具有标签ns=sub2中的pod,如果使用podSelector: {}表示允许来自同一命名空间中的所有 Pod 的流量
。
Egress: 允许流向所有目的地的流量,除了 CIDR 地址范围
10.243.0.0/16
和流向其他命名空间的流量,如果使用 namespaceSelector 则允许流向命名空间具有标签ns=sub2中的pod,如果使用podSelector: {}表示允许流向同一命名空间中的所有 Pod 的流量。
测试
创建策略
sub2-pod1 ping sub2-pod2(通)
sub2-pod1 ping sub3-pod1(不通)
sub3-pod1 ping sub2-pod1、sub2-pod2(不通)
sub2-pod1 ping 外网 ip(通)
sub2-pod1 ping 域名(不通)-- 因为域名解析服务 dns 在 kube-system 空间,而 sub1 屏蔽了所有空间,下面示例可解决。
外部 访问 sub2-pod1-nodeport(通)
取 k8s 集群任一节点 ip 10.34.106.14
6、创建网络策略 3-业务命名空间隔离
实际应用中某些命名空间中的 pod 可能和其他命名空间中的 pod 有调用关系,还可能用到一些系统命名空间中的服务(如 DNS 服务),所以不能将某个命名空间完全和其他所有命名空间隔离,只需要将确定没有业务调用的命名空间隔离。
策略描述:更新第 5 步 sub2 中创建的策略,使 sub2 中的 pod 除了不能和 sub3 中的 pod 通信外,和其他所有地址都可通信。
测试流程:
6.1、sub2-pod1 和 sub2-pod2 互 ping 可通;
6.2、sub2-pod1 和 kube-system 命名空间中的 coredns-pod 之间互 ping 可通;
6.3、sub2-pod1 和 sub3-pod1 互 ping 不通;
6.4、sub2-pod1 可以 ping 通外网(域名),外网也能和 sub2-pod1-nodeport 通信;
由于没有直接阻止具有某个 label 的命名空间配置,所有只能间接通过放行具有某些 labels 的命名空间以达到阻止的目的。
label 设置比较灵活,可根据实际情况配置,有一下几种方式可供参考:
1、可以将放行的所有命名空间配置一个统一的 label,这样只需要在配置中放行具有这个 label 的命名空间即可;
2、也可给每个命名空间配置一个 label,这样需要在配置中放行各个不同 label 的命名空间;
3、可以将通用的系统命名空间设置一个统一的 label,给业务命名空间配置不同的 label;
本例采用第 2 种,给所有需要放行的命名空间配置不同的 label;
命名空间加 label
网络隔离配置
解释
podSelector
:{}
表示选择命名空间中的所有 Pod。policyTypes
:Ingress
和Egress
表示同时控制进入和离开命名空间的流量。ingress
:from
字段中的podSelector: {}
表示允许来自同一命名空间中的所有 Pod 的流量;ipBlock
表示允许来自除了 Kubernetes 内部网络 CIDR 地址范围 10.243.0.0/16之外的所有 IP 地址的流量。
egress
:to
字段中的podSelector: {}
表示允许流向同一命名空间中的所有 Pod 的流量;ipBlock
表示允许流向除了 Kubernetes 内部网络 CIDR 地址范围 10.243.0.0/16之外的所有 IP 地址的流量。
from
和to
: 使用namespaceSelector
允许放行具有标签ns=kube-system、ns=kuboardns、ns=kube-public
的命名空间中的 Pod 的流量,间接阻止了其他命名空间的流量。
测试
创建策略
sub2-pod1 ping sub2-pod2(通)
sub2-pod1 ping kube-system 命名空间中的 coredns-pod(通)
sub2-pod1 ping sub3-pod1(不通)
sub2-pod1 可以 ping 通外网、域名(通)
外部 访问 sub2-pod1-nodeport(通)
取 k8s 集群任一节点 ip 10.34.106.14
文章转载自:技术人的菜园子
评论