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
结构
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | spec: ingress: - from : - podSelector: matchLabels: {} # 选择具有特定标签的 Pod - namespaceSelector: matchLabels: {} # 选择具有特定标签的命名空间 - ipBlock: cidr: 0.0.0.0/0 # CIDR 地址范围 except: - 10.0.0.0/8 # 排除的 CIDR 地址范围 - ports: - protocol: TCP # 协议类型 port: 80 # 具体端口 endPort: 8080 # 如果是端口范围,则需要指定结束端口 |
spec.egress
结构
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | spec: egress: - to: - podSelector: matchLabels: {} # 选择具有特定标签的 Pod - namespaceSelector: matchLabels: {} # 选择具有特定标签的命名空间 - ipBlock: cidr: 0.0.0.0/0 # CIDR 地址范围 except: - 10.0.0.0/8 # 排除的 CIDR 地址范围 - ports: - protocol: TCP # 协议类型 port: 80 # 具体端口 endPort: 8080 # 如果是端口范围,则需要指定结束端口 |
示例
假设你有一个 NetworkPolicy,它允许 Pod 接收来自 CIDR 地址范围 192.168.1.0/24
的流量,并允许 Pod 发送流量到 CIDR 地址范围 10.0.0.0/8
,同时只允许通过 TCP 协议的端口 80 和 443 进行通信。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: name: allow-traffic namespace : my- namespace spec: podSelector: {} ingress: - from : - ipBlock: cidr: 192.168.1.0/24 - ports: - protocol: TCP port: 80 - protocol: TCP port: 443 egress: - to: - ipBlock: cidr: 10.0.0.0/8 - ports: - protocol: TCP port: 80 - protocol: TCP port: 443 policyTypes: - Ingress - Egress |
注意事项
- 适用性: 该 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。
1 2 3 | kubectl create ns sub1 --labels ns=sub1 kubectl create ns sub2 --labels ns=sub2 kubectl create ns sub3 --labels ns=sub3 |
如果使用的是私有仓库,注意ns要创建docker-secret。
1 | kubectl create secret docker-registry my-registry-secret --docker-server=DOCKER_REGISTRY_SERVER --docker-username=DOCKER_USER --docker-password=DOCKER_PASSWORD -n namespace |
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;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 | apiVersion: apps/v1 kind: Deployment metadata: name: sub1-pod1 namespace : sub1 spec: selector: matchLabels: app: sub1pod1 replicas: 1 template: metadata: labels: app: sub1pod1 spec: containers: - name: my-test01-01 image: swr.cn-east-3.myhuaweicloud.com/k8s-imgs/account-platform-admin:dev01-084e7d9 imagePullPolicy: IfNotPresent imagePullSecrets: - name: default -secret imagePullSecrets: - name: swr-secret --- apiVersion: v1 kind: Service metadata: name: sub1-pod1-nodeport namespace : sub1 spec: type: NodePort selector: app: sub1pod1 ports: - protocol: TCP port: 80 targetPort: 8103 nodePort: 32700 --- apiVersion: apps/v1 kind: Deployment metadata: name: sub1-pod2 namespace : sub1 spec: selector: matchLabels: app: sub1pod2 replicas: 1 template: metadata: labels: app: sub1pod2 spec: containers: - name: my-test01-02 image: swr.cn-east-3.myhuaweicloud.com/k8s-imgs/account-platform-admin:dev01-084e7d9 imagePullPolicy: IfNotPresent imagePullSecrets: - name: default -secret imagePullSecrets: - name: swr-secret --- apiVersion: apps/v1 kind: Deployment metadata: name: sub2-pod1 namespace : sub2 spec: selector: matchLabels: app: sub2pod1 replicas: 1 template: metadata: labels: app: sub2pod1 spec: containers: - name: my-test02-01 image: swr.cn-east-3.myhuaweicloud.com/k8s-imgs/account-platform-admin:dev01-084e7d9 imagePullPolicy: IfNotPresent imagePullSecrets: - name: default -secret imagePullSecrets: - name: swr-secret --- apiVersion: v1 kind: Service metadata: name: sub2-pod1-nodeport namespace : sub2 spec: type: NodePort selector: app: sub2pod1 ports: - protocol: TCP port: 80 targetPort: 8103 nodePort: 32701 --- apiVersion: apps/v1 kind: Deployment metadata: name: sub2-pod2 namespace : sub2 spec: selector: matchLabels: app: sub2pod2 replicas: 1 template: metadata: labels: app: sub2pod2 spec: containers: - name: my-test02-02 image: swr.cn-east-3.myhuaweicloud.com/k8s-imgs/account-platform-admin:dev01-084e7d9 imagePullPolicy: IfNotPresent imagePullSecrets: - name: default -secret imagePullSecrets: - name: swr-secret --- apiVersion: apps/v1 kind: Deployment metadata: name: sub3-pod1 namespace : sub3 spec: selector: matchLabels: app: sub3pod1 replicas: 1 template: metadata: labels: app: sub3pod1 spec: containers: - name: my-test03-01 image: swr.cn-east-3.myhuaweicloud.com/k8s-imgs/account-platform-admin:dev01-084e7d9 imagePullPolicy: IfNotPresent imagePullSecrets: - name: default -secret imagePullSecrets: - name: swr-secret |
查看创建的资源
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
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: name: pod-policy namespace : sub1 spec: podSelector: {} ingress: - from : - ipBlock: cidr: 0.0.0.0/0 except: - 10.243.0.0/16 egress: - to: - ipBlock: cidr: 0.0.0.0/0 except: - 10.243.0.0/16 policyTypes: - Egress - Ingress |
解释:
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通信;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: name: sub2 namespace : sub2 spec: podSelector: {} egress: - to: - ipBlock: cidr: 0.0.0.0/0 except: - 10.243.0.0/16 - namespaceSelector: # 如果不想给命名空间加label,可以换成 - podSelector: {} # 允许来自同一命名空间中的所有 Pod 的流量 matchLabels: ns: sub2 ingress: - from : - ipBlock: cidr: 0.0.0.0/0 except: - 10.243.0.0/16 - namespaceSelector: # 如果不想给命名空间加label,可以换成 - podSelector: {} # 允许来自同一命名空间中的所有 Pod 的流量 matchLabels: ns: sub2 policyTypes: - Egress - Ingress |
解释
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
1 2 3 | kubectl label ns kube-system ns=kube-system kubectl label ns kuboard ns=kuboard kubectl label ns kube- public ns=kube- public |
网络隔离配置
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 | apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: name: ns-policy-2 namespace : sub2 spec: podSelector: {} ingress: - from : - podSelector: {} - ipBlock: cidr: 0.0.0.0/0 except: - 10.243.0.0/16 - from : - namespaceSelector: matchLabels: ns: kube-system - from : - namespaceSelector: matchLabels: ns: kuboard - from : - namespaceSelector: matchLabels: ns: kube- public egress: - to: - podSelector: {} - ipBlock: cidr: 0.0.0.0/0 except: - 10.243.0.0/16 - to: - namespaceSelector: matchLabels: ns: kube-system - to: - namespaceSelector: matchLabels: ns: kuboard - to: - namespaceSelector: matchLabels: ns: kube- public policyTypes: - Egress - Ingress |
解释
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
本文来自博客园,作者:技术人的菜园子,转载请注明原文链接:https://www.cnblogs.com/wangjiayu/p/18381458
免责声明:本文参照互联网上相关资料编写,如有侵犯,请联系本人修改
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 清华大学推出第四讲使用 DeepSeek + DeepResearch 让科研像聊天一样简单!
· 实操Deepseek接入个人知识库
· 易语言 —— 开山篇
· 一个费力不讨好的项目,让我损失了近一半的绩效!
· 【全网最全教程】使用最强DeepSeekR1+联网的火山引擎,没有生成长度限制,DeepSeek本体