二进制部署k8s之网络部分

1 CNI 网络组件

1.1 K8S的三种接口

CRI 容器运行时接口 docker containerd podman cri-o
CNI 容器网络接口 flannel calico cilium
CSI 容器存储接口 nfs ceph gfs oss s3 minio

1.2 K8S的三种网络

节点网络 nodeIP 物理网卡的IP实现节点间的通信
Pod网络 podIP Pod与Pod之间可通过Pod的IP相互通信
Service网络 clusterIP 在K8S集群内可通过service资源的clusterIP实现对Pod集群的网络代理转发
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 地址通信。

1.3 Flannel

Flannel 的功能是让集群中的不同节点主机创建的 Docker 容器都具有全集群唯一的虚拟 IP 地址。 Flannel 是 Overlay 网络的一种,也是将 TCP 源数据包封装在另一种网络包里面进行路由转发和通信,目前支持 udp、vxlan、 host-GW 3种数据转发方式。

flannel的三种模式
模式类型 说明
UDP 出现最早的模式,但是性能最差,基于flanneld应用程序实现数据包的封装/解封装
VXLAN flannel的默认模式,也是推荐使用的模式,性能比UDP模式更好,基于内核实现数据帧的封装/解封装,而且配置简单使用方便
HOST-GW 性能最好的模式,但是配置负载,且不能跨网段
flannel的UDP模式工作原理

1)原始数据包从源主机的Pod容器发出到cni0网桥接口,再由cni0转发到flannel0虚拟接口 2)flanneld服务进程会监听flannel0接口接收到的数据,flanneld进程会将原始数据包封装到UDP报文里 3)flanneld进程会根据在etcd中维护的路由表查到目标Pod所在的nodeIP,并在UDP报文外封装nodeIP头部、MAC头部,再通过物理网卡发送到目标node节点 4)UDP报文通过8285端口送达到目标node节点的flanneld进程进行解封装,再根据本地路由规则通过flannel0接口发送到cni0网桥,再由cni0发送到目标Pod容器

ETCD 之 Flannel 提供说明

存储管理Flannel可分配的IP地址段资源 监控 ETCD 中每个 Pod 的实际地址,并在内存中建立维护 Pod 节点路由表

VXLAN

将源数据包封装到UDP中,并使用基础网络的IP/MAC作为外层报文头进行封装,然后在以太网上传输,到达目的地后由隧道端点解封装并将数据发送给目标地址。

flannel的VXLAN模式工作原理

1)原始数据帧从源主机的Pod容器发出到cni0网桥接口,再由cni0转发到flannel.1虚拟接口 2)flannel.1接口接收到数据帧后添加VXLAN头部,并在内核将原始数据帧封装到UDP报文里 3)根据在etcd中维护的路由表查到目标Pod所在的nodeIP,并在UDP报文外封装nodeIP头部、MAC头部,再通过物理网卡发送到目标node节点 4)UDP报文通过8472端口送达到目标node节点的flannel.1接口并在内核进行解封装,再根据本地路由规则发送到cni0网桥,再由cni0发送到目标Pod容器

VLAN 和 VXLAN 的区别

1)作用不同:VLAN主要用作于在交换机上逻辑划分广播域,还可以配合STP生成树协议阻塞路径接口,避免产生环路和广播风暴,VXLAN可以将数据帧封装成UDP报文,再通过网络层传输给其它网络,从而实现虚拟大二层网络的通信 2)VXLAN支持更多的二层网络:VXLAN最多可支持 2^24 个;VLAN最多支持 2^12 个(4096-2) 3)VXLAN可以防止物理交换机MAC表耗尽:VLAN需要在交换机的MAC表中记录MAC物理地址;VXLAN采用隧道机制,MAC物理地址不需记录在交换机

Overlay Network

叠加网络,在二层或者三层基础网络上叠加的一种虚拟网络技术模式,该网络中的主机通过虚拟链路隧道连接起来(类似于VPN)。

1.4 flannel部署

在 node01、node02 节点上操作
复制代码
上传 cni-plugins-linux-amd64-v0.8.6.tgz 和 flannel.tar 到 /opt 目录中
cd /opt/ 
mkdir /opt/cni/bin -p
docker load -i flannel-cni-plugin.tar     #导入镜像
docker load -i flannel.tar                #导入镜像
tar zxvf cni-plugins-linux-amd64-v1.3.0.tgz -C /opt/cni/bin   #解压cni的压缩包到cni插件的工作目录
在 master01 节点上操作
复制代码
cd /opt/k8s
kubectl apply -f kube-flannel.yml    #启动flannel插件
​
kubectl get pods -n kube-flannel     #进入kube-flannel网络命名空间
NAME                    READY   STATUS    RESTARTS   AGE
kube-flannel-ds-hjtc7   1/1     Running   0          7s
​
kubectl get nodes                    #查看node状态
NAME            STATUS   ROLES    AGE   VERSION
192.168.111.11   Ready    <none>   81m   v1.20.11
重启服务器查看node01、node02是否分配网卡
复制代码
systemctl restart network
ip -d addr show flannel.1
8: flannel.1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1450 qdisc noqueue state UNKNOWN 
    link/ether 22:37:61:bb:a1:64 brd ff:ff:ff:ff:ff:ff promiscuity 0 
    vxlan id 1 local 192.168.111.22 dev ens33 srcport 0 0 dstport 8472 nolearning ageing 300 
    inet 10.244.0.0/32 scope global flannel.1
       valid_lft forever preferred_lft forever
node01和node02都分配了一个flannel.1的虚拟网卡,网段是10.244.0.0/16分配的目标端口是8472(对应的flannel的vxlan模式)
网络插件的目的是为了解决跨node节点的pod进行通信,那么进行验证
在master01节点创建pod资源
复制代码
kubectl create deployment test-v1 --image=soscscs/myapp:v1  --replicas=2   #创建pod
deployment.apps/test-v1 created
kubectl get pods -o wide
NAME                       READY   STATUS    RESTARTS   AGE   IP           NODE     NOMINATED NODE   READINESS GATES
test-v1-56f56b4db5-82hf6   1/1     Running   0          22s   10.244.0.2   node02   <none>           <none>
test-v1-56f56b4db5-zrcgv   1/1     Running   0          22s   10.244.1.2   node01   <none>           <non
在node节点查看容器情况
复制代码
docker ps -a
进入容器中,查看是否可以完成跨主机的pod通信
复制代码
docker exec -it 9c16ee2809b1 sh

注意:有几个文件中的网段设置需要一致

kube-flannel.yml中的网段设置

与controller manager以及kube-proxy脚本中设置的网段需要保持一致
复制代码
kube-flannel.yml 
net-conf.json: |
    {
      "Network": "10.244.0.0/16",
      "Backend": {
        "Type": "vxlan"
      }
    }
复制代码
 controller manager脚本
#!/bin/bash
##创建 kube-controller-manager 启动参数配置文件
MASTER_ADDRESS=$1
​
cat >/opt/kubernetes/cfg/kube-controller-manager <<EOF
KUBE_CONTROLLER_MANAGER_OPTS="--logtostderr=false \\
--v=2 \\
--log-dir=/opt/kubernetes/logs \\
--leader-elect=true \\
--kubeconfig=/opt/kubernetes/cfg/kube-controller-manager.kubeconfig \\
--bind-address=127.0.0.1 \\
--allocate-node-cidrs=true \\
--cluster-cidr=10.244.0.0/16 \\
--service-cluster-ip-range=10.0.0.0/24 \\
--cluster-signing-cert-file=/opt/kubernetes/ssl/ca.pem \\
--cluster-signing-key-file=/opt/kubernetes/ssl/ca-key.pem  \\
--root-ca-file=/opt/kubernetes/ssl/ca.pem \\
--service-account-private-key-file=/opt/kubernetes/ssl/ca-key.pem \\
--cluster-signing-duration=87600h0m0s"
EOF
kube-proxy脚本
复制代码
proxy.sh
#!/bin/bash
​
NODE_ADDRESS=$1
​
#创建 kube-proxy 启动参数配置文件
cat >/opt/kubernetes/cfg/kube-proxy <<EOF
KUBE_PROXY_OPTS="--logtostderr=false \\
--v=2 \\
--log-dir=/opt/kubernetes/logs \\
--hostname-override=${NODE_ADDRESS} \\
--cluster-cidr=10.244.0.0/16 \\
--proxy-mode=ipvs \\
--kubeconfig=/opt/kubernetes/cfg/kube-proxy.kubeconfig"
​

2.2 Calico的工作模式

IPIP模式

可以实现跨子网传输,但是传输过程中需要额外的封包和解包过程,对性能有一定的影响。

calico的IPIP模式工作原理

1)原始数据包从源主机的Pod容器发出,通过 veth pair 设备送达到tunl0接口,再被内核的IPIP驱动封装到node节点网络的IP报文里 2)根据Felix维护的路由规则通过物理网卡发送到目标node节点 3)IP数据包到达目标node节点的tunl0接口后再通过内核的IPIP驱动解封装得到原始数据包,再根据本地路由规则通过 veth pair 设备送达到目标Pod容器

BGP模式

会把每个node节点看作成路由器,通过Felix、BIRD组件来维护和分发路由规则,可实现直接通过BGP路由协议实现路由转发,传输过程中不需要额外封包和解包过程,因此性能较好,但是只能在同一个网段里使用,无法跨子网传输。

calico的BGP模式工作原理(本质就是通过路由规则来实现Pod之间的通信)

每个Pod容器都有一个 veth pair 设备,一端接入容器,另一个接入宿主机网络空间,并设置一条路由规则。 这些路由规则都是 Felix 维护配置的,由 BIRD 组件基于 BGP 动态路由协议分发路由信息给其它节点。 1)原始数据包从源主机的Pod容器发出,通过 veth pair 设备送达到宿主机网络空间 2)根据Felix维护的路由规则通过物理网卡发送到目标node节点 3)目标node节点接收到数据包后,会根据本地路由规则通过 veth pair 设备送达到目标Pod容器

混合模式(CrossSubnet)

2.3 flannel 与 calico 的区别

●flannel方案 需要在每个节点上把发向容器的数据包进行封装后,再用隧道将封装后的数据包发送到运行着目标Pod的node节点上。目标node节点再负责去掉封装,将去除封装的数据包发送到目标Pod上。数据通信性能则大受影响。

●calico方案 Calico不使用隧道或NAT来实现转发,而是把Host当作Internet中的路由器,使用BGP同步路由,并使用iptables来做安全访问策略,完成跨Host转发来。

flannel

UDP VXLAN HOST-GW 默认网段:10.244.0.0/16 通常会采用VXLAN模式,用的是叠加网络、IP隧道方式传输数据,对性能有一定的影响。 Flannel产品成熟,依赖性较少,易于安装,功能简单,配置方便,利于管理。但是不具备复杂的网络策略配置能力。

calico

IPIP BGP 混合模式(CrossSubnet) 默认网段:192.168.0.0/16 使用IPIP模式可以实现跨子网传输,但是传输过程中需要额外的封包和解包过程,对性能有一定的影响。 使用BGP模式会把每个node节点看作成路由器,通过Felix、BIRD组件来维护和分发路由规则,可实现直接通过BGP路由协议实现路由转发,传输过程中不需要额外封包和解包过程,因此性能较好,但是只能在同一个网段里使用,无法跨子网传输。calico不使用cni0网桥,而使通过路由规则把数据包直接发送到目标主机,所以性能较高;而且还具有更丰富的网络策略配置管理能力,功能更全面,但是维护起来较为复杂。

所以对于较小规模且网络要求简单的K8S集群,可以采用flannel作为cni网络插件。对于K8S集群规模较大且要求更多的网络策略配置时,可以考虑采用性能更好功能更全面的calico或cilium。

2.4 Calico实际部署

复制代码
​
//在 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: "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
 
 
---------- node02 节点部署 ----------
//在 node01 节点上操作
cd /opt/
scp kubelet.sh proxy.sh root@192.168.20.17:/opt/
scp -r /opt/cni root@192.168.20.17:/opt/
 
//在 node02 节点上操作
#启动kubelet服务
cd /opt/
chmod +x kubelet.sh
./kubelet.sh 192.168.20.17
 
//在 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.20.17
 
#查看群集中的节点状态
kubectl get nodes
​

3 CoreDNS

CoreDNS 是 K8S 默认的集群内部 DNS 功能实现,为 K8S 集群内的 Pod 提供 DNS 解析服务
  • 根据 service 的资源名称 解析出对应的 clusterIP

  • 根据 statefulset 控制器创建的Pod资源名称 解析出对应的 podIP

3.1 在所有 node 节点上操作

复制代码
上传 coredns.tar 到 /opt 目录中
cd /opt
docker load -i coredns.tar

3.2 在master节点上部署coredns

复制代码
上传 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
验证可以通过service的名称进行通信
复制代码
​
[root@master01 k8s#kubectl get pods --show-labels
##查看当前的pod资源 并展示其label标签
NAME                       READY   STATUS    RESTARTS   AGE   LABELS
test-v1-56f56b4db5-ksplj   1/1     Running   0          25m   app=test-v1,pod-template-hash=56f56b4db5
test-v1-56f56b4db5-z8p2p   1/1     Running   0          25m   app=test-v1,pod-template-hash=56f56b4db5
 
##查看当前的service资源有哪些
[root@master01 k8s#kubectl get service
复制代码
[root@master01 k8s#kubectl expose deployment test-v1  --port=80 --target-port=80
##创建service资源
service/test-v1 exposed
在node节点中进入容器,验证可以通过service资源名称通信以及可以实现nslookup
验证service资源可以实现pod集群的四层网络代理,实现负载均衡
相关推荐
lichenyang45314 小时前
Docker 学习笔记(四):Dockerfile,把项目打成自己的镜像
docker·容器
lichenyang45314 小时前
Docker 学习笔记(三):Docker 网络、bridge、子网和容器互通
docker·容器
lichenyang45314 小时前
Docker 学习笔记(二):docker run 的参数到底在控制什么?
docker·容器
运维开发故事3 天前
基于 Arthas 的多集群在线诊断系统设计与实现
kubernetes
Patrick_Wilson5 天前
从「改个端口」到 502:Next.js on k8s 的容器端口、Service 映射与 env 覆盖
docker·kubernetes·next.js
探索云原生6 天前
K8s 1.36 这个 GA 特性,把 initContainer 拉模型的 hack 干掉了
ai·云原生·kubernetes
云恒要逆袭6 天前
运行你的第一个Docker容器
后端·docker·容器
Java之美7 天前
一次k8s升级引发的DevicePlugin注册失败
云原生·kubernetes
程序员老赵7 天前
10 分钟部署 OpenCode:Docker 一键安装,浏览器打开就能用 AI 写代码(附完整命令与排错)
docker·容器·ai编程