Flannel 技术调研,固定主机和容器IP的方法

简介

Flannel是CoreOS团队针对Kubernetes设计的一个网络规划服务,简单来说,它的功能是让集群中的不同节点主机创建的Docker容器都具有全集群唯一的虚拟IP地址。但在默认的Docker配置中, 每个节点上的Docker服务会分别负责所在节点容器的IP分配。这样导致的一个问题是,不同节点上容器可能获得相同的内外IP地址。并使这些容器之间能够之间通过IP地址相互找到,也就是相 互ping通。

Flannel的设计目的就是为集群中的所有节点重新规划IP地址的使用规则,从而使得不同节点上的容器能够获得"同属一个内网"且"不重复的"IP地址,并让属于不同节点上的容器能够直接通过内网IP通信。

Flannel实质上是一种"覆盖网络(overlay network)",即表示运行在一个网上的网(应用层网络),并不依靠ip地址来传递消息,而是采用一种映射机制,把ip地址和identifiers做映射来资源定位。也就 是将TCP数据包装在另一种网络包里面进行路由转发和通信,目前已经支持UDP、VxLAN、AWS VPC和GCE路由等数据转发方式。

原理是每个主机配置一个ip段和子网个数。例如,可以配置一个覆盖网络使用 10.100.0.0/16段,每个主机/24个子网。因此主机a可以接受10.100.5.0/24,主机B可以接受10.100.18.0/24的包。flannel使用etcd来维护分配的子网到实际的ip地址之间的映射。对于数据路径,flannel 使用udp来封装ip数据报,转发到远程主机。选择UDP作为转发协议是因为他能穿透防火墙。例如,AWS Classic无法转发IPoIP or GRE 网络包,是因为它的安全组仅仅支持TCP/UDP/ICMP。

flannel 使用etcd存储配置数据和子网分配信息。flannel 启动之后,后台进程首先检索配置和正在使用的子网列表,然后选择一个可用的子网,然后尝试去注册它。 etcd也存储这个每个主机对应的ip。flannel 使用etcd的watch机制监视/coreos.com/network/subnets下面所有元素的变化信息,并且根据他来维护一个路由表。为了提高性能,flannel优化了Universal TAP/TUN设备,对TUN和UDP之间的ip分片做了代理。

另外,flannel是没有DNS服务的,容器无法通过hostname通信。

安装

需要先安装etcd,之后可以使用yum方式安装flannel

复制代码
yum install -y flannel

首先使用etcdctl命令在etcd服务中写入flannel需要用到的配置,注意set之后的路径前缀需要和flannel的配置文件中的FLANNEL_ETCD_PREFIX一致

swift 复制代码
etcdctl set /zkxl_flannel/network/config '{"Network": "10.0.0.0/16", "SubnetLen": 24, "SubnetMin": "10.0.0.0","SubnetMax": "10.0.199.0", "Backend": {"Type": "vxlan"}}'

Network:用于指定Flannel地址池

SubnetLen:用于指定分配给单个宿主机的docker0的ip段的子网掩码的长度

SubnetMin:用于指定最小能够分配的ip段

SudbnetMax:用于指定最大能够分配的ip段,在上面的示例中,表示每个宿主机可以分配一个24位掩码长度的子网,可以分配的子网从10.0.0.0/24到10.0.199.0/24,也就意味着在这个网段中,最多只能有200台宿主机

Backend:用于指定数据包以什么方式转发,默认为udp模式,host-gw模式性能最好,但不能跨宿主机网络

修改flannel配置文件,注意其中的FLANNEL_ETCD_PREFIX 要和之前设置到etcd中的路径前缀一致

bash 复制代码
vim /etc/sysconfig/flanneld
bash 复制代码
# Flanneld configuration options  

# etcd url location.  Point this to the server where etcd runs
FLANNEL_ETCD_ENDPOINTS="http://127.0.0.1:2379"

# etcd config key.  This is the configuration key that flannel queries
# For address range assignment
FLANNEL_ETCD_PREFIX="/zkxl_flannel/network"

# Any additional options that you want to pass
#FLANNEL_OPTIONS=""

启动flanneld

bash 复制代码
systemctl start flanneld
systemctl status flanneld

启动 flanneld 后,会有一张 flannel0 网卡产生:而且还生成了配置文件 /run/flannel/subnet.env,此网卡的地址就是之前在etcd中定义的网段地址。

这样则会生成/run/flannel/docker文件, 在这个文件中一般会给docker提供一个设定参数DOCKER_NETWORK_OPTIONS,DOCKER_NETWORK_OPTIONS中会包含如下设定信息:

--bip

--ip-masq

--mtu

而在docker的systemd的service中,只需要将DOCKER_NETWORK_OPTIONS传递给dockerd即可。

bash 复制代码
vim /usr/lib/systemd/system/docker.service

# 然后在ExecStart中添加$DOCKER_NETWORK_OPTIONS,如下所示
ExecStart=/usr/bin/dockerd $DOCKER_NETWORK_OPTIONS -H fd:// --containerd=/run/containerd/containerd.sock

然后重启docker,这样Flannel配置分配的ip才能生效,即docker0虚拟网卡的ip会变成上面flannel设定的ip段。

bash 复制代码
systemctl daemon-reload
systemctl restart docker

# 之后查看docker进程的启动,应该能看到相关的参数了

ps -ef | grep docker

root     18793     1  0 17:08 ?        00:00:00 /usr/bin/dockerd --bip=10.0.26.1/24 --ip-masq=true --mtu=1450 -H fd:// --containerd=/run/containerd/containerd.sock
root     18931 18741  0 17:09 pts/2    00:00:00 grep --color=auto docker

方案

如何固定某个主机的IP配置

参考官方文档中的介绍 flannel/reservations.md at master · flannel-io/flannel · GitHub

ini 复制代码
# 先看下在当前配置中本机分配到的IP地址段
cat /run/flannel/subnet.env

FLANNEL_NETWORK=10.0.0.0/16
FLANNEL_SUBNET=10.0.76.1/24  # 这里就是在当前配置下分配到的网段
FLANNEL_MTU=1450
FLANNEL_IPMASQ=false

# 先关掉flannel服务,防止修改过程中会更新还未修改完的配置
systemctl stop flanneld

# 查看当前etcd中存储的相关网段配置
etcdctl ls /zkxl_flannel/network/subnets

/zkxl_flannel/network/subnets/10.0.76.0-24     # 这一行就是当前主机的配置,我们要复制一份
/zkxl_flannel/network/subnets/10.0.84.0-24

# 以下命令复制了一份现在的配置,但是会把新的IP段设置到10.0.0.0-24这个网段,并且把ttl过期时间设置成0,这样这个配置就会变成永久的预留
etcdctl set -ttl 0 /zkxl_flannel/network/subnets/10.0.0.0-24 $(etcdctl get /zkxl_flannel/network/subnets/10.0.76.0-24)

# 删除原来的
etcdctl rm /zkxl_flannel/network/subnets/10.0.76.0-24

# 之后修改本机的subnet.env
vim /run/flannel/subnet.env

FLANNEL_NETWORK=10.0.0.0/16
FLANNEL_SUBNET=10.0.0.1/24  # 这里修改成想要调整到的网段
FLANNEL_MTU=1450
FLANNEL_IPMASQ=false

# 重新启动flannel服务
systemctl start flanneld

# 最后要重启docker服务
systemctl restart docker

如何固定某个容器的IP

flannel会给每个物理机的docker添加一个默认的网桥,通过这个网桥各个容器都是互通的,但是我们这里还有一个需求,就是怎么固定住其中的容器的IP?这个暂时没有找到有效的解决方法,使用docker-compose配置时只能使用自定义的网桥网络时才能指定IP,而flannel这个对于docker属于external网络,这时候就不能自己指定IP了。

Static ip · Issue #167 · flannel-io/flannel · GitHub在这个issue中,最后tomdee的回答如下,他提供了一种固定某个主机的IP配置的方式,也就是上面的章节中我们提到的方式,但是tomdee认为固定容器IP的方式不属于flannel应该解决的问题。

Static subnet reservation for a host can be done following this doc I added github.com/coreos/flan...

Static IP addresses for individual containers/pods is not something to flannel manages.

参考文档

相关推荐
m0_515790414 小时前
【深度学习实战(55)】记录一次在新服务器上使用docker的流程
docker
草明5 小时前
docker stats 增加一列容器名称的显示
java·开发语言·docker
楚禾Noah7 小时前
【通用常识】YAML 中的高阶语法
运维·docker·容器
东心十15 小时前
Win11安装WSL、Docker Desktop
运维·docker·容器
预判你的代码20 小时前
Docker 快速下载Neo4j 方法记录
docker·容器·neo4j
计算机小手20 小时前
基于 Flask 与 Milvus 构建高效图片搜索引擎,可通过API接入,支持Docker一键部署
经验分享·docker·flask·开源软件·milvus
楠有枝1 天前
普通用户使用docker命令
spring cloud·docker·eureka
冷面杰拉德1 天前
vscode连接docker
ide·vscode·docker
刘一说1 天前
CentOS 8开发测试环境:直接安装还是Docker更优?
linux·服务器·docker·centos
-小末1 天前
使用docker manifest制作本地多架构镜像
docker·容器·多架构镜像