K8S(03)核心插件-Flannel网络插件
系列文章说明
本系列文章,可以基本算是 老男孩2019年王硕的K8S周末班课程 笔记,根据视频来看本笔记最好,否则有些地方会看不明白
需要视频可以联系我
K8S核心网络插件Flannel
k8s虽然设计了网络模型,然后将实现方式交给了CNI网络插件,而CNI网络插件的主要目的,就是实现POD资源能够跨宿主机进行通信
常见的网络插件有flannel,calico,canal,但是最简单的flannel已经完全满足我们的要求,故不在考虑其他网络插件
网络插件Flannel介绍:https://www.kubernetes.org.cn/3682.html
1 flannel功能概述
1.1 flannel运转流程
- 首先
flannel利用Kubernetes API或者etcd用于存储整个集群的网络配置,其中最主要的内容为设置集群的网络地址空间。
例如,设定整个集群内所有容器的IP都取自网段“10.1.0.0/16”。 - 接着
flannel在每个主机中运行flanneld作为agent,它会为所在主机从集群的网络地址空间中,获取一个小的网段subnet,本主机内所有容器的IP地址都将从中分配。
例如,设定本主机内所有容器的IP地址网段“10.1.2.0/24”。 - 然后
flanneld再将本主机获取的subnet以及用于主机间通信的Public IP,同样通过kubernetes API或者etcd存储起来。 - 最后
flannel利用各种backend mechanism,例如udp,vxlan等等,跨主机转发容器间的网络流量,完成容器间的跨主机通信。 
1.2 flannel的网络模型
1.2.1 flannel支持3种网络模型
host-gw网关模型{"Network": "xxx", "Backend": {"Type": "host-gw"}}
主要用于宿主机在同网段的情况下POD间的通信,即不跨网段通信.
此时flannel的功能很简单,就是在每个宿主机上创建了一条通网其他宿主机的网关路由
完全没有性能损耗,效率极高vxlan隧道模型
{"Network": "xxx", "Backend": {"Type": "vxlan"}}
主要用于宿主机不在同网段的情况下POD间通信,即跨网段通信.
此时flannel会在宿主机上创建一个flannel.1的虚拟网卡,用于和其他宿主机间建立VXLAN隧道
跨宿主机通信时,需要经由flannel.1设备封包、解包,因此效率不高混合模型
{"Network": "xxx", "Backend": {"Type": "vxlan","Directrouting": true}}
在既有同网段宿主机,又有跨网段宿主机的情况下,选择混合模式
flannel会根据通信双方的网段情况,自动选择是走网关路由通信还是通过VXLAN隧道通信
1.2.2 实际工作中的模型选择
很多人不推荐部署K8S的使用的flannel做网络插件,不推荐的原因是是flannel性能不高,然而
- flannel性能不高是指它的VXLAN隧道模型,而不是gw模型
 - 规划K8S集群的时候,应规划多个K8S集群来管理不同的业务
 - 同一个K8S集群的宿主机,就应该规划到同一个网段
 - 既然是同一个网段的宿主机通信,使用的就应该是gw模型
 - gw模型只是创建了网关路由,通信效率极高
 - 因此,建议工作中使用flannel,且用
gw模型 
2. 部署flannel插件
2.1 在etcd中写入网络信息
以下操作在任意etcd节点中执行都可以
/opt/etcd/etcdctl set /coreos.com/network/config '{"Network": "172.7.0.0/16", "Backend": {"Type": "host-gw"}}'
# 查看结果
[root@hdss7-12 ~]# /opt/etcd/etcdctl get /coreos.com/network/config
{"Network": "172.7.0.0/16", "Backend": {"Type": "host-gw"}}
2.2 部署准备
2.2.1 下载软件
wget https://github.com/coreos/flannel/releases/download/v0.11.0/flannel-v0.11.0-linux-amd64.tar.gz
mkdir /opt/flannel-v0.11.0
tar xf flannel-v0.11.0-linux-amd64.tar.gz -C /opt/flannel-v0.11.0/
ln -s /opt/flannel-v0.11.0/ /opt/flannel
2.2.2 拷贝证书
因为要和apiserver通信,所以要配置client证书,当然ca公钥自不必说
cd /opt/flannel
mkdir cert
scp hdss7-200:/opt/certs/ca.pem         cert/
scp hdss7-200:/opt/certs/client.pem     cert/
scp hdss7-200:/opt/certs/client-key.pem cert/
2.2.3 配置子网信息
cat >/opt/flannel/subnet.env <<EOF
FLANNEL_NETWORK=172.7.0.0/16
FLANNEL_SUBNET=172.7.21.1/24
FLANNEL_MTU=1500
FLANNEL_IPMASQ=false
EOF
注意:subnet子网网段信息,每个宿主机都要修改
2.3 启动flannel服务
2.3.1 创建flannel启动脚本
cat >/opt/flannel/flanneld.sh <<'EOF'
#!/bin/sh
./flanneld \
  --public-ip=10.4.7.21 \
  --etcd-endpoints=https://10.4.7.12:2379,https://10.4.7.21:2379,https://10.4.7.22:2379 \
  --etcd-keyfile=./cert/client-key.pem \
  --etcd-certfile=./cert/client.pem \
  --etcd-cafile=./cert/ca.pem \
  --iface=eth0 \
  --subnet-file=./subnet.env \
  --healthz-port=2401
EOF
# 授权
chmod u+x flanneld.sh
注意:
public-ip为节点IP,注意按需修改
iface为网卡,若本机网卡不是eth0,注意修改
2.3.2 创建supervisor启动脚本
cat >/etc/supervisord.d/flannel.ini <<EOF
[program:flanneld]
command=sh /opt/flannel/flanneld.sh
numprocs=1
directory=/opt/flannel
autostart=true
autorestart=true
startsecs=30
startretries=3
exitcodes=0,2
stopsignal=QUIT
stopwaitsecs=10
user=root
redirect_stderr=true
stdout_logfile=/data/logs/flanneld/flanneld.stdout.log
stdout_logfile_maxbytes=64MB
stdout_logfile_backups=4
stdout_capture_maxbytes=1MB
;子进程还有子进程,需要添加这个参数,避免产生孤儿进程
killasgroup=true
stopasgroup=true
EOF
supervisor的各项配置不再备注,有需要的看K8S二进制安装中的备注
2.3.3 启动flannel服务并验证
启动服务
mkdir -p /data/logs/flanneld
supervisorctl update
supervisorctl status
验证路由
[root@hdss7-22 ~]# route -n|egrep -i '172.7|des'
Destination   Gateway     Genmask         Flags Metric Ref   Use Iface
172.7.21.0    10.4.7.21   255.255.255.0   UG    0      0       0 eth0
172.7.22.0    0.0.0.0     255.255.255.0   U     0      0       0 docker0
[root@hdss7-21 ~]# route -n|egrep -i '172.7|des'
Destination   Gateway     Genmask         Flags Metric Ref   Use Iface
172.7.21.0    0.0.0.0     255.255.255.0   U     0      0       0 docker0
172.7.22.0    10.4.7.22   255.255.255.0   UG    0      0       0 eth0
验证通信结果
[root@hdss7-21 ~]# ping 172.7.22.2
PING 172.7.22.2 (172.7.22.2) 56(84) bytes of data.
64 bytes from 172.7.22.2: icmp_seq=1 ttl=63 time=0.538 ms
64 bytes from 172.7.22.2: icmp_seq=2 ttl=63 time=0.896 ms
[root@hdss7-22 ~]# ping 172.7.21.2
PING 172.7.21.2 (172.7.21.2) 56(84) bytes of data.
64 bytes from 172.7.21.2: icmp_seq=1 ttl=63 time=0.805 ms
64 bytes from 172.7.21.2: icmp_seq=2 ttl=63 time=1.14 ms
3 优化iptables规则
3.1 前因后果
3.1.1 优化原因说明
我们使用的是gw网络模型,而这个网络模型只是创建了一条到其他宿主机下POD网络的路由信息.
因而我们可以猜想:
- 从外网访问到B宿主机中的POD,源IP应该是外网IP
 - 从A宿主机访问B宿主机中的POD,源IP应该是A宿主机的IP
 - 从A的POD-A01中,访问B中的POD,源IP应该是POD-A01的容器IP
此情形可以想象是一个路由器下的2个不同网段的交换机下的设备通过路由器(gw)通信 
然后遗憾的是:
- 前两条毫无疑问成立
 - 第3条理应成立,但实际不成立
 
不成立的原因是:
Docker容器的跨网络隔离与通信,借助了iptables的机制
因此虽然K8S我们使用了ipvs调度,但是宿主机上还是有iptalbes规则
而docker默认生成的iptables规则为:
若数据出网前,先判断出网设备是不是本机docker0设备(容器网络)
如果不是的话,则进行SNAT转换后再出网,具体规则如下[root@hdss7-21 ~]# iptables-save |grep -i postrouting|grep docker0
-A POSTROUTING -s 172.7.21.0/24 ! -o docker0 -j MASQUERADE
由于
gw模式产生的数据,是从eth0流出,因而不在此规则过滤范围内就导致此跨宿主机之间的POD通信,使用了该条SNAT规则
解决办法是:
- 修改此IPTABLES规则,增加过滤目标:过滤目的地是宿主机网段的流量
 
3.1.2 问题复现
在
7-21宿主机中,访问172.7.22.2curl 172.7.22.2
在
7-21宿主机启动busybox容器,进入并访问172.7.22.2docker pull busybox
docker run --rm -it busybox bash
/ # wget 172.7.22.2
查看
7-22宿主机上启动的nginx容器日志[root@hdss7-22 ~]# kubectl logs nginx-ds-j777c --tail=2
10.4.7.21 - - [xxx] "GET / HTTP/1.1" 200 612 "-" "curl/7.29.0" "-"
10.4.7.21 - - [xxx] "GET / HTTP/1.1" 200 612 "-" "Wget" "-"
第一条日志为对端宿主机访问日志
第二条日志为对端容器访问日志
可以看出源IP都是宿主机的IP
3.2 具体优化过程
3.2.1 先查看iptables规则
[root@hdss7-21 ~]# iptables-save |grep -i postrouting|grep docker0
-A POSTROUTING -s 172.7.21.0/24 ! -o docker0 -j MASQUERADE
3.2.2 安装iptables并修改规则
yum install iptables-services -y
iptables -t nat -D POSTROUTING -s 172.7.21.0/24 ! -o docker0 -j MASQUERADE
iptables -t nat -I POSTROUTING -s 172.7.21.0/24 ! -d 172.7.0.0/16 ! -o docker0  -j MASQUERADE
# 验证规则并保存配置
[root@hdss7-21 ~]# iptables-save |grep -i postrouting|grep docker0
-A POSTROUTING -s 172.7.21.0/24 ! -d 172.7.0.0/16 ! -o docker0 -j MASQUERADE
[root@hdss7-21 ~]# iptables-save > /etc/sysconfig/iptables
3.2.3 注意docker重启后操作
docker服务重启后,会再次增加该规则,要注意在每次重启docker服务后,删除该规则
验证:
修改后会影响到docker原本的iptables链的规则,所以需要重启docker服务
[root@hdss7-21 ~]# systemctl restart docker
[root@hdss7-21 ~]# iptables-save |grep -i postrouting|grep docker0
-A POSTROUTING -s 172.7.21.0/24 ! -o docker0 -j MASQUERADE
-A POSTROUTING -s 172.7.21.0/24 ! -d 172.7.0.0/16 ! -o docker0 -j MASQUERADE
# 可以用iptables-restore重新应用iptables规则,也可以直接再删
[root@hdss7-21 ~]# iptables-restore /etc/sysconfig/iptables
[root@hdss7-21 ~]# iptables-save |grep -i postrouting|grep docker0
-A POSTROUTING -s 172.7.21.0/24 ! -d 172.7.0.0/16 ! -o docker0 -j MASQUERADE
3.2.4 结果验证
# 对端启动容器并访问
[root@hdss7-21 ~]# docker run --rm -it busybox  sh
/ # wget 172.7.22.2
# 本端验证日志
[root@hdss7-22 ~]# kubectl logs nginx-ds-j777c --tail=1
172.7.21.3 - - [xxxx] "GET / HTTP/1.1" 200 612 "-" "Wget" "-"
												
											K8S(03)核心插件-Flannel网络插件的更多相关文章
- Kubernetes1.91(K8s)安装部署过程(五)--安装flannel网络插件
		
node节点需要安装flannel网络插件才能保证所有的pod在一个局域网内通信,直接使用yum安装即可,版本是0.7.1. 1.安装flannel插件: 注意是2个node节点都需要安装,都需要修改 ...
 - K8S Flannel网络插件
		
0.前言 参考文档:https://github.com/containernetworking/cni Pod网络插件,为了实现Pod网络而需要的插件.组件.由于Kubernetes通过开放的CNI ...
 - 使用kubeadm安装kubernetes/部署前准备/flannel网络插件/镜像下载/
		
本文内容参考<kuberneters进阶实战>/马哥的新书/推荐 部署前的准备 主机名称解析 分布式系统环境中的多主机通信通常基于主机名称进行,这在IP地址存在变化的可能性时为主机提供了固 ...
 - k8s的flannel网络插件配置
		
flannel的网络插件配置 Kubernetes网络通信需要解决以下问题: (1)容器间通信:同一个Pod内的多个容器间的通信,lo (2)Pod通信:P ...
 - Flannel网络插件配置
		
# ps -ef|grep docker|grep bip FLANNEL_OPTIONS="-ip-masq=true" -ip-masq=true 这个参数的目的是让flann ...
 - k8s入坑之路(9)k8s网络插件详解
		
Flannel: 最成熟.最简单的选择 Calico: 性能好.灵活性最强,目前的企业级主流 Canal: 将Flannel提供的网络层与Calico的网络策略功能集成在一起. Weave: 独有的功 ...
 - K8s二进制部署单节点 etcd集群,flannel网络配置   ——锥刺股
		
K8s 二进制部署单节点 master --锥刺股 k8s集群搭建: etcd集群 flannel网络插件 搭建master组件 搭建node组件 1.部署etcd集群 2.Flannel 网络 ...
 - k8s之网络插件flannel及基于Calico的网络策略
		
1.k8s网络通信 a.容器间通信:同一个pod内的多个容器间的通信,通过lo即可实现; b.pod之间的通信:pod ip <---> pod ip,pod和pod之间不经过任何转换即可 ...
 - k8s更换网络插件:从flannel更换成calico
		
卸载flannel 查看已安装的flannel的信息 # 查看CNI插件,可以得知使用的是flannel # cat /etc/cni/net.d/10-flannel.conflist { &quo ...
 
随机推荐
- 【TNS】TNS-00515  TNS-12560  TNS-12545解决方案
			
今天同事的plsql连接不上数据库,我用他的本地tnsping是不通的,于是上服务器上查看下,结果发现监听没起来,不知道怎么就断了 再次尝试重启 lsnrctl start 发现直接报错: NSLSN ...
 - java创建线程安全的类
			
如果一个对象想要被多个线程安全的并发访问,那么这个对象必须是或线程安全的或事实不可变的或由锁来保护的. 1.java监视器模式 大多数对象都是组合对象.当从头开始构建一个类,或者将多个非线程安全的类组 ...
 - CodeMonke少儿编程第1章 step与turn
			
第1章 step与turn 目标 了解游戏舞台的各组成部分 掌握step和turn指令的用法 说起计算机,对于不了解它的人来说,也许会感到有些神秘,其实不然,它不过是能够接收指令并且按照指令执行的一种 ...
 - Py-多态,封装,反射,描述符,包装标准类型,面向对象进阶
			
多态: 对象可以通过他们共同的属性和动作来访问,而不需要考虑他们的类多态是继承的应用 class H2o: def __init__(self,temp): self.temp=temp def ht ...
 - java实现Excel定制导出(基于POI的工具类)
			
我的需求: 项目中有一些工程表格需要导出,设计到行列合并,定制样式,原有工具类冗余,内聚性强.所以想写一个可以随意定制excel的工具类,工具类满足需求: 对于常用的工程表格有模板格式,可以任意插拔. ...
 - 树莓派做私有云盘-极简版(owncloud)
			
这里直接给出配置好私有云的镜像,只需烧录镜像后微改配置后即可使用 链接:https://pan.baidu.com/s/1EOQaSQso-0wmnuWgZKknZg提取码:q26h 1.直接将此镜像 ...
 - BBR implements bbr-like limiter 限流
			
pkg/ratelimit/bbr/bbr.go:68 github.com/go-kratos // BBR implements bbr-like limiter.// It is inspire ...
 - JAVA中关于基本数据和引用数据参数传递过程
			
基本数据和引用数据参数传递过程 案例1:判断程序的输出结果 class Demo{ public static void main(String[] atgs){ int x =4; show(x); ...
 - AutoMapper 10.0使用教程
			
这里有个目录 什么是AutoMapper 配置 使用MapperConfiguration配置 使用Profile Instances配置 Naming Conventions(命名约定) Repla ...
 - 在Ubuntu下安装Jenkins
			
一.安装Jenkins 1. 确保Java环境已经安装配置好 java -version 2. 将存储库密钥添加到系统 wget -q -O - https://pkg.jenkins.io/debi ...