目录
1 上传 cni-plugins-linux-amd64-v0.8.6.tgz 和 flannel.tar 到 /opt 目录中
一 部署 CNI 网络组件
部署 flannel
1 K8S 中 Pod 网络通信:
① Pod 内容器与容器之间的通信
在同一个 Pod 内的容器(Pod 内的容器是不会跨宿主机的)共享同一个网络命名空间,相当于它
们在同一台机器上一样,可以用 localhost 地址访问彼此的端口。
② 同一个 Node 内 Pod 之间的通信
每个 Pod 都有一个真实的全局 IP 地址,同一个 Node 内的不同 Pod 之间可以直接采用对方 Pod
的 IP 地址进行通信,Pod1 与 Pod2 都是通过 Veth 连接到同一个 docker0/cni0 网桥,网段相同,
所以它们之间可以直接通信。
③ 不同 Node 上 Pod 之间的通信
Pod 地址与 docker0 在同一网段,docker0 网段与宿主机网卡是两个不同的网段,且不同 Node 之
间的通信只能通过宿主机的物理网卡进行。
要想实现不同 Node 上 Pod 之间的通信,就必须想办法通过主机的物理网卡 IP 地址进行寻址和通
信。
因此要满足两个条件:Pod 的 IP 不能冲突;将 Pod 的 IP 和所在的 Node 的 IP 关联起来,通
过这个关联让不同 Node 上 Pod 之间直接通过内网 IP 地址通信。
关于k8s的三种类型的网络IP
节点网络:nodeIP---node节点的物理网卡ip,实现node节点之间的通信
Pod网络:PodIP---Pod与Pod之间通过PodIP进行通信(虚拟ip)
service网络:clusterIP---k8s集群内部,service资源的clusterIP实现对Pod集群的网络代理(虚拟ip、service网络四层)
-----------------------------------------------------------------------------------
Pod IP:
Pod IP是Kubernetes中Pod的IP地址。
每个Pod都有一个独立的IP地址,这个地址是由Docker Engine根据docker0网络的IP段进行分配的,通常是一个虚拟的二层网络地址。
Pod IP是虚拟IP地址,用于Pod之间的通信。在默认情况下,Kubernetes集群内不同节点上的Pod是不能直接通信的,需要通过集群网络进行管理和配置,以确保Pod之间可以互相通信。
Service IP(Server IP)
Service IP是Kubernetes中Service的IP地址。
Service是对一组具有相同功能的Pods的抽象,它提供负载均衡以及服务发现的能力。
Service IP是虚拟IP地址,用于集群内部访问Service。
当外部网络请求访问某个Service时,请求会首先到达Node节点网络,然后转发到Service网络,最后由Service代理给对应的Pod网络。
节点IP(Node IP)
节点IP是Kubernetes集群中每个节点(服务器)的物理网卡的IP地址。
这是一个真实存在的物理网络地址(也可能是虚拟机网络地址),用于节点之间的通信以及Kubernetes集群与外部网络的通信。
节点IP可以是内部IP和外部IP。内部IP用于集群节点之间的互相访问,而外部IP则提供了从外部网络访问Kubernetes集群的功能。
2 Overlay Network:
叠加网络,在二层或者三层基础网络上叠加的一种虚拟网络技术模式,该网络中的主机通过虚拟链
路隧道连接起来。
通过Overlay技术(可以理解成隧道技术),在原始报文外再包一层四层协议(UDP协议),通过
主机网络进行路由转发。这种方式性能有一定损耗,主要体现在对原始报文的修改。目前Overlay
主要采用VXLAN。
VXLAN:
将源数据包封装到UDP中,并使用基础网络的IP/MAC作为外层报文头进行封装,然后在以太网上
传输,到达目的地后由隧道端点解封装并将数据发送给目标地址。
Flannel:
Flannel 的功能是让集群中的不同节点主机创建的 Docker 容器都具有全集群唯一的虚拟 IP 地址。
Flannel 是 Overlay 网络的一种,也是将 TCP 源数据包封装在另一种网络包里面进行路由转发和通
信,目前支持 UDP、VXLAN、Host-gw 3种数据转发方式。
① Flannel UDP 模式的工作原理:
数据从主机 A 上 Pod 的源容器中发出后,经由所在主机的 docker0/cni0 网络接口转发到 flannel0
接口,flanneld 服务监听在 flannel0 虚拟网卡的另外一端。
Flannel 通过 Etcd 服务维护了一张节点间的路由表。源主机 A 的 flanneld 服务将原本的数据内容
封装到 UDP 报文中, 根据自己的路由表通过物理网卡投递给目的节点主机 B 的 flanneld 服务,
数据到达以后被解包,然后直接进入目的节点的 flannel0 接口, 之后被转发到目的主机的
docker0/cni0 网桥,最后就像本机容器通信一样由 docker0/cni0 转发到目标容器。
ETCD 之 Flannel 提供说明:
存储管理Flannel可分配的IP地址段资源
监控 ETCD 中每个 Pod 的实际地址,并在内存中建立维护 Pod 节点路由表
由于 UDP 模式是在用户态做转发,会多一次报文隧道封装,因此性能上会比在内核态做转发的
VXLAN 模式差。
②VXLAN 模式:
VXLAN 模式使用比较简单,flannel 会在各节点生成一个 flannel.1 的 VXLAN 网卡(VTEP设备,
负责 VXLAN 封装和解封装)。
VXLAN 模式下作是由内核进行的。flannel 不转发数据,仅动态设置 ARP 表和 MAC 表项。
UDP 模式的 flannel0 网卡是三层转发,使用 flannel0 时在物理网络之上构建三层网络,属于 ip in
udp ;VXLAN封包与解包的工 模式是二层实现,overlay 是数据帧,属于 mac in udp 。
③ host-gw:
二层网络服务 不支持云环境 通过主机路由表 直接创建路由信息(subnet路由条目)
到达目标 性能好 配置麻烦
Flannel VXLAN 模式跨主机的工作原理:
1、数据帧从主机 A 上 Pod 的源容器中发出后,经由所在主机的 docker0/cni0 网络接口转发到
flannel.1 接口
2、flannel.1 收到数据帧后添加 VXLAN 头部,封装在 UDP 报文中
3、主机 A 通过物理网卡发送封包到主机 B 的物理网卡中
4、主机 B 的物理网卡再通过 VXLAN 默认端口 4789 转发到 flannel.1 接口进行解封装
5、解封装以后,内核将数据帧发送到 cni0,最后由 cni0 发送到桥接到此接口的容器 B 中。
二 部署flannel网络插件
在 node01 节点上操作
1 上传 cni-plugins-linux-amd64-v0.8.6.tgz 和 flannel.tar 到 /opt 目录中
上传 cni-plugins-linux-amd64-v0.8.6.tgz 和 flannel.tar 到 /opt 目录中
cd /opt/
docker load -i flannel.tar
mkdir /opt/cni/bin
tar zxvf cni-plugins-linux-amd64-v0.8.6.tgz -C /opt/cni/bin
docker images
2 同时也在node02上操作
cd /opt
上传包cni-plugins-linux-amd64-v0.8.6.tgz 和 flannel.tar的包
docker load -i flannel.tar 载入镜像
mkdir /opt/cni/bin -p
tar xf cni-plugins-linux-amd64-v0.8.6.tgz -C /opt/cni/bin/
上传 cni-plugins-linux-amd64-v0.8.6.tgz 和 flannel.tar 到 /opt 目录中
3 在 master01 节点上操作
在 master01 节点上操作
#上传 kube-flannel.yml 文件到 /opt/k8s 目录中,部署 CNI 网络
cd /opt/k8s
kubectl apply -f kube-flannel.yml
#加载上传的flannel的yml文件部署CNI 网络
kubectl get pods -n kube-system #获取kube-system 命名空间所有pod的状态信息
NAME READY STATUS RESTARTS AGE
kube-flannel-ds-hjtc7 1/1 Running 0 7s
kubectl get nodes
NAME STATUS ROLES AGE VERSION
192.168.10.18 Ready <none> 81m v1.20.11
此实验没有做通:
四 部署 Calico
k8s 组网方案对比:
1 flannel方案
需要在每个节点上把发向容器的数据包进行封装后,再用隧道将封装后的数据包发送到运行着目标
Pod的node节点上。目标node节点再负责去掉封装,将去除封装的数据包发送到目标Pod上。数据
通信性能则大受影响。
2 calico方案
Calico不使用隧道或NAT来实现转发,而是把Host当作Internet中的路由器,使用BGP同步路由,
并使用iptables来做安全访问策略,完成跨Host转发。
采用直接路由的方式,这种方式性能损耗最低,不需要修改报文数据,但是如果网络比较复杂场景
下,路由表会很复杂,对运维同事提出了较高的要求。
Calico 主要由三个部分组成:
Calico CNI插件:主要负责与kubernetes对接,供kubelet调用使用。
Felix:负责维护宿主机上的路由规则、FIB转发信息库等。
BIRD:负责分发路由规则,类似路由器。
Confd:配置管理组件。
Calico 工作原理:
Calico 是通过路由表来维护每个 pod 的通信。Calico 的 CNI 插件会为每个容器设置一个 veth pair
设备, 然后把另一端接入到宿主机网络空间,由于没有网桥,CNI 插件还需要在宿主机上为每个
容器的 veth pair 设备配置一条路由规则, 用于接收传入的 IP 包。
有了这样的 veth pair 设备以后,容器发出的 IP 包就会通过 veth pair 设备到达宿主机,然后宿主
机根据路由规则的下一跳地址, 发送给正确的网关,然后到达目标宿主机,再到达目标容器。
这些路由规则都是 Felix 维护配置的,而路由信息则是 Calico BIRD 组件基于 BGP 分发而来。
calico 实际上是将集群里所有的节点都当做边界路由器来处理,他们一起组成了一个全互联的网
络,彼此之间通过 BGP 交换路由, 这些节点我们叫做 BGP Peer。
目前比较常用的CNI网络组件是flannel和calico,flannel的功能比较简单,不具备复杂的网络策略
配置能力,calico是比较出色的网络管理插件,但具备复杂网络配置能力的同时,往往意味着本身
的配置比较复杂,所以相对而言,比较小而简单的集群使用flannel,考虑到日后扩容,未来网络可
能需要加入更多设备,配置更多网络策略,则使用calico更好。
calico工作原理 2
IP地址管理:Calico会为每个节点分配一个唯一的IP地址段,并使用BGP(边界网关协议)来分发路由表。这样,容器之间就可以通过IP地址相互通信,而不会与其他节点或集群发生冲突。
网络隔离:Calico提供基于iptables规则和Linux内核功能的网络隔离能力。通过这种隔离,容器可以被放置在不同的虚拟网络中,从而防止不同租户或服务之间的干扰和攻击。
BGP路由协议:Calico使用BGP协议来管理网络路由。当新的节点或容器被添加到集群中时,BGP协议可以自动发现这些变化,并动态调整路由表。这使得Calico能够快速适应网络变化,并实现高效的流量转发和负载均衡。
纯三层方法:Calico不使用重叠网络(如Flannel和libnetwork重叠网络驱动),而是采用纯三层的方法。它使用虚拟路由代替虚拟交换,每台虚拟路由都通过BGP协议传播可达信息(路由)到整个数据中心。这确保了所有工作负载之间的数据流量都是通过IP包的方式完成互联的。
Calico 是通过路由表来维护每个 pod 的通信。Calico 的 CNI 插件会为每个容器设置一个 veth pair 设备, 然后把另一端接入到宿主机网络空间,由于没有网桥,CNI 插件还需要在宿主机上为每个容器的 veth pair 设备配置一条路由规则, 用于接收传入的 IP 包。
有了这样的 veth pair 设备以后,容器发出的 IP 包就会通过 veth pair 设备到达宿主机,然后宿主机根据路由规则的下一跳地址, 发送给正确的网关,然后到达目标宿主机,再到达目标容器。
五 部署calico
1 在 master01 节点上操作
在 master01 节点上操作
#上传 calico.yaml 文件到 /opt/k8s 目录中,部署 CNI 网络
cd /opt/k8s
vim calico.yaml
#修改里面定义 Pod 的网络(CALICO_IPV4POOL_CIDR),需与前面 kube-controller-manager 配置文件指定的 cluster-cidr 网段一样
- name: CALICO_IPV4POOL_CIDR
value: "10.244.0.0/16" #Calico 默认使用的网段为 192.168.0.0/16
kubectl apply -f calico.yaml
kubectl get pods -n kube-system
NAME READY STATUS RESTARTS AGE
calico-kube-controllers-659bd7879c-4h8vk 1/1 Running 0 58s
calico-node-nsm6b 1/1 Running 0 58s
calico-node-tdt8v 1/1 Running 0 58s
#等 Calico Pod 都 Running,节点也会准备就绪
kubectl get nodes
输入 / 进行查找
注意:状态可能不是running 分析其状态 大约需要3分钟,找其原因
因为只做了一个node 所以running有一个没有运行
2 node02 节点部署
2.1 在 node01 节点上操作
cd /opt/
scp kubelet.sh proxy.sh root@192.168.11.14:/opt/
scp -r /opt/cni root@192.168.11.14:/opt/
2.2 在 node02 节点上操作
在 node02 节点上操作
#启动kubelet服务
cd /opt/
chmod +x kubelet.sh
./kubelet.sh 192.168.11.14
2.3 在 master01 节点上操作
在 master01 节点上操作
kubectl get csr
NAME AGE SIGNERNAME REQUESTOR CONDITION
node-csr-BbqEh6LvhD4R6YdDUeEPthkb6T_CJDcpVsmdvnh81y0 10s kubernetes.io/kube-apiserver-client-kubelet kubelet-bootstrap Pending
node-csr-duiobEzQ0R93HsULoS9NT9JaQylMmid_nBF3Ei3NtFE 85m kubernetes.io/kube-apiserver-client-kubelet kubelet-bootstrap Approved,Issued
#通过 CSR 请求
kubectl certificate approve node-csr-BbqEh6LvhD4R6YdDUeEPthkb6T_CJDcpVsmdvnh81y0
kubectl get csr
NAME AGE SIGNERNAME REQUESTOR CONDITION
node-csr-BbqEh6LvhD4R6YdDUeEPthkb6T_CJDcpVsmdvnh81y0 23s kubernetes.io/kube-apiserver-client-kubelet kubelet-bootstrap Approved,Issued
node-csr-duiobEzQ0R93HsULoS9NT9JaQylMmid_nBF3Ei3NtFE 85m kubernetes.io/kube-apiserver-client-kubelet kubelet-bootstrap Approved,Issued
加载 ipvs 模块
for i in $(ls /usr/lib/modules/$(uname -r)/kernel/net/netfilter/ipvs|grep -o "^[^.]*");do echo $i; /sbin/modinfo -F filename $i >/dev/null 2>&1 && /sbin/modprobe $i;done
#使用proxy.sh脚本启动proxy服务
cd /opt/
chmod +x proxy.sh
./proxy.sh 192.168.11.14
#查看群集中的节点状态
kubectl get nodes
六 对比flannel和calico的区别
6.1从模式来讲
flannel插件的模式有:udp、vxlan、host-gw
calico插件的模式有:IPIP、BGP、CrossSubnet(混合模式)
6.2从默认网段来讲
flannel默认的网段是10.244.0.0/16
calico默认的网段是192.168.0.0/16
6.3从模式的性能来讲
flannel
通常会采用VXLAN模式,用的是叠加网络、IP隧道方式传输数据,对性能有一定的影响
Flannel产品成熟,依赖性较少,易于安装,功能简单,配置方便,利于管理。但是不具备复杂的
网络策略配置能力。
calico
使用IPIP模式可以实现跨子网传输,但是传输过程中需要额外的封包和解包过程,对性能有一定的影响。
使用BGP模式会把每个node节点看作成路由器,通过Felix、BIRD组件来维护和分发路由规则,可实现直接通过BGP路由协议实现路由转发,传输过程中不需要额外封包和解包过程,因此性能较好,但是只能在同一个网段里使用,无法跨子网传输。
calico不使用cni0网桥,而使通过路由规则把数据包直接发送到目标主机,所以性能较高;而且还具有更丰富的网络策略配置管理能力,功能更全面,但是维护起来较为复杂。
从使用场景来讲
- 对于较小规模且网络要求简单的K8S集群,可以采用flannel作为cni网络插件;
- 对于K8S集群规模较大且要求更多的网络策略配置时,可以考虑采用性能更好功能更全面的calico或cilium。
七 部署 CoreDNS
CoreDNS:可以为集群中的 service 资源创建一个域名 与 IP 的对应关系解析
部署好etcd、master、node节点之后,才可以使用flannel网络插件接着部署,具体使用哪种(flannel、或者calico)网络插件,根据具体情况考虑
1 在所有 node 节点上操作
在所有 node 节点上操作
#上传 coredns.tar 到 /opt 目录中
cd /opt
docker load -i coredns.tar
2 在 master01 节点上操作
在 master01 节点上操作
#上传 coredns.yaml 文件到 /opt/k8s 目录中,部署 CoreDNS
cd /opt/k8s
kubectl apply -f coredns.yaml
kubectl get pods -n kube-system
NAME READY STATUS RESTARTS AGE
coredns-5ffbfd976d-j6shb 1/1 Running 0 32s
3 DNS 解析测试
DNS 解析测试
kubectl run -it --rm dns-test --image=busybox:1.28.4 sh
If you don't see a command prompt, try pressing enter.
/ # nslookup kubernetes
Server: 10.0.0.2
Address 1: 10.0.0.2 kube-dns.kube-system.svc.cluster.local
Name: kubernetes
Address 1: 10.0.0.1 kubernetes.default.svc.cluster.local
注意:
注:
如果出现以下报错
[root@master01 k8s]# kubectl run -it --image=busybox:1.28.4 sh
If you don't see a command prompt, try pressing enter.
Error attaching, falling back to logs: unable to upgrade connection: Forbidden (user=system:anonymous, verb=create, resource=nodes, subresource=proxy)
Error from server (Forbidden): Forbidden (user=system:anonymous, verb=get, resource=nodes, subresource=proxy) ( pods/log sh)
需要添加 rbac的权限 直接使用kubectl绑定 clusteradmin 管理员集群角色 授权操作权限
[root@master01 k8s]# kubectl create clusterrolebinding cluster-system-anonymous --clusterrole=cluster-admin --user=system:anonymous
clusterrolebinding.rbac.authorization.k8s.io/cluster-system-anonymous created
总结——CNI网络插件
1.Flannel
通常会采用VXLAN模式,用的是叠加网络(二层和三层网络)、IP隧道方式传输数据,由于要进行封装和解封装,对性能有一定的影响。
Flannel产品成熟,依赖性较少,易于安装,功能简单,配置方便,利于管理。但是不具备复杂的网络策略配置能力。同时不具备策略的配置能力。
3种模式(UDP、VXLAN、Host-gw)
VXLAN隧道模式,默认配置,利用内核VXLAN来封装主机(host)之间传送数据包
UDP用户态,就是应用程序封装,通过UDP协议,IP封装,解封装的过程,原理通过FLannel服务进行封装,将UDP封装进去。由于 UDP 模式是在用户态做转发,会多一次报文隧道封装,因此性能上会比在内核态做转发的 VXLAN 模式差。
Host-gw:二层网络配置,不支持云环境,通过在主机的路由表中直接创建路由信息(subnet路由条目),到达目标,性能好,配置麻烦
注:其中只配置一种,根据你的需求来配(或者自己判断)
默认网段10.244.0.0/16
2.Calico
功能强大,没有封装和解封装的过程,对性能影响较小,具有网络策略的配置能力,但是路由表维护起来比较复杂。
使用IPIP模式可以实现跨子网传输,但是传输过程中需要额外的封包和解包过程,对性能有一定的影响。
使用BGP模式会把每个node节点看作成路由器,通过Felix、BIRD组件来维护和分发路由规则,可实现直接通过BGP路由协议实现路由转发,传输过程中不需要额外封包和解包过程,因此性能较好,但是只能在同一个网段里使用,无法跨子网传输。
Calico不使用CNI0网桥,而使通过路由规则把数据包直接发送到目标主机,所以性能较高;而且还具有更丰富的网络策略配置管理能力,功能更全面,但是维护起来较为复杂。
默认网段192.168.0.0/16
模式:网络BGP、IPIP(封装的模式)、混合模式(CrossSubnet)
BGP:跨网络网关的动态路由协议,实现路由的最佳状态到达对端
2.1Calico的IPIP模式工作原理
原始数据包从源主机的Pod容器发出,通过 veth pair 设备送达到tunl0接口,再被内核的IPIP驱动封装到node节点网络的IP报文
根据Felix维护的路由规则通过物理网卡发送到目标node节点
IP数据包到达目标node节点的tunl0接口后再通过内核的IPIP驱动解封装得到原始数据包,再根据本地路由规则通过 veth pair 设备送达到目标Pod容器
2.2Calico的BGP模式工作原理
每个Pod容器都有一个 veth pair 设备,一端接入容器,另一个接入宿主机网络空间,并设置一条路由规则。这些路由规则都是 Felix 维护配置的,由 BIRD 组件基于 BGP 动态路由协议分发路由信息给其它节点。
原始数据包从源主机的Pod容器发出,通过 veth pair 设备送达到宿主机网络空间
根据Felix维护的路由规则通过物理网卡发送到目标node节点
目标node节点接收到数据包后,会根据本地路由规则通过 veth pair 设备送达到目标Pod容器
所以对于较小规模且网络要求简单的K8S集群,可以采用Flannel作为CNI网络插件。
对于K8S集群规模较大且要求更多的网络策略配置时,可以考虑采用性能更好更全面的Calico或Cilium
二进制安装K8s
etcd 安装步骤:
1.准备 CA 证书和私钥文件 ,首先 CA 签发服务端证书和私有文件
2.使用 CA 证书、服务端证书 、私有文件加上 etcd 集群配置文件去启动 etcd 服务
3.复制 etcd 工作目录和管理文件到另外几个节点上(node01 node02),修改 etcd 集群配置文件并且启动 etcd 服务
4.使用 v3 版本的接口去执行 etcdctl + 证书选项(endpoint healh)| endpoint status | member list 査看 etcd 集群和节点的状态
master 组件安装:
1.先安装 apiserver
(1)准备组件相关的证书和私钥文件
(2)准备 bootstrap token 认证文件,给 kubelet 启动时签发证书使用
(3)准备组件启动配置文件
(4)启动 apiserver 服务,端口是 6443 https
2.再启动 controller-manager 和 scheduler
(1)准备启动配置文件
(2)准备相关证书和私钥文件生成 kubeconfig 文件(用于指定对接哪个 apiserver,使用什么证书认证)启动服务
3.检查集群组件状态
需要准备 kubeconfig 文件把 kubectl 加入到集群中(指定对接哪个apiserver,使用什么证书认证)
kubectl get cs
node组件安装:
1.生成kubelet初次加入集群引导kubeconfig文件和kube-proxy.kubeconfig文件
2.把 kubelet、kube-proxy、bootstrap.kubeconfig kube-proxy.kubeconfig 拷贝到 node 节点
3.RBAC授权,使用户 kubelet-bootstrap 能够有权限发起 CSR 请求证书
4.在 node 节点启动 kubelet 服务
5.在 master 节点通过 CSR 请求并签发证书
6.在 master 节点使用命令 kubectl get node 获取集群中所有节点(Node)的信息
7.在 node 节点加载 ip_vs 模块,启动proxy服务