Kubernetes Notes
  • README
  • 序:Kubernetes之道
  • 搭建开发环境
    • 搭建本地开发测试环境
  • 基本概念
    • Workloads
      • StatefulSet
    • 认证鉴权
      • 理解证书
      • Kubelet配置
    • 垃圾回收
    • Service
  • 基础组件
    • Scheduler
    • 自动扩缩容(HPA)
  • 容器运行时(Container Runtime)
    • CRI
    • Docker
      • 安装配置Docker
      • Docker FAQ
    • Containerd
  • 资源隔离与限制
    • 基础知识
      • Cgroup
      • Namespaces
    • CPU
    • Memory
    • 网络出/入带宽
    • GPU
    • Container
    • FAQ
  • 网络
    • 基础知识
      • Linux network interfaces
      • Iptables
      • Overlay network
    • CNI
    • Flannel
      • Flannel原理
      • host-gw
      • vxlan
      • ipip
    • Calico
    • Cilium
  • Service Mesh
    • Istio
  • 扩展Kubernetes
    • Admission controller
    • Custom resource definition(CRD)
    • Scheduler extender
    • 扩展资源维度
    • Kubectl plugin
    • Aggregator
    • Device plugin
  • 现网问题
    • Kubernetes
    • ETCD
    • Docker
  • 最佳实践
    • 各组件参数配置调优
    • 各大公司生产环境实践
    • 如何打造一个Kubernetes平台
  • 生产力小工具
    • 生成特定权限和配额的kubeconfig
  • 社区贡献
  • 学习资料
  • 附录:RTFSC
    • Informer
    • Pod deletion
Powered by GitBook
On this page
  • 1. Host-gw原理
  • 2. Host-gw实验
  • 3. Host-gw on Flannel
  • 4. 参考资料

Was this helpful?

  1. 网络
  2. Flannel

host-gw

PreviousFlannel原理Nextvxlan

Last updated 6 years ago

Was this helpful?

1. Host-gw原理

Host-gw并不是一个linux里类似vxlan的专有概念,它只是里的一个利用route表实现不同主机上container互连的,当然前提条件是各主机在一个子网内,是layer2互通的。如下图所示,node0和node1之间可以通过eth0互连,但container0和container2无法互连,如果想让它们之间能通信,可以怎么做呢?本文主要介绍host-gw方法。

container0和container2无法互连的原因在于:当container0发往container2的包(container2向container0发包也是类似的情况)经过eth0时,内核将查找route表规则,显然不能找到符合192.168.1.2/24(container2的ip)的规则,因此只能发往默认路由(一般是gateway网关),事实上gateway也不能找到符合192.168.1.2/24的规则,最终所有的路由器都不知道目标ip地址为192.168.1.2/24的包该发到哪个主机上。

知道这个原因后,你可能会想:如果在node0上创建一条route表规则,让目标地址为192.168.1.2/24的包全部发往node1,那不就解决问题了?是的,host-gw正是这样解决的:在node0上创建route表规则(ip route add 192.168.1.0/24 via 10.20.0.2 dev eth0),让目标地址为192.168.1.0/24的包全部发往node1,在node1上创建route表规则(ip route add 192.168.0.0/24 via 10.20.0.1 dev eth0),让目标地址为192.168.0.0/24的包全部发往node0,这样node0和node1上的container就可以互相通信了。

2. Host-gw实验

在Vagrant file所在目录执行vagrant up后,将启动3个安装了docker的节点node0、node1、node2(这个实验只需要用到两个节点即可)。

接下来,我们为node0(对外通信的网卡为enp0s8,ip为172.28.128.9)和node1(对外通信的网卡为enp0s8,ip为172.28.128.10)上的docker分别配置ip段192.168.0.1/24和192.168.1.1/24,并加上相应的route表。

# node0配置
root@node0:~# /vagrant/config_docker0.sh 192.168.0.1/24 192.168.0.1/24
root@node0:~# ip route add 192.168.1.0/24 via 172.28.128.10 dev enp0s8 
root@node0:~# iptables -A FORWARD -s 192.168.0.0/16 -j ACCEPT
root@node0:~# iptables -A FORWARD -d 192.168.0.0/16 -j ACCEPT
root@node0:~# echo 1 > /proc/sys/net/ipv4/ip_forward

# node1配置
root@node1:~# /vagrant/config_docker0.sh 192.168.1.1/24 192.168.1.1/24
root@node1:~# ip route add 192.168.1.0/24 via 172.28.128.9 dev enp0s8 
root@node1:~# iptables -A FORWARD -s 192.168.0.0/16 -j ACCEPT
root@node1:~# iptables -A FORWARD -d 192.168.0.0/16 -j ACCEPT
root@node1:~# echo 1 > /proc/sys/net/ipv4/ip_forward

现在可以在node0和node1上分别启动一个container(docker run -it hex108/ubuntu:ping bash),然后ping对方了。

3. Host-gw on Flannel

Flannel的host-gw方案和上文实验中一样,只不过我们不用手动增加route表和iptables规则了。

下面通过实验来说明flannel host-gw的一些细节,实验环境使用上面使用vagrant创建的3个节点(node0对外通信的网卡为enp0s8,ip为172.28.128.9,node1对外通信的网卡为enp0s8,ip为172.28.128.10,node2对外通信的网卡为enp0s8,ip为172.28.128.11)。

首先,在node2上安装最新版本的etcd,并将各节点上flannel可以申请使用的ip地址范围192.168.0.2/16配置到etcd上,并指定flannel使用的backend类型为host-gw。

root@node2:~# wget https://github.com/etcd-io/etcd/releases/download/v3.3.10/etcd-v3.3.10-linux-amd64.tar.gz
root@node2:~# etcd-v3.3.10-linux-amd64/etcd --advertise-client-urls 'http://172.28.128.11:2379' --listen-client-urls 'http://172.28.128.11:2379'
root@node2:~# /etcd-v3.3.10-linux-amd64/etcdctl --endpoints="http://172.28.128.11:2379" set /coreos.com/network/config '{ "Network": "192.168.0.2/16", "Backend": {"Type": "host-gw"}}'
# node0
root@node0:~# wget https://github.com/coreos/flannel/releases/download/v0.10.0/flanneld-amd64 && chmod +x flanneld-amd64
root@node0:~# ./flanneld-amd64 -etcd-endpoints "http://172.28.128.11:2379" -iface enp0s8 -public-ip 172.28.128.9
root@node0:~# /vagrant/config_docker0_with_flannel.sh

# node1
root@node0:~# wget https://github.com/coreos/flannel/releases/download/v0.10.0/flanneld-amd64 && chmod +x flanneld-amd64
root@node0:~# ./flanneld-amd64 -etcd-endpoints "http://172.28.128.11:2379" -iface enp0s8 -public-ip 172.28.128.10
root@node0:~# /vagrant/config_docker0_with_flannel.sh

现在可以在node0和node1上分别启动一个container(docker run -it hex108/ubuntu:ping bash),然后ping对方了。

4. 参考资料

实验环境:Mac, ,

说明:从docker 1.13开始,docker会将FORWARD表的默认规则改为DROP,导致从container0到container2的包虽然被正确转到node1上了,但是会被drop掉,因此我们在上面增加了两条ACCEPT规则,让容器间的包通过。另外,要确保/proc/sys/net/ipv4/ip_forward值为1(小知识:),这样container0的包到了node1上,才会经由enp0s8雷劈到docker0再转到container2上。

其次,在node0和node1上安装启动flannel,并配置docker。启动flannel后,flannel会通过机制向etcd“申请”一块ip地址,并将它写入文件/run/flannel/subnet.env,配置docker时,docker0的bip地址来源于它。同时,flannel会增加前面提到的两条iptables规则,并开始监听etcd,当它发现其他节点也从etcd申请一块ip地址后,它就会创建一条相应的route表规则,这样这两台机器上container之间就可以互相通信了,例:node0上的flannel监听到node1上的flannel申请ip地址块192.168.1.0/24后,它就会创建一条相应的route表ip route add 192.168.1.0/24 via 172.28.128.10 dev enp0s8。如果有新的节点增加进来,比如新加进来节点node3,它会为所有已经存在的flannel创建相应的route表规则,这样这机器上的container就能和其他节点上的container通信了。可以发现,如果有大量节点,机器上将会有大量相应的route表规则。

flannel host-gw模式工作原理浅析:

Routing table:

What is kernel ip forwarding:

Setting Up Gateway Using iptables and route on Linux:

Running flannel:

Vagrant
Vagrant file以及相应的配置脚本
What is kernel ip forwarding
Leases and Reservations
https://blog.csdn.net/cloudvtech/article/details/79809569
https://en.wikipedia.org/wiki/Routing_table
https://unix.stackexchange.com/questions/14056/what-is-kernel-ip-forwarding
https://www.systutorials.com/1372/setting-up-gateway-using-iptables-and-route-on-linux/
https://github.com/coreos/flannel/blob/master/Documentation/running.md
Flannel
backend
host-gw