写点什么

Kubernetes 网络策略之详解

作者:乌龟哥哥
  • 2023-04-20
    江苏
  • 本文字数:3588 字

    阅读完需:约 12 分钟

Kubernetes 网络策略之详解

NetWork Policy 简介

随着微服务架构的日渐盛行,Serverless 框架的逐步落地,应用上云后带来了模块间网络调用需求的大规模增长,Kubernetes 自 1.3 引入了 Network Policy,其提供以应用为中心, 基于策略的网络控制,用于隔离应用以减少攻击面。


网络策略(Network Policy )是 Kubernetes 的一种资源。Network Policy 通过 Label 选择 Pod,并指定其他 Pod 或外界如何与这些 Pod 通信。


Pod 的网络流量包含流入(Ingress)和流出(Egress)两种方向。默认情况下,所有 Pod 是非隔离的,即任何来源的网络流量都能够访问 Pod,没有任何限制。当为 Pod 定义了 Network Policy,只有 Policy 允许的流量才能访问 Pod。


Pod 之间能否通信可通过如下三种组合进行确认:


  • 其他被允许的 Pods(例如:Pod 无法限制对自身的访问)

  • 被允许访问的 namespace

  • IP CIDR(例如:与 Pod 运行所在节点的通信总是被允许的)


在定义基于 Pod 或 namespace 的 NetworkPolicy 时,可以使用标签选择器来设定哪些流量可以进入或离开 Pod。同时,当创建基于 IP 的 NetworkPolicy 时,可以基于 IP CIDR 来定义策略。


Kubernetes 的网络策略功能也是由第三方的网络插件实现的,因此,只有支持网络策略功能的网络插件才能进行配置网络策略,比如 Calico、Canal、kube-router 等等。

部署 calico 网络插件提供网络策略功能

Calico 可以独立地为 Kubernetes 提供网络解决方案和网络策略,也可以和 flannel 相结合,由 flannel 提供网络解决方案,Calico 仅用于提供网络策略,此时将 Calico 称为 Canal。结合 flannel 工作时,Calico 提供的默认配置清单式以 flannel 默认使用的 10.244.0.0/16 为 Pod 网络,因此在集群中 kube-controller-manager 启动时就需要通过--cluster-cidr 选项进行设置使用该网络地址,并且---allocate-node-cidrs 的值应设置为 true。


本文使用 calico 作为网络插件,并提供网络策略功能来加以说明


1、下载 calico 安装文件,修改网段


curl -LO https://docs.projectcalico.org/archive/v3.15/manifests/calico.yaml
复制代码


将配置文件中 CALICO_IPV4POOL_CIDR 注释取消,并将值修改为: 10.244.0.0/16


2、安装 calico


kca -f calico.yaml
复制代码

配置网络策略

在 Kubernetes 系统中,报文的流入和流出的核心组件是 Pod 资源,它们也是网络策略功能的主要应用对象。NetworkPolicy 对象通过 podSelector 选择 一组 Pod 资源作为控制对象。NetworkPolicy 是定义在一组 Pod 资源之上用于管理入站流量,或出站流量的一组规则,有可以是出入站规则一起生效,规则的生效模式通常由 spec.policyTypes 进行 定义。


默认情况下,Pod 对象的流量控制是为空的,报文可以自由出入。在附加网络策略之后,Pod 对象会因为 NetworkPolicy 而被隔离,一旦名称空间中有任何 NetworkPolicy 对象匹配了某特定的 Pod 对象,则该 Pod 将拒绝 NetworkPolicy 规则中不允许的所有连接请求,但是那些未被匹配到的 Pod 对象依旧可以接受所有流量。


就特定的 Pod 集合来说,入站和出站流量默认是放行状态,除非有规则可以进行匹配。还有一点需要注意的是,在 spec.policyTypes 中指定了生效的规则类型,但是在 networkpolicy.spec 字段中嵌套定义了没有任何规则的 Ingress 或 Egress 时,则表示拒绝入站或出站的一切流量。定义网络策略的基本格式如下:


apiVersion: networking.k8s.io/v1    #定义API版本kind: NetworkPolicy             #定义资源类型metadata:  name: allow-myapp-ingress          #定义NetwokPolicy的名字  namespace: defaultspec:                  #NetworkPolicy规则定义  podSelector:                #匹配拥有标签app:myapp的Pod资源    matchLabels:      app: myapp  policyTypes:        #NetworkPolicy类型,可以是Ingress,Egress,或者两者共存  - Ingress  - Egress  ingress:                #定义入站规则  - from:    - ipBlock:              #定义可以访问的网段        cidr: 10.244.0.0/16        except:              #排除的网段        - 10.244.3.0/24    - podSelector:            #选定当前default名称空间,标签为app:myapp可以入站        matchLabels:          app: myapp    ports:               #开放的协议和端口定义    - protocol: TCP      port: 80  egress:  - to:    - ipBlock:              #指定端口上的流量匹配到 10.244.0.0/24 中的任何目的地        cidr: 10.244.0.0/24    ports:    - protocol: TCP      port: 80  该网络策略就是将default名称空间中拥有标签"app=myapp"的Pod资源开放80/TCP端口给10.244.0.0/16网段,并排除10.244.3.0/24网段的访问,并且也开放给标签为app=myapp的所有Pod资源进行访问。
复制代码


  • 必需字段:与所有其他的 Kubernetes 对象一样,NetworkPolicy 需要 apiVersion、 kind 和 metadata 字段。

  • spec:NetworkPolicy 规约中包含了在名字空间中定义特定网络策略所需的所有信息。

  • podSelector:每个 NetworkPolicy 都包括一个 podSelector,它选择适用该该策略的 Pod。示例中的策略选择带有 “app=myapp” 标签的 Pod。若 podSelector 为空的,则选择名字空间下所有 Pod。

  • policyTypes: 每个 NetworkPolicy 都包含一个 policyTypes 列表,其中包含 Ingress 或 Egress 或(两者亦可)。policyTypes 字段表示给定的策略是应用于 所选 Pod 的入口流量还是来出口流量(两者亦可)。如果 NetworkPolicy 未指定 policyTypes 则默认情况下始终设置 Ingress;如果 NetworkPolicy 有任何出口规则的话则设置 Egress。

  • ingress: 每个 NetworkPolicy 可包含一个 ingress 规则的白名单列表。每个规则都允许同时匹配 from 和 ports 部分的流量。示例策略中包含一条 简单的规则:它匹配某个特定端口,第一个通过 ipBlock 指定,第二个通过 podSelector 指定。

  • egress: 每个 NetworkPolicy 可包含一个 egress 规则的白名单列表。每个规则都允许匹配 to 和 port 部分的流量。该示例策略包含一条规则, 该规则指定端口上的流量匹配到 10.0.0.0/24 中的任何目的地。


该网络策略总结如下:


  • 隔离 default 名字空间下 app=myapp 的 Pod 。

  • 出口限制:允许符合以下条件的 Pod 连接到 default 名字空间下标签为 app=myapp 的所有 Pod 的 80 TCP 端口:

  • a) default 名字空间下带有 app=myapp 标签的所有 Pod

  • b) IP 地址范围为 10.244.0.0–10.244.0.255 和 10.244.3.0–10.244.255.255(即除了 10.244.3.0/24 之外的所有 10.244.0.0/16)

  • 入口限制:允许从带有 app=myapp 标签的名字空间下的任何 Pod 到 CIDR 10.244.0.0/16 下 80 TCP 端口。

部署应用

1、部署 nginx 服务


[root@localhost ~]# kubectl create deployment nginx --image=nginxdeployment.apps/nginx created
[root@localhost ~]# kubectl expose deployment nginx --port=80service/nginx exposed
复制代码


2、测试网络


[root@localhost ~]# kubectl get svc,podNAME                 TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)   AGEservice/kubernetes   ClusterIP   10.96.0.1        <none>        443/TCP   9dservice/nginx        ClusterIP   10.105.249.196   <none>        80/TCP    22m
NAME READY STATUS RESTARTS AGEpod/nginx-6799fc88d8-dpqrp 1/1 Running 0 22m
[root@localhost ~]# kubectl run busybox --rm -ti --image=busybox /bin/shIf you don't see a command prompt, try pressing enter./ # wget --spider --timeout=1 nginxConnecting to nginx (10.105.249.196:80)remote file exists
复制代码


3、测试网络策略


如果只让那些拥有标签 access: true 的 Pod 访问 nginx 服务, 那么可以创建一个如下所示的 NetworkPolicy 对象:


cat << EOF | kubectl apply -f -apiVersion: networking.k8s.io/v1kind: NetworkPolicymetadata:  name: access-nginxspec:  podSelector:    matchLabels:      app: nginx  ingress:  - from:    - podSelector:        matchLabels:          access: "true"EOFnetworkpolicy.networking.k8s.io/access-nginx created
复制代码


  • 不带 access=true 标签的 Pod 还是无法访问 nginx 服务


  [root@localhost ~]# kubectl run busybox --rm -ti --image=busybox /bin/sh  If you don't see a command prompt, try pressing enter.  / # wget --spider --timeout=1 nginx  Connecting to nginx (10.105.249.196:80)  wget: download timed out
复制代码


  • 而带有 access=true 标签的 Pod 可以访问 nginx 服务


  [root@localhost ~]# kubectl run busybox --rm -ti --labels="access=true" --image=busybox /bin/sh  If you don't see a command prompt, try pressing enter.  / # wget --spider --timeout=1 nginx  Connecting to nginx (10.105.249.196:80)  remote file exists
复制代码

应用场景

管控入站流量

发布于: 刚刚阅读数: 5
用户头像

乌龟哥哥

关注

正在努力寻找offer的大四小菜鸟 2021-03-16 加入

擅长 Hbuilder、VS Code、MyEclipse、AppServ、PS 等软件的安装与卸载 精通 Html、CSS、JavaScript、jQuery、Java 等单词的拼写 熟悉 Windows、Linux、 等系统的开关机 看–时间过得多快,不说了,去搬砖了

评论

发布
暂无评论
Kubernetes网络策略之详解_三周年连更_乌龟哥哥_InfoQ写作社区