容器网络基础
深入剖析容器网络篇中,介绍了容器网络同宿主机不同容器和不同宿主机不同容器的访问。
依赖linux系统,提供了创建虚拟网桥(工作在TCP/IP二层)和 创建 veth pair特殊设备的能力, 容器网络有了生长的土壤。docker项目会在宿主机上创建docker0网桥。 容器启动时创建一个eth0网卡 对应veth pair设备一端,另一端插在 docker0网桥上。 当容器container1 向eth0发送数据包时,数据包就会出现在docker0网桥上,进入宿主机的网络栈。
当container1需要访问container2时,container1先查询本地的路由表,发现是直连规则。则直接封装二层mac数据包发送到docker0网桥上,然后docker0网桥查询本地的转发表,然后将数据转发到端口vethb4963f3中。
k8s 四层网络
网络由于其复杂性,专业的事情还是交给专业的人来做。 k8s并没有直接做网络连通方案,相反提供了网络插件能力CNI。k8s中接管pod的网桥为cni0网桥,非dokcer0.
flannel 网络
k8s中常用的网络方案为flannel,其实现有三种方式
- UDP
- Vxlan
- HostGw 生产环境中通常使用hostgw模式,其它两种模式不做过多了解。
在云上VPC环境中,创建ack集群,部署两个pod,网络拓扑如
pod:172.16.0.70如何访问172.16.0.134呢
1、先查询 172.16.0.70的路由表命中第二条路由规则,数据发送到eth0
2、数据从通过eth0发出,就出现在veth设备另一端进入cni0网桥,进入宿主机10.95.242.47的网络栈 3、查询宿主机路由表,发现命中数据从宿主机的eth0网卡发出,会进入vswitch中。
4、 vswitch查询路由表,然后部署发送给宿主机10.95.242.47。 注意vswitch可以工作在二层或者三层,云上一般工作在三层,有路由表信息。
terway网络
阿里云提供了另外一种terway网络,其共用宿主机的网络。
可以看到pod和宿主机的节点ip地址段是一样的。 pod 10.200.119.195如何访问 10.71.236.214呢 1、先查询10.200.119.195的路由表,数据经过eth0网卡发出 2、call设备接收到数据包后直接从eth1网卡发出。 此eth1网卡被多个pod共用。
terway网络的性能相比flannel提升了很多。同时运维管理也方便,避免维护vpc和容器两个不同的网络段。
k8s 网络方案
k8s在节点上部署了kubelet和kubeproxy两个组件,前者主要负责pod生命周期管理,kubeproxy主要负责网络管理。
pod的ip地址是易变的,同时有多个pod同时提供相同的服务,因此k8s提供了Service服务的概念。Service实现有三种方式
- ClusterIp
- NodePort
- Loadbalance
ClusterIp
集群内访问时可以提供clusterIp的方式
Service本质就是一些iptables\ipvs规则,生产环境一般使用ipvs. 当在k8s集群中创建了Service,节点上kubeproxy监听到了service就会将其转化为节点上的iptables路由规则或者ipvs规则。
比如当pod访问,pod A和pod B提供的服务Service时,pod C需要先从kubeDNS中获取clusterIP,然后发送数据包。当数据包进入节点C 网络栈时选择一个ip,做下dnat访问对应的pod a的ip。
nodeport
当需要在集群外访问时,可以使用nodeport的方式
client可以通过访问节点B的ip地址,如curl: ip节点b:8080.
当请求到达节点B时对应的端口时,如果是Service服务的端口时。节点B网络栈就会对数据包做下Dnat和Snat,将请求转发给PodA。
loadbalance
当服务部署在云上时,还可以只用loadbalance类型,云厂商会创建SLB然后将对应pod的node节点会被挂载到SLB上。
ingress
为每一个服务创建一个loadbalance是一件很奢侈的事情,可以通过ingress的方式,为一批服务创建一个代理服务如nginx。
创建一个ingress对象,ingress-controller会收到ingress对象解析其中的规则,启动并部署nginx,nginx监听服务的clusterIp (有些资料不是clusterIP)。 client访问时,请求到了nginx的pod中访问服务的ClusterIp,后面过程和clusterIp是一样的。