写点什么

k8s- 使用 Network Policies 实现网络隔离

  • 2024-08-29
    福建
  • 本文字数:7171 字

    阅读完需:约 24 分钟

一、需求


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:  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 结构


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 进行通信。


apiVersion: networking.k8s.io/v1kind: NetworkPolicymetadata:  name: allow-traffic  namespace: my-namespacespec:  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。


kubectl create ns sub1 --labels ns=sub1kubectl create ns sub2 --labels ns=sub2kubectl create ns sub3 --labels ns=sub2
复制代码



  如果使用的是私有仓库,注意 ns 要创建 docker-secret。


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;


apiVersion: apps/v1kind: Deploymentmetadata:  name: sub1-pod1  namespace: sub1spec:  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: v1kind: Servicemetadata:  name: sub1-pod1-nodeport  namespace: sub1spec:  type: NodePort  selector:    app: sub1pod1  ports:    - protocol: TCP      port: 80      targetPort: 8103      nodePort: 32700 --- apiVersion: apps/v1kind: Deploymentmetadata:  name: sub1-pod2  namespace: sub1spec:  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/v1kind: Deploymentmetadata:  name: sub2-pod1  namespace: sub2spec:  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: v1kind: Servicemetadata:  name: sub2-pod1-nodeport  namespace: sub2spec:  type: NodePort  selector:    app: sub2pod1  ports:    - protocol: TCP      port: 80      targetPort: 8103      nodePort: 32701 --- apiVersion: apps/v1kind: Deploymentmetadata:  name: sub2-pod2  namespace: sub2spec:  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/v1kind: Deploymentmetadata:  name: sub3-pod1  namespace: sub3spec:  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


apiVersion: networking.k8s.io/v1kind: NetworkPolicymetadata:  name: pod-policy  namespace: sub1spec:  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 通信;


apiVersion: networking.k8s.io/v1kind: NetworkPolicymetadata:  name: sub2  namespace: sub2spec:  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


kubectl label ns kube-system ns=kube-systemkubectl label ns kuboard ns=kuboardkubectl label ns kube-public ns=kube-public
复制代码


网络隔离配置


apiVersion: networking.k8s.io/v1kind: NetworkPolicymetadata:  name: ns-policy-2  namespace: sub2spec:  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



文章转载自:技术人的菜园子

原文链接:https://www.cnblogs.com/wangjiayu/p/18381458

体验地址:http://www.jnpfsoft.com/?from=infoq

用户头像

还未添加个人签名 2023-06-19 加入

还未添加个人简介

评论

发布
暂无评论
k8s-使用Network Policies实现网络隔离_Kubernetes_不在线第一只蜗牛_InfoQ写作社区