1.K8S 中 Pod 网络通信:
Pod 内容器与容器之间的通信 在同一个 Pod 内的容器(Pod 内的容器是不会跨宿主机的)共享同一个网络命令空间,相当于它们在同一台机器上一样,可以用 localhost 地址访问彼此的端口。
同一个 Node 内 Pod 之间的通信 每个 Pod 都有一个真实的全局 IP 地址,同一个 Node 内的不同 Pod 之间可以直接采用对方 Pod 的 IP 地址进行通信,Pod1 与 Pod2 都是通过 Veth 连接到同一个 docker0 网桥,网段相同,所以它们之间可以直接通信。
不同 Node 上 Pod 之间的通信 Pod 地址与 docker0 在同一网段,docker0 网段与宿主机网卡是两个不同的网段,且不同 Node 之间的通信只能通过宿主机的物理网卡进行。 要想实现不同 Node 上 Pod 之间的通信,就必须想办法通过主机的物理网卡 IP 地址进行寻址和通信。因此要满足两个条件:Pod 的 IP 不能冲突;将 Pod 的 IP 和所在的 Node 的 IP 关联起来,通过这个关联让不同 Node 上 Pod 之间直接通过内网 IP 地址通信。
Overlay Network:
叠加网络,在二层或者三层基础网络上叠加的一种虚拟网络技术模式,该网络中的主机通过虚拟链路隧道连接起来(类似于VPN)。
VXLAN:
vxlan 是一种overlay(虚拟隧道通信)技术,通过三层网络搭建虚拟的二层网络,跟 udp 模式具体实现不太一样:
- udp模式是在用户态实现的,数据会先经过tun网卡,到应用程序,应用程序再做隧道封装,再进一次内核协议栈,而vxlan是在内核当中实现的,只经过一次协议栈,在协议栈内就把vxlan包组装好
- udp模式的tun网卡是三层转发,使用tun是在物理网络之上构建三层网络,属于ip in udp,vxlan模式是二层实现, overlay是二层帧,属于mac in udp
- vxlan由于采用mac in udp的方式,所以实现起来会涉及mac地址学习,arp广播等二层知识,udp模式主要关注路由
将源数据包封装到UDP中,并使用基础网络的IP/MAC作为外层报文头进行封装,然后在以太网上传输,到达目的地后由隧道端点解封装并将数据发送给目标地址。
2.Flannel
2.1 Flannel的功能
Flannel 的功能是让集群中的不同节点主机创建的 Docker 容器都具有全集群唯一的虚拟 IP 地址。 Flannel 是 Overlay 网络的一种,也是将 TCP 源数据包封装在另一种网络包里面进行路由转发和通信,目前支持 udp、vxlan、 host-GW 3种数据转发方式。
2.2 Flannel udp 模式的工作原理
数据从 node01 上 Pod 的源容器中发出后,经由所在主机的 docker0 虚拟网卡转发到 flannel.1 虚拟网卡,flanneld 服务监听在 flannel.1 虚拟网卡的另外一端。 Flannel 通过 Etcd 服务维护了一张节点间的路由表。源主机 node01 的 flanneld 服务将原本的数据内容封装到 UDP 中后根据自己的路由表通过物理网卡投递给目的节点 node02 的 flanneld 服务,数据到达以后被解包,然后直接进入目的节点的 flannel.1 虚拟网卡,之后被转发到目的主机的 docker0 虚拟网卡,最后就像本机容器通信一样由 docker0 转发到目标容器。
由于 udp 模式是在用户态做转发,会多一次报文隧道封装,因此性能上会比在内核态做转发的 vxlan 模式差。
存储管理Flannel可分配的IP地址段资源 监控 ETCD 中每个 Pod 的实际地址,并在内存中建立维护 Pod 节点路由表
2.3 Flannel vxlan 模式的工作原理
vxlan在内核当中实现,当数据包使用vxlan设备发送数据时,会打上vlxan的头部信息,在发送出去,对端解包,flannel.1网卡把原始报文发送到目的服务器。
2.4.部署Flannel
1.在node01节点上操作,上传 cni-plugins-linux-amd64-v0.8.6.tgz 和 flannel.tar 到 /opt 目录中
bash
cd /opt/
docker load -i flannel.tar
docker load -i flannel-cni-plugin.tar
2.创建工作目录并解压cni安装包到指定位置
bash
mkdir /opt/cni/bin
tar zxvf cni-plugins-linux-amd64-v0.8.6.tgz -C /opt/cni/bin
3.将我们的脚本文件和cni文件传送给我们的node02文件
bash
scp *.tar node02:`pwd`
bash
cd /opt
scp -r cni/ node02:/opt
4.在node02节点上操作上传我们的flannel镜像
bash
cd /opt/k8s/
for i in `ls *.tar`
> do
> docker load -i $i
> done
5.在 master01 节点上操作,上传 kube-flannel.yml 文件到 /opt/k8s 目录中,部署 CNI 网络
bash
cd /opt/k8s
kubectl apply -f kube-flannel.yml
4.查看cni网络状态是否配置好了
arduino
kubectl get pods -n A
kubectl get nodes
5.在master01上创建一些pods进行测试
sql
kubectl create deployment lzq-11 --image=nginx:latest --port=80 --replicas=3
kubectl get pods -o wide
6.去到这些pods上所对应的node节点
bash
docker exec -it ce2f1a8aafb8 bash
7.安装ping软件进行测试,进行ping测试
sql
apt-get update
apt-get install -y inetutils-ping
ping 10.244.0.5
3.Calico k8s网络插件
3.1 calico方案
Calico不使用隧道或NAT来实现转发,而是把Host当作Internet中的路由器,使用BGP同步路由,并使用iptables来做安全访问策略,完成跨Host转发来。
3.2 calico的组成
- Calico CNI插件:主要负责与kubernetes对接,供kubelet调用使用。
- Felix:负责维护宿主机上的路由规则、FIB转发信息库等。
- BIRD:负责分发路由规则,类似路由器。
- Confd:配置管理组件。
3.3 Calico 工作原理
Calico 是通过路由表来维护每个 pod 的通信。Calico 的 CNI 插件会为每个容器设置一个 veth pair 设备, 然后把另一端接入到宿主机网络空间,由于没有网桥,CNI 插件还需要在宿主机上为每个容器的 veth pair 设备配置一条路由规则,用于接收传入的IP包。 有了这样的 veth pair 设备以后,容器发出的IP包就会通过 veth pair 设备到达宿主机,然后宿主机根据路由规则的下一跳地址, 发送给正确的网关,然后到达目标宿主机,再到达目标容器。 这些路由规则都是 Felix 维护配置的,而路由信息则是 Calico BIRD 组件基于 BGP 分发而来。calico 实际上是将集群里所有的节点都当做边界路由器来处理,他们一起组成了一个全互联的网络,彼此之间通过 BGP 交换路由,这些节点我们叫做 BGP Peer。
3.4 flannel与calico之间的对比
目前比较常用的时flannel和calico,flannel的功能比较简单,不具备复杂的网络策略配置能力, calico是比较出色的网络管理插件,但具备复杂网络配置能力的同时,往往意味着本身的配置比较复杂, 所以相对而言,比较小而简单的集群使用flannel,考虑到日后扩容,未来网络可能需要加入更多设备,配置更多网络策略, 则使用calico更好。
3.5 部署calico
1.在 master01 节点上操作,上传 calico.yaml 文件到 /opt/k8s 目录中,部署 CNI 网络
bash
cd /opt/k8s
vim calico.yaml
#修改里面定义Pod网络(CALICO_IPV4POOL_CIDR),与前面kube-controller-manager配置文件指定的cluster-cidr网段一样
2.安装calico
bash
cd /opt/k8s
kubectl apply -f calico.yaml
3.使用命令来验证是否生效
arduino
kubectl get pods -n -A
kubectl get nodes
4.部署 CoreDNS
1.在所有node节点上操作,上传 coredns.tar 到 /opt 目录中
bash
cd /opt/k8s
docker load -i coredns.tar
2.在 master01 节点上操作,上传 coredns.yaml 文件到 /opt/k8s 目录中,部署 CoreDNS
bash
cd /opt/k8s
kubectl apply -f coredns.yaml
3.使用命令检查
sql
kubectl get pods -n kube-system
4.我们创建一个域名
css
kubectl expose deployment myapp-ky31 --port=80 --target-port=80
kubectl get svc
5.进入到我们其中一个pod容器
perl
kubectl exec -it dns-test sh
#拒绝登录时用这个命令添加权限
kubectl create clusterrolebinding cluster-system-anonymous --clusterrole=cluster-admin --user=system:anonymous
nslookup kubernetes
nslookup myapp-ky31