目录
跨主机通信
Docker默认的网络环境下,单台主机上的Docker容器可以通过docker0网桥直接通信,而不同主机上的Docker容器之间只能通过在主机上做端口映射进行通信。
这种端口映射方式对很多集群应用来说极不方便。
如果能让Docker容器之间直接使用自己的IP地址进行通信,会解决很多问题。 按实现原理可分别直接路由方式、桥接方式(如pipework)、Overlay隧道方式(如flannel、ovs+gre)等。
1.Flannel 简介
Flannel实质上是一种覆盖网络(overlay network),即表示运行在一个网上的网(应用层网络),并不依靠ip地址来传递消息, 而是采用一种映射机制,把ip地址和identifiers做映射来资源定位。
也就是将TCP数据包装在另一种网络包里面进行路由转发和通信, 目前已经支持UDP、VxLAN、AWS VPC和GCE路由等数据转发方式
Flannel实现的容器的跨主机通信通过如下过程实现:
- 每个主机上安装并运行etcd和flannel;
- 在etcd中规划配置所有主机的docker0子网范围;
- 每个主机上的flannel根据etcd中的配置,为本主机的docker0分配子网,保证所有主机上的docker0网段不重复,并将结果(即本主机上的docker0子网信息和本主机IP的对应关系)存入 etcd库中,这样etcd库中就保存了所有主机上的docker子网信息和本主机IP的对应关系;
- 当需要与其他主机上的容器进行通信时,查找etcd数据库,找到目的容器的子网所对应的outip(目的宿主机的IP);
- 将原始数据包封装在VXLAN或UDP数据包中,IP层以outip为目的IP进行封装;
- 由于目的IP是宿主机IP,因此路由是可达的;
- VXLAN或UDP数据包到达目的宿主机解封装,解出原始数据包,最终到达目的容器。
1.1 Flannel特点
- 使集群中的不同Node主机创建的Docker容器都具有全集群唯一的虚拟IP地址。
- 建立一个覆盖网络(overlay network),通过这个覆盖网络,将数据包原封不动的传递到目标容器。覆盖网络是建立在另一个网络之上并由其基础设施支持的虚拟网络。覆盖网络通过将 一个分组封装在另一个分组内来将网络服务与底层基础设施分离。在将封装的数据包转发到端点后,将其解封装。
- 创建一个新的虚拟网卡flannel0接收docker网桥的数据,通过维护路由表,对接收到的数据进行封包和转发(vxlan)。
- etcd保证了所有node上flanned所看到的配置是一致的。同时每个node上的flanned监听etcd上的数据变化,实时感知集群中node的变化。
2 环境搭建
注:保证当前主机已经在一个集群下
2.1 etcd 版本问题
ETCD3.4版本中,ETCDCTL_API=3和etcd --enable-v2=false成为了默认配置 flannel操作etcd使用的是v2的API,而kubernetes操作etcd使用的v3的API 为了兼容flannel,将默认开启v2版本,故配置文件中还要设置:
vi /etc/profile
export ETCDCTL_API=2 # 指定etcdctl命令的版本为v2
source /etc/profile
2.2 etcd中保存网络信息
ETCDCTL_API=2 etcdctl --endpoints "http://192.168.27.110:2379,http://192.168.27.110:2379" set /coreos.com/network/config '{"NetWork":"10.0.0.0/16","SubnetMin": "10.0.1.0","SubnetMax": "10.0.20.0","Backend": {"Type": "vxlan"}}'
- Network: 用于指定Flannel地址池, 整个overlay(覆盖)网络为10.0.0.0/16网段.
- SubnetLen: 用于指定分配给单个宿主机的docker0的ip段的子网掩码的长度,默认值也是24
- SubnetMin: 用于指定最小能够分配的ip段
- SudbnetMax: 用于指定最大能够分配的ip段,在上面的示例中,表示每个宿主机可以分配一个24位掩码长度的子网,可以分配的子网从10.0.1.0/24到10.0.20.0/24,也就意味着在这个网 段中,最多只能有20台宿主机
- Backend: 用于指定数据包以什么方式转发,默认为udp模式, 这里使用的是vxlan模式.因为为vxlan比起预设的udp性能相对好一些
2.3 flannel安装与配置
官网下载fiannel 安装包
创建flannel安装目录
mkdir -p /opt/flannel
解压到安装目录
tar xzf flannel-v0.11.0-linux-amd64.tar.gz -C /opt/flannel
为flannel创建一个systemd服务,用于后台启动
vim /etc/systemd/system/flanneld.service
[Unit]
Description=Flanneld
After=network.target
After=network-online.target
Wants=network-online.target
##1.flannel服务需要先于Docker启动,后于etcd启动
After=etcd.service
Before=docker.service
[Service]
User=root
##2.ExecStart即flanneld启动程序位置
##3.--etcd-endpoints参数为ectd集群客户端地址
##4.--iface参数为要绑定的网卡的IP地址,或是网卡名(ifconfig查看获得)请根据实际情况修改
ExecStart=/opt/flannel/flanneld \
--etcd-endpoints=http://192.168.27.110:2379,http://192.168.27.120:2379 \
--etcd-prefix=/coreos.com/network \
--iface=ens33 \
--ip-masq
Restart=on-failure
Type=notify
LimitNOFILE=65536
[Install]
WantedBy=multi-user.target
systemctl daemon-reload && systemctl restart flanneld
2.4 docker配置
创建Docker运行参数(使用flannel提供的脚本将subnet.env转写成Docker启动参数)
/opt/flannel/mk-docker-opts.sh -d /run/flannel/docker_opts.env -c
修改Docker启动参数
vim /lib/systemd/system/docker.service
[Unit]
Description=Docker Application Container Engine
Documentation=https://docs.docker.com
After=network-online.target firewalld.service containerd.service
Wants=network-online.target
Requires=docker.socket containerd.service
[Service]
EnvironmentFile=/run/flannel/docker_opts.env
Type=notify
# the default is not to use systemd for cgroups because the delegate issues still
# exists and systemd currently does not support the cgroup feature set required
# for containers run by docker
ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock $DOCKER_OPTS
ExecReload=/bin/kill -s HUP $MAINPID
TimeoutSec=0
RestartSec=2
Restart=always
# Note that StartLimit* options were moved from "Service" to "Unit" in systemd 229.
# Both the old, and new location are accepted by systemd 229 and up, so using the old location
# to make them work for either version of systemd.
StartLimitBurst=3
# Note that StartLimitInterval was renamed to StartLimitIntervalSec in systemd 230.
# Both the old, and new name are accepted by systemd 230 and up, so using the old name to make
# this option work for either version of systemd.
StartLimitInterval=60s
# Having non-zero Limit*s causes performance problems due to accounting overhead
# in the kernel. We recommend using cgroups to do container-local accounting.
LimitNOFILE=infinity
LimitNPROC=infinity
LimitCORE=infinity
# Comment TasksMax if your systemd version does not support it.
# Only systemd 226 and above support this option.
TasksMax=infinity
# set delegate yes so that systemd does not reset the cgroups of docker containers
Delegate=yes
# kill only the docker process, not all processes in the cgroup
KillMode=process
OOMScoreAdjust=-500
[Install]
WantedBy=multi-user.target
重新加载systemd配置,并重启Docker
systemctl daemon-reload && systemctl restart docker && systemctl status docker
此时docker0的网卡ip地址已经处于flannel网卡网段中
3.测试flannel
创建容器
docker run -itd --name=centos centos bash
测试从不同宿主机容器ping到其他宿主机容器
经测试,发现是防火墙的问题,关闭防火墙后问题解决,但作为服务的防火墙是不能关闭的,如何解决呢
这是由于linux还有底层的iptables,所以在node上分别执行:
iptables -P INPUT ACCEPT
iptables -P FORWARD ACCEPT
iptables -F
iptables -L -n