kubernetes 网络模型设计的一个基本原则是:每个Pod拥有一个独立IP地址,并假定所有Pod都在一个可以直接连通的、扁平的网络空间中,
在Kubernetes IP以Pod为单位进行分配的,一个Pod内部的所有容器共享一个网络堆栈(网络命名空间,ip地址,网络设备,配置都是共享的)按照这个原则抽象出来的每个Pod都设置一个Ip地址的模型也叫做Ip-per-Pod模型
Kubernetes 对网络有什么前提和要求
Docker本身的技术依赖于近年Linux内核虚拟化技术的发展,所以Docker对Linux内核特性有很强的依赖。
为了支持多个网络协议栈的多个实例,LInux在内核中引入了命名空间,独立的协议栈被隔离到不同的命名空间。
为了隔离出独立协议栈,纳入命名空间的元素有:进程、套接字、网络设备等
由于网络命名空间代表一个独立协议栈,所以它们之间是相互隔离的,彼此无法通信,在协议栈内部无法看到对方。如果想在两个命名空间之间通信,就必须有一个Veth设备对。
可以用Linux iproute2 系列配置工具中的ip命令来操作网络命名空间
root用户创建
ip netns add Name
在命名空间中 执行命令
ip netns exec Name command
也可以通过bash命令进入内部的shell界面,然后执行各种命令,
ip netns exec name shell
ethtool -k br0
如果netns-local : on fixed 如果是on 说明不可以转移,否则可以转移
引入Veth设备对是为了在不同的网络命名空间之间通信,利用它可以将两个网络命名空间连接起来。
Veth设备对都是成对出现的,就像一对以太网卡,并且中间有一根直连的网线。既然是一对网卡,那么我们将其中一端称为另一端的peer。
ip link add veth0 type peer name veth1
ip link set veth1 netns netns1
ip netns exec netns1 ip addr add 10.1.1.1/24 dev veth1
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
Linux可以支持不同的网络,它们之间能够互相通信,如何将这些网络连接起来并实现各网络中主机的相互通信呢?可以用网桥
网桥是一个二层的虚拟网络设备,把若干个网络接口“连接”起来,以使得网络接口之间的报文能够互相转发。
Linux 内核通过一个虚拟的网桥设备Net Device 来实现网桥的。这个虚拟设备可以绑定若干个以太网接口设备,从而将它们桥接起来。
桥接是在数据链路层实现的
brctl addbr XXXXXX
brctl addif XXXXXX ethx
ifconfig ethx 0.0.0.0
ifconfig brxxx xxx.xxx.xxx.xxx
在Linux网络协议栈中有一组回调函数挂接点,通过这些挂接点的钩子函数可以在linux网络处理数据包的过程中对数据进行一些操作,如过滤、修改、丢弃等 。整个挂接点叫做Netfilter和iptables
Netfilter负责在内核中执行各种挂接的规则,运行在内核模式中,而iptables是在用户模式下运行的进程,负责协助和维护内核中Netfilter的各种规则表。
Netfilter 可以连接的规则点有五个
上层协议处理
接口设备
挂接点挂接的规则分不同的类型
主要支持的Table类型有
从上到下优先级从高到低
每个规则的特性分为以下几个部分
参看LInux iptables文档
iptables-save 按照命令的方式打印iptables内容
iptables-vnL 以另一种格式显示Netfilter表内容
LInux系统包含一个完整的路由功能,当IP层处理数据发送或者转发时,会使用路由表来决定发往哪里。
路由功能由IP层维护的一张路由表来实现。
当主机接收到报文时,IP层首先检查报文的IP地址是否与主机自身的地址相同。
如果数据报文中的IP地址是主机自身的地址,那么报文将会被发送到传输层相应的协议中。如果报文中的IP地址不是主机自身的值,并且主机设置了路由功能,那么报文将会被转发,否则报文将会被抛弃。
lInux路由表至少包括两个表 一个Local表 一个MAIN,
Local表中包含所有的本地设备地址,Main表用于各类网络IP地址的转发,它的建立既可以使用静态配置生成,也可以使用动态路由发现协议生成。
1 ip route list
2 netstat -rn
标准的Docker支持以下四种网络模式
在kubernetes模式下一般只会使用bridge模式
Kubernetes 网络设计主要致力于解决以下问题
容器到容器之间的直接通信
抽象的pod到pod之间的通信
pod到service之间的通信
集群外部与内部组件之间的通信
同一个pod内的容器(Pod内的容器时不会垮宿主机的)共享同一个网络命名空间,共享同一个Linux协议栈。
所以对于网络的各类操作,就和它们在同一台机器上一样
每一个pod都有一个真实的全局IP地址,同一个Node 内的不同Pod之间可以直接采用对方的Pod的IP地址通信,而且不需要采用其他发现机制,如DNS、Consul或etcd
1 同一个Node内Pod之间的通信
同一个Node内两个Pod都被关联在同一个Dokcer0网桥上,地址段相同,它们之间是能直接通信的。它们的IP地址和docker0网桥在同一个网段。
2 不同node上pod之间的通信
docker0网桥和宿主机网卡是两个完全不同的ip段,不同node之间的通信只能通过宿主机的物理网卡进行。因此实现不同Node上Pod之间的通信,就必须想办法通过主机的这个Ip地址进行寻址和通信。