Kubernetes Pod间网络隔离

2023-08-23 10:03:38 浏览数 (1)

Hi~朋友,关注置顶防止错过消息

网络隔离的对象

使用NetworkPolicy对象来实现。

NetworkPolicy对象示例

代码语言:javascript复制
apiVersion: networking.k8s.io/v1

kind: 
NetworkPolicy

metadata:

  name: test-network-policy

namespace
: 
default

spec:

  podSelector:

    matchLabels:

      role: db

  policyTypes:

    - 
Ingress

    - 
Egress

  ingress:

    - 
from
:

        - ipBlock:

            cidr: 
172.17
.
0.0
/
16

  except
:

  - 
172.17
.
1.0
/
24



   - namespaceSelector:

       project: myproject

    - podSelector:

        matchLabels:

          role: frontend

  ports:

    - protocol: TCP

      port: 
6379



egress:

 - to:

     - ipBlock:

         cidr: 
10.0
.
0.0
/
24

   ports:

     - protocol: TCP

       port: 
5978
  • spec.podSelector:定义被网络隔离器管理pod(default namespace pod上有roles:db标签的Pod)
  • policyTypes:网络隔离的方向,入口(ingress)或者出口(egress)
  • ingress:可以有三种方式来定义如何隔离入口流量:ip block 、 namespace、和 pod(上述示例ingree表明了只允许源ip 在172.0.0.0/16但不在172.17.1.0/24的网段或者namespace上带有project:myproject标签下的所有pod 、或者default namespace下带有role:frontend标签的所有pod访问6379端口)
  • egress:允许roles:db标签的Pod访问ip网段在10.0.0.0/24 下的pod的5987端口

可以看到上面我们的例子中from的写法是或得关系,如果是 AND 的关系的话写法如下:

代码语言:javascript复制
...

  ingress:

- 
from
:

- namespaceSelector:

    matchLabels:

      user: alice

  podSelector:

    matchLabels:

    role: client

...
 

上述namespace和pod则是与的关系。

NetworkPolicy生效的前提

CNI网络插件必须支持NetworkPolicy,该类型的插件都会维护着一个NetworkPolicy Controller,通过控制循环的方式对NetworkPolicy对象的增删改查作出响应,然后在宿主机上完成 iptables规则的配置工作。

如何实现网络的隔离

Kubernetes对Pod进行隔离依靠的就是在宿主机上生成NetworkPolicy对应的iptables规则来进行实现。

代码语言:javascript复制
for
 dstIP := range 所有被networkpolicy.spec.podSelector选中的
Pod
的IP地址

for
 srcIP := range 所有被ingress.
from
.podSelector选中的
Pod
的IP地址

for
 port, protocol := range ingress.ports {

      iptables -A KUBE-NWPLCY-CHAIN -s $srcIP -d $dstIP -p $protocol -m $protocol --dport $port -j ACCEPT

}

}
 

这是一条名称为KUBE-NWPLCY-CHAIN的规则,含义是当ip包源地址是srcIp,目的ip地址是dstIp,协议是protocol,目的端口是port的时候就允许他通过。

如何将Pod的访问请求转发到上述规则上去?

CNI网络插件需要设置两组iptables规则来实现。

第一组规则是用来负责拦截被隔离Pod的访问请求,生成的伪代码如下:

代码语言:javascript复制
for
 pod := range 该
Node
上的所有
Pod
{

if
 pod是networkpolicy.spec.podSelector选中的 {

        iptables -A FORWARD -d $podIP -m physdev --physdev-
is
-bridged -j KUBE-POD-SPECIFIC-FW-CHAIN

        iptables -A FORWARD -d $podIP -j KUBE-POD-SPECIFIC-FW-CHAIN

...

}

}
 

上述规则都被转发到KUBE-POD-SPECIFIC-FW-CHAIN规则上,该规则就是第二组规则,该规则就是用来对请求做通过和拒绝操作,如下:

代码语言:javascript复制
iptables -A KUBE-POD-SPECIFIC-FW-CHAIN -j KUBE-NWPLCY-CHAIN

iptables -A KUBE-POD-SPECIFIC-FW-CHAIN -j REJECT --reject-
with
 icmp-port-unreachable

上述第一条规则中我们会将请求转给前面定义的KUBE-NWPLCY-CHAIN规则进行匹配,如果匹配成功则通过,如果匹配不成功,IP 包则会命中第二条规则,这一条规则则是进行拒绝,通过这条规则则实现了不满足NetworkPolicy定义的请求就会被拒绝掉。

iptables的作用

iptables是用来操作Linux内核Netfilter,Netfilter是Linux内核里挡在用户态进程和网卡之间的一道防火墙,用来进行过滤,转发数据包。

iptables处理IP包的流程

IP包进入主机网卡(Netfilter流入路径)后,在查询路由表决定下一步走向之前,会经过PREROUTING链的检查,经过检查并且成功路由以后,IP包会有两个走向:

  • 留在本机进行处理转到七层中的上层继续处理
  • 转发到其他目的地

第一种走向在进入传输层之前,会经过 INPUT链的检查,检查通过以后即可进入用户空间交由用户进程处理。用户处理完成以后会通过本机响应IP包,此时IP包会到达Netfliter流出路径,此时会先根据路由表进行路由,路由结束后会经过一个OUTPUT链进行检查,OUTPUT链检查通过以后,会经过POSTROUTING链的检查。

第二种走向不会进入传输层,会在网络层继续流动,从而进入到转发路径(FORWARD PATH),在这里会经过FORWARD链的检查,检查通过以后不再经过路由,会直接到达流出路径的POSTROUTING链的检查。

Netfilter原理图

Netfliter的原理图如下,可以看出Netfilter不仅存在于传输层,也存在于数据链路层。

0 人点赞