欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

kubernetes单节点集群搭建之CNI flannel网络安装

程序员文章站 2024-01-15 15:34:58
...

一、前言

kubernetes集群搭建方法很多

1.可以用第三方工具,比如minikube,kubeadm。

2.也可以去kubernetes官网下release出的二进制bin文件。

3.下载kubernetes源码,手动编译后生成二进制bin文件,该方法适用于需要对kubernetes源码进行改动或者二次开发的同学。

 

本文采用第三种方法,即编译源码的方式。

编译过程不在这详述,安装好后,如果没有安装额外的cni插件,默认会以docker0作为pod的网络。但在默认的Docker配置中,每个Node的Docker服务会分别负责所在节点容器的IP分配。Node内部得容器之间可以相互访问,但是跨主机(Node)网络相互间是不能通信。

因此需要安装额外的cni网络插件,让集群中的不同节点主机创建的Docker容器都具有全集群唯一的虚拟IP地址,并且不同node上的pod容器可以相互通信。

 

二、CNI插件类型简介

1.Flannel

kubernetes单节点集群搭建之CNI flannel网络安装

简单解释下这个原理图:

  • 数据从源容器中发出后,经由所在主机的docker0虚拟网卡转发到flannel0虚拟网卡,这是个P2P(pair to pair)的虚拟网卡,flanneld服务监听在网卡的另外一端。
  • Flannel通过Etcd服务维护了一张节点间的路由表,该张表里保存了各个节点主机的子网网段信息。
  • 源主机的flanneld服务将原本的数据内容UDP封装后根据自己的路由表投递给目的节点的flanneld服务,数据到达以后被解包,然后直接进入目的节点的flannel0虚拟网卡,然后被转发到目的主机的docker0虚拟网卡,最后就像本机容器通信一样的由docker0路由到达目标容器。
  • 当然也可以不用udp进行封装,vxlan、host-gw等。

Flannel配置第3层IPv4 Overlay网络。它会创建一个大型内部网络,跨越集群中每个节点。在此Overlay网络中,每个节点都有一个子网,用于在内部分配IP地址。在配置Pod时,每个节点上的Docker桥接口都会为每个新容器分配一个地址。同一主机中的Pod可以使用Docker桥接进行通信,而不同主机上的pod会使用flanneld将其流量封装在UDP数据包中,以便路由到适当的目标。

Flannel有几种不同类型的后端可用于封装和路由。默认和推荐的方法是使用VXLAN,因为VXLAN性能更良好并且需要的手动干预更少。

总的来说,Flannel是大多数用户的不错选择。从管理角度来看,它提供了一个简单的网络模型,用户只需要一些基础知识,就可以设置适合大多数用例的环境。一般来说,在初期使用Flannel是一个稳妥安全的选择,直到你开始需要一些它无法提供的东西。

 

2.Calico

Calico是Kubernetes生态系统中另一种流行的网络选择。虽然Flannel被公认为是最简单的选择,但Calico以其性能、灵活性而闻名。Calico的功能更为全面,不仅提供主机和pod之间的网络连接,还涉及网络安全和管理。Calico CNI插件在CNI框架内封装了Calico的功能。

与Flannel不同,Calico不使用overlay网络。相反,Calico配置第3层网络,该网络使用BGP路由协议在主机之间路由数据包。这意味着在主机之间移动时,不需要将数据包包装在额外的封装层中。BGP路由机制可以本地引导数据包,而无需额外在流量层中打包流量。与flannel相比降低了损耗,提高了效率。

除了性能优势之外,在出现网络问题时,用户还可以用更常规的方法进行故障排除。虽然使用VXLAN等技术进行封装也是一个不错的解决方案,但该过程处理数据包的方式同场难以追踪。使用Calico,标准调试工具可以访问与简单环境中相同的信息,从而使更多开发人员和管理员更容易理解行为。

除了网络连接外,Calico还以其先进的网络功能而闻名。 网络策略是其最受追捧的功能之一。此外,Calico还可以与服务网格Istio集成,以便在服务网格层和网络基础架构层中解释和实施集群内工作负载的策略。这意味着用户可以配置强大的规则,描述Pod应如何发送和接受流量,提高安全性并控制网络环境。

如果对你的环境而言,支持网络策略是非常重要的一点,而且你对其他性能和功能也有需求,那么Calico会是一个理想的选择。此外,如果您现在或未来有可能希望得到技术支持,那么Calico是提供商业支持的。一般来说,当您希望能够长期控制网络,而不是仅仅配置一次并忘记它时,Calico是一个很好的选择。

 

3.Weave

Weave是由Weaveworks提供的一种Kubernetes CNI网络选项,它提供的模式和我们目前为止讨论的所有网络方案都不同。Weave在集群中的每个节点之间创建网状Overlay网络,参与者之间可以灵活路由。这一特性再结合其他一些独特的功能,在某些可能导致问题的情况下,Weave可以智能地路由。

为了创建网络,Weave依赖于网络中每台主机上安装的路由组件。然后,这些路由器交换拓扑信息,以维护可用网络环境的最新视图。当需要将流量发送到位于不同节点上的Pod时,Weave路由组件会自动决定是通过“快速数据路径”发送,还是回退到“sleeve”分组转发的方法。

对于那些寻求功能丰富的网络、同时希望不要增加大量复杂性或管理难度的人来说,Weave是一个很好的选择。它设置起来相对容易,提供了许多内置和自动配置的功能,并且可以在其他解决方案可能出现故障的场景下提供智能路由。网状拓扑结构确实会限制可以合理容纳的网络的大小,不过对于大多数用户来说,这也不是一个大问题。

 

三、flannel网络下,pod获取ip的流程:

结合使用docker容器引擎以及flannel插件来说就是,kubelet通过CRI接口创建POD,它会第一个创建Infra容器,这一步是调用Dokcer对CRI的实现(dockershim),dockershim调用docker api来完成,然后就会设置网络,首选需要准备CNI插件参数、其次就是传递参数并调用这个CNI插件去设置Infra网络。对于flannel插件所需要的参数包含2个部分:

  1. kubelet通过CRI调用dockershim时候传递的一组信息,也就是具体动作比如ADD或者DEL以及这些动作所需要的参数,如果是ADD的话则包括容器网卡名称、POD的Network namespace路径、容器的ID等。

  2. dockershim从CNI配置文件中加载到的(在CNI中叫做Network Configuration),也就是从--cni-conf-dir目录中加载的默认配置信息。

有了上面2部分信息之后,dockershim就会把这个信息给flannel插件,插件会对第二部分信息做补充,然后这个插件来做ADD操作,而这个操作是由CNI bridge这个插件来完成的。这个bridge使用全部的参数信息来执行把容器加入到CNI网络的操作了。它会做如下内容:

  1. 检查是否有CNI网桥,如果没有就创建并UP这个网桥,相当于在宿主机上执行ip link add cni0 type bridgeip link set cni0 up命令

  2. 接下来bridge会通过传递过来的Infra容器的网络名称空间文件进入这个网络名称空间中,然后创建Veth Pair设备,然后UP容器的这一端eth0,然后将另外一端放到宿主机名称空间里并UP这个设备。

  3. bridge把宿主机的一端连接到网桥cni0上

  4. bridge会调用IPAM插件为容器的eth0分配IP地址,并设置默认路由。

  5. bridge会为CNI网桥添加IP地址,如果是第一次的话。

  6. 最后CNI插件会把容器的IP地址等信息返回给dockershim,然后被kubelet添加到POD的status字段中。

可以看到下面的截图:

kubernetes单节点集群搭建之CNI flannel网络安装

cni0网桥其实就是docker0虚拟网卡,他们会和flannel0虚拟网卡通信。

而veth04b806e8和veth9bdcc769等设备,就是容器Veth Pair设备在宿主机的另一端。这些设备会被bridge连接到网桥cni0(docker0)上,也就形成了下面红框中的状态:

kubernetes单节点集群搭建之CNI flannel网络安装

 

四、Flannel网络插件安装

由于是单节点集群,且对网络性能要求没有那么苛刻,因此选择了flannel。后续也会尝试calico。

a)停止node的kubelet和docker服务

systemctl stop docker

systemctl stop kubelet

 

b)向etcd注册网段。

由于flanneld需要依赖etcd来保证集群IP分配不冲突的问题,所以首先要在etcd中设置 flannel节点所使用的IP段。

利用etcdctl添加k-v记录,在文件/coreos.com/network/config中添加记录。

etcdctl --endpoints="https://192.168.209.130:2379" set /coreos.com/network/config '{"Network":"10.149.0.0/16","Backend": {"Type": "vxlan"}}'

network表示想要pod使用的ip网段cidr。这里可以随意选择网段,我选择了10.149.0.0/16。type选择vxlan,性能较好。

 

c)安装Flannel

1.下载flannel,并解压:https://github.com/coreos/flannel/releases。选择最新版的0.12.0版本的二进制包。解压后,有用的就2个文件,flanneld二进制程序和一个脚本:mk-docker-opts.sh。其中flanneld就是我们需要启动的flannel程序;而mk-docker-opts.sh的作用在于将分配给 flanneld 的 Pod 子网网段信息写入指定的docker配置文件中,后续 docker 启动时使用这个文件中的环境变量配置 docker0 网桥,具体如何使用请往下看。

2.将flanneld和mk-docker-opts.sh移动到/usr/bin/目录下,这样就可以直接运行,不需要加路径。

3.配置flanneld的启动配置文件:

新建文件:/etc/kubernetes/flanneld

FLANNEL_OPTIONS="--etcd-endpoints=http://9.134.33.208:2379 \
--etcd-prefix=/coreos.com/network"

这个文件配置了flannel启动所需参数变量,主要就是etcd的信息,因为flannel需要向etcd获取我们所设置的网段,并根据此对pod ip进行分配。

新建文件:/etc/systemd/system/flanneld.service

[Unit]
Description=Flanneld overlay address etcd agent
After=network-online.target network.target
Before=docker.service

[Service]
Type=notify
EnvironmentFile=/etc/kubernetes/flanneld
ExecStart=/usr/bin/flanneld --ip-masq $FLANNEL_OPTIONS
Restart=on-failure

[Install]
WantedBy=multi-user.target

其中,EnvironmentFile是flanneld的环境配置文件,这个文件里包含了flanneld运行需要用到的一些变量,比如ExecStart=/usr/bin/flanneld --ip-masq $FLANNEL_OPTIONS中的$FLANNEL_OPTIONS变量,就是/etc/kubernetes/flanneld中定义的。

 

d)安装CNI网络插件

CNI插件可以认为是一种适配插口,能够让kubernetes与flannel,calico等无修改进行对接安装。由于kubernetes采用二进制的形式,这里也采用二进制的形式进行安装。

1.新建存放CNI插件的目录:mkdir -p /opt/cni/{bin,net.d}

2.下载cni到上面的bin目录,并解压:https://github.com/containernetworking/plugins/releases,选择最新版本的v0.8.5的二进制包。

3.在上面的net.d目录新建10-flannel.conflist文件,内容如下:

{
  "name": "cni0",
  "cniVersion": "0.8.5",
  "subnetFile": "/run/flannel/subnet.env",
  "plugins": [
    {
      "type": "flannel",
      "delegate": {
        "hairpinMode": true,
        "isDefaultGateway": true
      }
    },
    {
      "type": "portmap",
      "capabilities": {
        "portMappings": true
      }
    }
  ]
}

name: 网络名称而不是网桥的名字

cniVersion: 插件版本,可以不写。

subnetFile: 本机flanneld从etcd中申请的本机网段,这个信息存放在哪个文件中,默认就是/run/flannel/subnet.env。这个文件是flanneld服务启动后,自动生成的。

plugins:表示使用什么插件

type: 插件类型,这里是flannel,如果尝试其他网络插件,这些就写插件的名字比如calico等

 

e)启动flanneld服务。

systemctl daemon-reload
systemctl start flanneld
systemctl enable flanneld

然后检查下网卡信息:ifconfig

发现会多一个:

kubernetes单节点集群搭建之CNI flannel网络安装

这个虚拟网卡就是上面flannel原理图中的flannel0。ip地址为10。149.84.0,也符合我们在etcd中注册的网段。

然后再检查下生成的/run/flannel/subnet.env文件:

kubernetes单节点集群搭建之CNI flannel网络安装

 

f)修改docker服务配置,并启动docker

pod的ip实际上是由docker分配的,且docker0虚拟网卡需要与flannel0通信,也就是两者必须在同一网段。那么就需要修改docker的网络桥(docker0)ip。

bip这个参数就是设置docker分配给容器的ip网段,以及自身docker0的ip。

可以在/etc/docker/daemon.json文件中添加bip这个选项来修改。或者在/etc/systemd/system/docker.service中的ExecStart=/usr/bin/dockerd后加上bip这个参数。

那么该如何知道flannel0所在的ip段呢。之前mk-docker-opts.sh脚本和flannel生成的生成的/run/flannel/subnet.env起作用了。

利用mk-docker-opts.sh可以生成符合docker服务的配置参数。命令如下:

mk-docker-opts.sh -d /run/docker_opts.env

-d后就是期望生成的符合docker的配置参数格式的文件。mk-docker-opts.sh脚本默认会从/run/flannel/subnet.env读取信息,然后转换成docker格式的配置。输出到/run/docker_opts.env。

/run/docker_opts.env内容如下:

kubernetes单节点集群搭建之CNI flannel网络安装

可以看到DOCKER_NETWORK_OPTIONS里包含了bip参数配置和其他参数配置。

接下来就是修改/etc/systemd/system/docker.service文件来添加docker的bip启动参数了:

kubernetes单节点集群搭建之CNI flannel网络安装

EnvironmentFile参数表示docker变量的读取位置,这里就是/run/docker_opts.env

ExecStart=/usr/bin/dockerd $DOCKER_NETWORK_OPTIONS其中的$DOCKER_NETWORK_OPTIONS变量就是/run/docker_opts.env中的DOCKER_NETWORK_OPTIONS。

修改好后,启动docker服务:

systemctl daemon-reload
systemctl start docker
systemctl enable docker

检查ifconfig:

kubernetes单节点集群搭建之CNI flannel网络安装

生成docker0网卡,ip和flannel0在同一网段。

 

g)配置kubelet服务,并重启kubelet

配置kubelet服务的CNI插件目录等。

修改kubelet服务文件,增加3个参数:--cni-bin-dir=/opt/cni/bin --cni-conf-dir=/opt/cni/net.d --network-plugin=cni

/etc/systemd/system/kubelet.service

kubernetes单节点集群搭建之CNI flannel网络安装

修改完后,启动kubelet:

systemctl daemon-reload
systemctl start kubelet
systemctl enable kubelet

检验,看node是否ready即可:

kubelet get node,如果node ready了,表示安装成功。

 

五、注意事项

a)如果修改docker后,启动docker服务,docker0网卡的网段没有变化,没有生效,则需要手动把docker0网卡删除,再启动docker服务即可。

sudo service docker stop

sudo ip link set dev docker0 down

sudo brctl delbr docker0

sudo service docker restart