在上期,我们介绍了如何在yaml中,描述一个networkpolicy实例。
实际上,networkpolicy是由kubernetes的CNI插件实现的。也就是说,CNI插件的开发者,需要解析yaml描述的networkpolicy,并实现networkpolicy描述的功能。
networkpolicy需要实现哪些功能呢?
很容易看出,networkpolicy描述的是容器组之间的策略,策略的内容是:
源容器组:源端口 -> 目的容器组:目的端口 放行 or 禁止
有网络安全基础的同学会发现,这种描述似曾相识——
在我们熟悉的状态检测防火墙中,配置的策略为:
源安全域->目的安全域 策略放行 or 禁止
当IP地址 100.1.1.100通过端口41316,向目的地址 200.1.1.100的端口443发起TCP连接,目的服务器回应,两端建立连接后,防火墙会话得以建立:
100.1.1.100:41316 -> 200.1.1.200:443
再让我们回到容器的世界中,看下图:
实际上,前文的networkpolicy描述的是这么一条策略:
源IP:所有带有frontend标签的容器
源端口:任意
目的IP:所有带有db标签的容器
目的端口:3306
协议:TCP
行为:允许
这与传统的状态防火墙本质上是一致的,唯一的区别是,传统防火墙识别的是安全域,而容器networkpolicy识别的是容器标签。
也就是说,networkpolicy实现的时候,首先要根据数据包的源IP,查找它对应的标签,再根据数据包的目的IP,查找它对应的标签,结合源端口、目的端口,查询策略对应的行为。
那么,谁掌握了容器标签与容器IP地址之间的对应关系呢?
如果大家仔细阅读了这个专题,答案就昭然若揭了——
kubernetes调用CNI插件的时候,会向CNI插件传入pod的IP地址和pod的标签。因此,根据networkpolicy的配置,通过pod的IP地址确定其标签,进而实现networkpolicy,也就成了CNI插件责无旁贷的义务。正所谓,权力越大,知识越多,责任越重。
当然,CNI插件并非都需要实现networkpolicy。遗憾的是,最常见的软件CNI插件flannel并不支持networkpolicy。
幸好,与flannel齐名的开源CNI插件calico支持networkpolicy。
calico的介绍不在本文范围内,感兴趣的同学可以去calico的主页学习相关文档:https://www.projectcalico.org/
在calico的文档中,可以看到这样一张图:
calico会在每个node(host)上安装agent,同时,policy controller会监视kubernetes上对networkpolicy的创建。
当用户创建networkpolicy的时候,policy controller可以将其记录到etcd数据库,并推送到各个node(host)的agent。
下面是重点:agent如何让networkpolicy落地呢?
原来,agent最终还是调用了Linux中破一切的安全/负载均衡组件——
iptables。
实际上,在实现了networkpolicy的容器网络中,每个node上逻辑网络可以呈现为下图:
任何pod之间的通信都需要被iptables监管。
可想而知地,在pod之间流量较大的时候,iptables的性能显然会成为瓶颈——
如何解决这个问题呢?
请看下期。