二进制部署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集群的四层网络代理,实现负载均衡
相关推荐
小的~~7 分钟前
k8s使用本地docker私服启动自制的flink集群
docker·flink·kubernetes
诚诚k35 分钟前
docker存储
运维·docker·容器
数据智能老司机1 小时前
Kubernetes从入门到精通系列——外部 DNS 和全局负载均衡
云原生·容器·kubernetes
运维Z叔1 小时前
云安全 | AWS S3存储桶安全设计缺陷分析
android·网络·网络协议·tcp/ip·安全·云计算·aws
weixin_456732591 小时前
网络-内核是如何与用户进程交互
网络·交互
爱吃涮毛肚的肥肥(暂时吃不了版)2 小时前
计算机网络34——Windows内存管理
网络·计算机网络·udp
NiNg_1_2342 小时前
使用Docker Compose一键部署
运维·docker·容器
FLGB2 小时前
Flink 与 Kubernetes (K8s)、YARN 和 Mesos集成对比
大数据·flink·kubernetes
萠哥啥都行2 小时前
Linux安装Docker以及Docker入门操作
运维·docker·容器
码哝小鱼3 小时前
firewalld封禁IP或IP段
linux·网络