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不仅存在于传输层,也存在于数据链路层。