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.ingressspec.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

解释:

  1. podSelector{} 表示选择命名空间中的所有 Pod。
  2. ingress: 定义了进入命名空间的流量控制规则。
    • from: 表示允许来自哪些来源的流量。
    • ipBlock: 表示允许来自除了 10.243.0.0/16 CIDR 地址范围之外的所有 IP 地址的流量。
  3. egress: 定义了离开命名空间的流量控制规则。
    • to: 表示允许流向哪些目的地的流量。
    • ipBlock: 表示允许流向除了 10.243.0.0/16 CIDR 地址范围之外的所有 IP 地址的流量。
  4. 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

解释

  1. podSelector{} 表示选择命名空间中的所有 Pod。
  2. ingress: 定义了进入命名空间的流量控制规则。
    • from: 表示允许来自哪些来源的流量。
    • ipBlock: 表示允许来自除了 10.243.0.0/16 CIDR 地址范围之外的所有 IP 地址的流量。
    • namespaceSelector: 表示允许来自具有标签 ns=sub2 的命名空间中的 Pod 的流量。
    • from字段中的 podSelector: {} 表示允许来自同一命名空间中的所有 Pod 的流量。
  3. egress: 定义了离开命名空间的流量控制规则。
    • to: 表示允许流向哪些目的地的流量。
    • ipBlock: 表示允许流向除了 10.243.0.0/16 CIDR 地址范围之外的所有 IP 地址的流量。
    • namespaceSelector: 表示允许流向具有标签 ns=sub2 的命名空间中的 Pod 的流量。
    • to字段中的 podSelector: {} 表示允许流向同一命名空间中的所有 Pod 的流量。
  4. 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。
  • policyTypesIngress 和 Egress 表示同时控制进入和离开命名空间的流量。
  • ingressfrom 字段中的 podSelector: {} 表示允许来自同一命名空间中的所有 Pod 的流量;ipBlock 表示允许来自除了 Kubernetes 内部网络 CIDR 地址范围10.243.0.0/16
    之外的所有 IP 地址的流量。
  • egressto 字段中的 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

 

 

 

 

 

 

 

 

 

 

 

  

 

posted @   技术人的菜园子  阅读(541)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 清华大学推出第四讲使用 DeepSeek + DeepResearch 让科研像聊天一样简单!
· 实操Deepseek接入个人知识库
· 易语言 —— 开山篇
· 一个费力不讨好的项目,让我损失了近一半的绩效!
· 【全网最全教程】使用最强DeepSeekR1+联网的火山引擎,没有生成长度限制,DeepSeek本体
点击右上角即可分享
微信分享提示