k8s网络包括网络模型、CNI、Service、Ingress、DNS。
k8s的容器网络关注两点:IP地址分配,路由。
网络
k8s的网络依赖于docker,docker的网络需要linux内核特性的支持。
k8s的三种ip
- node ip:node节点的ip地址。节点的物理网卡ip。从集群的VPC网络为节点分配IP地址。
- pod ip:pod的ip地址。是docker engine根据docker0网桥的ip地址段分配的,是虚拟的二层网络。可以实现不同node中pod之间的通信。通过--pod-cidr指定pod的可分配IP地址段。
- cluster ip:service的ip地址。由k8s管理和分配,来源于cluster ip地址池。无法被ping,因为没有“实体网络对象”。只能结合service port组成具体的通信端口。从集群的VPC网络为每项服务分配IP地址。
创建Pod的网络流程
1 每个Pod除了创建时指定的容器外,都有一个kubelet启动时指定的基础容器。
2 kubelet创建基础容器,生成network namespace。
3 kubelet调用网络CNI driver,由它根据配置调用具体的CNI 插件。
4 CNI 插件给基础容器配置网络。
5 Pod 中其他的容器共享使用基础容器的网络。
Ingress
Ingress是HTTP方式的路由转发机制,即是7层负载均衡器,由Ingress Controller和HTTP代理服务器组成。Ingress Controller实时监控k8s API,实时更新HTTP代理服务器的转发规则。HTTP代理服务器有GCE Load-Balancer、HaProxy、Nginx等方案。ingress controller在转发客户端请求到后端服务时,将跳过kube-proxy提供的4层负载均衡器的功能,直接转发到service的后端pod(endpoint)。
对于需要为k8s集群外的客户端提供服务的service,可以通过ingress将服务暴露出去。
Network Policy
网络策略是基于pod源ip(因此k8s网络不能随便做SNAT)的访问控制列表,限制pod之间的访问。
网络策略作为pod网络隔离的一层抽象,用白名单实现了访问控制列表,从label selector、namespace selector、端口、CIDR这4个维度限制pod的流量进出。
ingress限制进入的流量,egress限制外出的流量。
集群DNS
完成从服务名到clusterIP的解析。
DNS服务经历从skyDNS到kubeDNS再到coreDNS的过程。k8s通过Add-On增值包的方式引入DNS系统,把服务名作为dns域名。程序就可以直接使用服务名来建立通信连接。
容器中的数据到外网
从容器发出的数据包先到达br0,然后交给host机器的协议栈,由于目的IP是外网,且host主机开启了IP forward功能,数据包会通过eth0发出。因容器分配的网段都不在物理网络网段内,所以一般发出去之前先做NAT转换。(可以用iptables进行转换)
当涉及转发的目的IP地址是其他机器时,需要确保启用ip forward功能,即把linux当作交换机。
参考
- 《Kubernetes 权威指南》
- 《每天5分钟玩转kubernetes》
- 《Kubernetes 权威指南-企业级容器云实践》
- 《Kubernetes 网络权威指南》
- k8s网络--竹径风声