Docker/k8s网络基础总结
- Docker/k8s网络基础总结
- Docker网络基础
- 网络命名空间
- Veth设备对
- 网桥
- iptables和Netfilter
- 路由
- Docker网络实现
- k8s网络实现
- 容器与容器的通信
- pod与pod之间的通信
Docker/k8s网络基础总结
Docker网络基础
docker依赖于Linux内核虚拟化技术的发展,对Linux内核特性有很强的依赖。docker网络涉及网络命名空间、Veth设备对、网桥、iptables和路由。
网络命名空间
Linux在网络栈中引入网络网络命令空间以支持网络协议栈的多个实例。处于不同网络命令空间的网络栈彼此之间完全隔离,无法通信。通过对网络资源的隔离实现同一宿主机虚拟多个网络环境。Docker利用网络命名空间特性实现不同容器之间的隔离。
在Linux网络命令空间中可以有独立的路由表、iptables设置来提供包转发、NAT及IP包过滤等功能。
新生成的私有命名空间只有名为lo的回环设备。Docker容器中的各类网络栈设备都是Docker Daemon在穷时自动创建和配置的。
所有的网络设备都只能属于一个命名空间。物理设备通常只关联到root命名空间。虚拟网络设备可以被创建并关联到一个给定的命名空间中,而且可以在这些命令空间之间移动。
相关操作
- 创建命名空间 ip netns add
- 进入命名空间执行命令 ip nets exec
- 进入命名空间 ip nets exec bash
- 查看设备是否可以转移 ethtool -k br0
- 转移设备 ip link set br0 netns ns1
Veth设备对
Veth设备对是用来实现不同命名空间之间通信的,一端连接一个网络命名空间的协议栈,一端连接另一个网络空间协议栈。
相关操作
- 创建ip link add veth0 type veth peer name veth1
- 查看 ip link show
- 设置对端设备 ip link set veth1 netns netns1
设置 ip ip addr add 10.1.1.2/24 dev veth0
启动 ip netns exec netns1 ip link set dev veth1 up & ip link set dev veth0 up
网桥
网桥是一个二层的虚拟网络设备,把若干个网络接口“连接”起来,以使得网络接口之间的报文能够互相转发。
网桥能够解析收发的报文,读取目标MAC地址的信息,和自己记录表结合,来决策报文的转发目源MAC标网络接口。为了实现这些功能,网桥会学习C地址(二层网桥是MA转发的依据就C地址)。在转发报文时,网桥只需要向特定的网口进行转发,来避免不必要的网络交互。如果它遇到一个自己从未学习到的地址,就无法知道这个报文应该向哪个网络接口转发,就将报文广播给所有的网络接口(报文来源的网络接口除外)。
Linux(NetDevice内核是通过一个虚拟的网桥设备)来实现桥接的。这个虚拟设备可以绑定若干个以太网接口设备,从而将它们桥接起来。
相关操作:
- 新增网桥设备 brctl addbr xxx
- 增加网口 brctl addif xxx ethx
- 配置ip ifconfig ethx 0.0.0.0 | ifconfig brxxx xxx.xxx.xxx.xxx
iptables和Netfilter
在Linux网络洗衣栈中有一组回调函数挂载点,通过这些挂载点挂接的狗子函数可以在Linux网络栈处理数据包的过程中对数据包进行一些操作,例如过滤、修改、丢弃等。整个挂载点技术叫作netfilter和iptbales。
iptables是在用户模式下运行的进程,负载协助和维护内核中Netfilter的各种规则表;netfilter是在内核中执行各种挂接的规则,运行在内核模式中。二者相互配合实现网络协议栈中灵活的数据包处理。
Netfilter可以挂载的规则点有5个,如下图所示
挂载点能挂载的规则分为不同类型,可以在不同的规则表中加入规则。规则表主要分为:RAW、MANGLE、NAT和FILTER。其中RAW有限级最高,FILTER最低。
相关操作:
- iptables-save 查看iptables内容
路由
路由功能通过路由表维护,在IP层处理数据发送或者转发时,会使用路由表来决定发往哪里。
路由表包含以下信息:
- 目的IP地址
- 下一路由器的IP地址
- 标志
- 网络接口规范
Linux的路由表包括LOCAL、MAIN。LOCAL表中包含所哟本地设备地址。LOCAL路由表示在配置希望罗设备地址时创建LOCAL表用于Linux协议栈识别本地地址,以及进行本地各个不同网络接口之间的数据转发。
相关操作:
- 查看Local表:ip route show table local type local
- 查看当前路由表:ip route list | netstat -rn
Docker网络实现
Docker支持以下4中网络模式:
- host模式
- container模式
- none模式
- bridge模式
在k8s管理模式下默认使用bridge模式。
在bridge模式下,Docker Daemon第1此启动时会创建一个虚拟的网桥,默认的名称是docker0,然后按照RPC1918的模型在私有网络空间中给这个网桥分配一个子网。针对由Docker创建的每一个容器,都会创建一个虚拟的以太网设备(Veth),其中一端连接到网桥上,另一端使用Linux的网络空间技术,映射到容器内的eth0设备,然后从网桥的地址端给eth0接口分配一个IP地址。
为了让不同容器跨节点互相通信,必须在主机的地址上分配端口,然后通过这个端口路由或代理到容器上。这使得在集群上部署的容器需要谨慎协调端口分配。若使用动态端口技术,每个应用程序都只能将端口看作一个符号(因为是动态分配的,所以无法提前设置)。而且API Server要在分配完后,将动态端口插入配置的合适位置,服务也必须能互相找到对方等。这些都是Docker的网络模型在跨主机访问时面临的问题。
k8s网络实现
k8s基础原则是每一个pod都拥有一个独立的地址,并假定所有pod都在一个可以连通的、扁平的网络空间中。不需要考虑容器端口映射到主机端口的问题。
k8s网络主要解决以下问题
- 容器与容器之间的直接通信
- pod与pod之间的通信
- pod与service之间的通信
- 集群外部与内部组件的通信
容器与容器的通信
同一个pod内的容器共享一个网络命名空间、协议栈。
pod与pod之间的通信
一个节点内pod的通信是通过Veth连接到docker0网桥上,并从网桥上动态获取网段,与网桥属于同一个网段。
k8s会记录所有正在运行的pod的ip分配信息,并将这些信息保存在etcd中作为service的endpoint。k8s通过flannel等网络插件实现ip资源池的分配,避免冲突。在下图中,pod1在访问pod2时,受限将数据从源node的eth0发送出去,找到并到达Node2的eth0。即先是从IP3到IP4的递送,之后才是IP4到IP2的递送。