Docker学习笔记 — Coreos/Flannel

Flannel介绍


Flannel是CoreOS团队针对Kubernetes设计的一个网络规划服务,简单来说,它的功能是让集群中的不同节点主机创建的Docker容器都具有全集群唯一的虚拟IP地址。

在Kubernetes的网络模型中,假设了每个物理节点应该具备一段“属于同一个内网IP段内”的“专用的子网IP”。例如:

节点A:10.0.1.0/24
节点B:10.0.2.0/24
节点C:10.0.3.0/24

但在默认的Docker配置中,每个节点上的Docker服务会分别负责所在节点容器的IP分配。这样导致的一个问题是,不同节点上容器可能获得相同的内外IP地址。并使这些容器之间能够之间通过IP地址相互找到,也就是相互ping通。

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

Flannel的工作原理


Flannel实质上是一种“覆盖网络(overlay network)”,也就是将TCP数据包装在另一种网络包里面进行路由转发和通信,目前已经支持UDP、VxLAN、AWS VPC和GCE路由等数据转发方式。

默认的节点间数据通信方式是UDP转发,在Flannel的GitHub页面有如下的一张原理图:

这里写图片描述

这张图的信息量很全,下面简单的解读一下。

数据从源容器中发出后,经由所在主机的docker0虚拟网卡转发到flannel0虚拟网卡,这是个P2P的虚拟网卡,flanneld服务监听在网卡的另外一端。

Flannel通过Etcd服务维护了一张节点间的路由表,在稍后的配置部分我们会介绍其中的内容。

源主机的flanneld服务将原本的数据内容UDP封装后根据自己的路由表投递给目的节点的flanneld服务,数据到达以后被解包,然后直接进入目的节点的flannel0虚拟网卡,然后被转发到目的主机的docker0虚拟网卡,最后就像本机容器通信一下的有docker0路由到达目标容器。

这样整个数据包的传递就完成了,这里需要解释三个问题。

UDP封装是怎么一回事?

我们来看下面这个图,这是在其中一个通信节点上抓取到的ping命令通信数据包。可以看到在UDP的数据内容部分其实是另一个ICMP(也就是ping命令)的数据包。

这里写图片描述

原始数据是在起始节点的Flannel服务上进行UDP封装的,投递到目的节点后就被另一端的Flannel服务还原成了原始的数据包,两边的Docker服务都感觉不到这个过程的存在。

为什么每个节点上的Docker会使用不同的IP地址段?

这个事情看起来很诡异,但真相十分简单。其实只是单纯的因为Flannel通过Etcd分配了每个节点可用的IP地址段后,偷偷的修改了Docker的启动参数,见下图。

这里写图片描述

这个是在运行了Flannel服务的节点上查看到的Docker服务进程运行参数。

注意其中的“–bip=172.17.18.1/24”这个参数,它限制了所在节点容器获得的IP范围。

这个IP范围是由Flannel自动分配的,由Flannel通过保存在Etcd服务中的记录确保它们不会重复。

为什么在发送节点上的数据会从docker0路由到flannel0虚拟网卡,在目的节点会从flannel0路由到docker0虚拟网卡?

我们来看一眼安装了Flannel的节点上的路由表。下面是数据发送节点的路由表:

这里写图片描述

这个是数据接收节点的路由表:

这里写图片描述

例如现在有一个数据包要从IP为172.17.18.2的容器发到IP为172.17.46.2的容器。根据数据发送节点的路由表,它只与172.17.0.0/16匹配这条记录匹配,因此数据从docker0出来以后就被投递到了flannel0。同理在目标节点,由于投递的地址是一个容器,因此目的地址一定会落在docker0对于的172.17.46.0/24这个记录上,自然的被投递到了docker0网卡。

Flannel的安装和配置


Flannel是Golang编写的程序,因此的安装十分简单。

https://github.com/coreos/flannel/releaseshttps://github.com/coreos/etcd/releases分别下载Flannel和Etcd的最新版本二进制包。

解压后将Flannel的二进制文件“flanneld”和脚本文件“mk-docker-opts.sh”、以及Etcd的二进制文件“etcd”和“etcdctl”放到系统的PATH目录下面安装就算完成了。

配置部分要复杂一些。

首先启动Etcd,参考https://github.com/coreos/etcd … overy。

访问这个地址:https://discovery.etcd.io/new?size=3 获得一个“Discovery地址”

在每个节点上运行以下启动命令:

etcd -initial-advertise-peer-urls http://<当前节点IP>:2380 -listen-peer-urls http://<当前节点IP>:2380 -listen-client-urls http://<当前节点IP>:2379,http://<当前节点IP>:2379 -advertise-client-urls http://<当前节点IP>:2379  -discovery <刚刚获得的Discovery地址> &

启动完Etcd以后,就可以配置Flannel了。

Flannel的配置信息全部在Etcd里面记录,往Etcd里面写入下面这个最简单的配置,只指定Flannel能用来分配给每个Docker节点的拟IP地址段:

etcdctl set /coreos.com/network/config '{ "Network": "172.17.0.0/16" }'

然后在每个节点分别启动Flannel:

flanneld &

最后需要给Docker动一点手脚,修改它的启动参数和docker0地址。

在每个节点上执行:

sudo mk-docker-opts.sh -i
source /run/flannel/subnet.env
sudo rm /var/run/docker.pid
sudo ifconfig docker0 ${FLANNEL_SUBNET} 

重启动一次Docker,这样配置就完成了。

现在在两个节点分别启动一个Docker容器,它们之间已经通过IP地址直接相互ping通了。

到此,整个Flannel集群也就正常运行了。

最后,前面反复提到过Flannel有一个保存在Etcd的路由表,可以在Etcd数据中找到这些路由记录,如下图。

这里写图片描述



转载自:DockOne技术分享(十八):一篇文章带你了解Flannel

<think>好的,用户的问题是关于在应用kube-flannel.yml时,组件显示unchanged状态的原因。我需要先理解kubectl apply命令的工作原理。这个命令会对比当前集群中的资源状态和YAML文件中定义的期望状态,如果两者一致,就会显示unchanged。这可能是因为用户之前已经成功应用过相同的配置文件,所以没有变化。 接下来,用户提供的引用内容提到他们使用了特定的镜像版本,比如flannel v0.25.5和cni-plugin v1.5.1-flannel1。这些信息说明用户可能正确配置了镜像,避免了版本不一致的问题。此外,引用中还提到kube-flannel.yml文件是从特定URL下载的,或者来自已验证的包,这可能意味着文件内容没有变动,导致多次应用时没有更新。 我需要考虑其他可能的原因,比如配置没有实质性改动,或者资源已经处于稳定状态。另外,权限问题或网络问题也可能导致apply失败,但根据unchanged的状态提示,更可能是配置未变化。需要向用户解释这些可能性,并提供验证步骤,比如检查资源状态、查看事件日志,或者手动删除后重新应用。同时,提醒用户如果确实需要更新,应该修改配置文件中的版本或其他字段,以触发更新操作。</think>关于执行`kubectl apply -f kube-flannel.yml`时显示组件状态为`unchanged`的问题,以下是具体原因和验证方法: ### 原因分析 1. **配置未发生变化** Kubernetes通过`kubectl apply`命令对比**当前集群资源状态**与YAML文件定义的**期望状态**。若二者完全一致,控制台会返回`<resource-name> unchanged`,这是Kubernetes声明式API的正常行为[^1][^2]。 2. **镜像版本已固定** 根据您提供的引用信息,YAML中已明确指定镜像版本: ```yaml image: docker.io/flannel/flannel:v0.25.5 image: docker.io/flannel/flannel-cni-plugin:v1.5.1-flannel1 ``` 这避免了因镜像版本拉取策略导致的意外更新[^3]。 3. **历史操作记录** 若之前已成功执行过相同的`kubectl apply`操作,且后续未修改YAML文件内容,系统会持续维持当前状态。 ### 验证步骤 1. **检查资源状态** ```bash kubectl get daemonset -n kube-system kube-flannel-ds kubectl describe daemonset kube-flannel-ds -n kube-system ``` 观察`Events`字段是否显示正常调度记录 2. **强制更新操作** 修改YAML文件中的注释或无关字段(如添加`# updated`),重新执行`kubectl apply` 3. **日志验证** ```bash kubectl logs -n kube-system -l app=flannel --tail=50 ``` 确认日志中无`CrashLoopBackOff`等异常状态 ### 特殊场景说明 若需强制替换配置,可使用: ```bash kubectl replace --force -f kube-flannel.yml ``` 该命令会先删除旧资源再创建新实例,但需注意服务短暂中断风险。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值