k8s的网络类型

k8s中的通信模式

pod内部之间容器与容器之间的通信:

在同一个pod中的容器时共享资源和网络。使用同一个网络命名空间。可以直接通信

同一个node节点之内,不同pod之间的通信:

每个pod都有一个全局的真实IP地址。同一个node节点之间的不同pod可以直接使用对方pod的IP地址进行通信。

例如:pod1和pod2时通过docker0的网桥来进行通信。

不同node节点上的pod之间进行通信:

cni插件:cni在k8s中是一个标准接口,在容器运行时调用网络插件,配置容器网络。负责设置容器的网络命名空间,IP地址。路由等等一系列的参数。

flannel插件

flannel:这是一个插件或者说组件。是cni插件中的一个组件。

flannel的作用

它可以让集群中不同节点的docker容器具有全集群唯一的虚拟IP地址。

overlay网络

在底层物理网络的基础之上,创建一个逻辑的网络层。属于二层+三层的集合。二层是物理网络而三层是逻辑上的网络层。

overlay网络也是一种网络虚拟化的技术。

flannel支持的数据转发方式

UDP模式

默认模式,应用转发、配置简单但是性能最差。默认就是UDP

UDP:基于应用转发,flannel提供路由表,flannel封装数据包,解封装。

UDP基于应用层。走用户态

UDP模式使用的网卡是flannel.0

UDP模式的工作流程:

封装过程:

pod将数据通过 docker 0 网桥将数据转发的flannel.0网卡

node节点上都会有一个flannel的虚拟网卡负责封装和解封装。

网卡:flannel.0。封装数据包。通过自身flannel插件的路由表转发。

转发到部署在k8s上的pod。flanneld上。

每个node节点都有一个IP地址。在封装的过程中,会封装两层

第一层信息是源IP地址和目的IP地址

第二层是容器内的信息源内部容器的IP到目的内部容器的IP地址。使用的是UDP协议

数据包封装好了之后会转发到20的pod节点flannel。

解封装过程:

先到flannel.0网卡。由网卡来转发。通过docker0的网桥把数据流量转发到指定的容器内部。发送到指定的pod上。

在封装和解封装之后,信息会保存在etcd中。下次转发,可以直接请求etcd

vxlan模式

基于内核转发,是最常用的网络类型。

一般的小集群都是用vxlan模式。

vxlan使用的overlay的虚拟隧道通信技术。二层+三层

flannel提供路由表,内核实现封装和解封装。

vxlan使用的网卡是flannel1.1网卡

vxlan模式的工作流程:

封装:

pod基于 docker 0 的网桥将数据传输至flannel.1网卡。会生成一个VTEP虚拟网络隧道。

VTEP:virul tunel endpoint 虚拟网络隧道

由网卡将发送至对方的网卡

通过VTEP来实现数据封装。

源IP地址和目的IP地址还会生成vni。类似于vlanid。这些vni对应的是内部容器的源IP和目的iIP。

这些信息也会保存到etcd中

通过隧道模式转发

解封装:

数据发送到对方的网卡。

由内核解封装数据包。并传递给flannel.1网卡,通过数据包内的目的vni地址。

依次向下传递通过 docker 0 找到指定pod内容器的IP地址。

封装过程类似于三层交换机

这里的flannel就需要负责识别对应的VNI的IP地址即可

这些信息也会保存到etcd中

总结:flannel提供VNI,在封装过程中会绑定VNI和目标IP地址进行绑定。由内核封装解封装。通过数据包内的目的vni地址。 找到指定pod内容器的IP地址。

host-gw模式

性能最好,但是配置麻烦。

总结

flannel将每个发向容器的数据包进行封装。vxlan通过vtep打包数据。由内核封装成数据包。转发到目的node节点。到了目标节点,还有个解封装的过程。再发送目标pod,性能是有一定影响的。

部署 CNI 网络组件安装flannel

bash 复制代码
在 node01 节点上操作
上传 cni-plugins-linux-amd64-v0.8.6.tgz 和 flannel.tar 到 /opt 目录中
在主节点上传入flannel的yml文件
cd /opt/
docker load -i flannel.tar

mkdir -p /opt/cni/bin
tar zxvf cni-plugins-linux-amd64-v0.8.6.tgz -C /opt/cni/bin
#解压插件源码包放到指定的目录中。
node02节点上相同操作

在 master01 节点上操作上传入flannel的yml文件 部署 CNI 网络
cd /opt/k8s
kubectl apply -f kube-flannel.yml
#自动拉起pod节点

kubectl get pods -n kube-system
#查看是否拉起成功
kubectl get -o wide pods -n kube-system
#查看node使用的IP地址是什么

calico插件

calico:采用直接路由的方式。BGP路由。不需要修改报文,统一直接通过路由表转发。路由表会很复杂。对运行维护的要求比较高。

BGP模式的特点:交换路由信息的外部网关协议,可以连接不同的node节点。这些node节点可能不是一个网段。BGP实现可靠的、最佳的、动态的路由选择。自动识别相邻的路由设备(自动识别需要手动配置)。

可靠:安全

最佳:最佳路径

动态:自动识别自动选择

calico不使用重叠网络,也不需要交换,直接通过虚拟路由实现。每一台虚拟路由都通过BGP转发到不同的节点。

calico的核心组件

felix:也是运行再主机上一个个pod,可以理解为一个个进程。在k8s中通过daemonset的方式部署pod。

daemontset会在每个node节点上以后台运行方式部署相同的pod。

负责在宿主机上插入规则。维护calico所需的网络设备。例如:管理、监听网络接口。路由转发等等。

BGP client:就是BIRD。是BGP的客户端、专门负责在集群当中分发路由规则的信息。每一个节点都会有一个BGP client。

BGP协议广播方式通知掐他节点,分发路由规则。实现网络互通

etcd:保存路由信息。负责网络元数据的一致性。

etcd保存元数据的作用就是保证整个网络状态的一致和准确。

calico插件的工作:

通过路由表维护每个pod之间的通信。

一旦创建好pod之后,会添加一个设备cali。生成veth pair设备

veth pair设备:是一对设备,虚拟的以太网设备。一头连接在容器的网络命名空间(eth0)。另一头连接宿主机的网络命名空间(cali)

IP地址分配:veth pair连接容器的部分给容器分配一个IP地址。这个IP地址是唯一标识。宿主机也会被veth pair分配一个calico网络的内部IP地址。用于和其他节点上的容器进行通信。

veth设备,容器发出的IP地址通过veth pair设备到宿主机。宿主机根据路由规则的下一跳地址发送到网关。也就是目标宿主机。

数据包到达目标宿主机,通过veth pari设备。目标宿主机也是根据路由规则。下一跳地址。转发的目标容器。

calico是路由转发,直接转发。一头连接容器,一头连接宿主机。通过bgp协议自动发现对方设备。直接通过路由规则转发。

ipip模式:会生成一个tunnel。所有的数据包封装都在tunnel内部打包。封装宿主机IP、容器内部的IP地址。

部署 CNI 网络组件安装calico

bash 复制代码
在 master01 节点上操作上传 calico.yaml 文件到 /opt/k8s 目录中,部署 CNI 网络
cd /opt/k8s
vim calico.yaml
-----3878行-----
修改里面定义 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
#执行部署calico的yaml文件
kubectl get pods -n kube-system
#查看节点是否部署成功
#有一个总控制网络负责控制两个节点网络
kubectl get nodes

kubectl create deployment nginx1 --image=nginx:1.22 --replicas=3
#每创建一个pod就会生成一个calico网卡
ip route
#可以查看路由表

靠路由规则和路由条目转发。但是路由表数量太多,反而会影响转发效率。可以手动删除pod,它会自动清空路由表和路由条目。

在k8s中常用的网络插件有flannel和calico两种

flannel插件

flannel:配置简单。功能简单。基于overlay叠加网络实现。在物理层的网络封装一个虚拟的网络。

vxlan是虚拟三层网络。

UDP是默认模式一般不用。

flannel使用最多的就是vxlan模式。它是通过vni+ip进行转发,flannel提供路由表,由内核封装和解封装。

由于封装和解封装的过程。对数据传输的性能会有影响。同时不具备网络策略配置的能力。

host-gw配置太过于复杂。

calico插件

calico:功能强大,基于路由表转发。没有封装和解封装的过程。具备网络策略和配置能力。但是路由表维护起来比较复杂。

calico有两种模式:ipip、BGP

BGP:通过为ip路由表的前缀来实现目标主机的可达性。对比ipip模式,BGP模式没有隧道。BGP模式下,pod的数据包直接通过网卡,发送到目的地。

ipip的隧道:隧道进行数据包的封装。外层是宿主机的IP----内部是容器的IP

如果是简单的小集群使用flannel即可。

如果考虑到扩容、配置网络策略建议使用calico。

我们公司集群比较小使用flannel插件使用vxlan模式,但是calico我也知道。

coredns

可以在集群当中的为service资源创建一个域名和IP进行对应解析的关系。

service是对外提供访问的地址。现在加入DNS机制之后,可以直接访问服务名。

部署 CoreDNS

bash 复制代码
在所有 node 节点上操作
上传 coredns.tar 到 /opt 目录
cd /opt
docker load -i coredns.tar

在 master01 节点上操作
上传 coredns.yaml 文件到 /opt/k8s 目录中,部署 CoreDNS 
cd /opt/k8s
kubectl apply -f coredns.yaml
#一件拉起执行配置文件
kubectl get pods -n kube-system

kubectl run -it --rm dns-test --image=busybox:1.28.4 sh
#--rm:一旦退出容器就会被销毁
nslookup kubernetes
exit

部署多节点master02

bash 复制代码
开始master02 节点部署
iptables -F
iptables -t nat -F
iptables -t mangle -F
iptables -x
#清空iptables的所有策略
master01、node01、node02关闭swap交换分区
swapoff -a
#关闭swap交换分区
#k8s在涉及时,为了提升性能,默认不使用swap交换分区,k8s在初始化的时候会自动检测swap
开始给主机改名
hostnamectl set-hostname master02
cat >> /etc/hosts << EOF
20.0.0.32 master01
20.0.0.33 master02
20.0.0.34 node01
20.0.0.35 node02
EOF
每台主机都加入映射

优化参数:
cat > /etc/sysctl.d/k8s.conf << EOF
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
net.ipv6.conf.all.disable_ipv6=1
net.ipv4.ip_forward=1
EOF
systemctl --system
#让配置文件生效

进行时间同步:
yum install ntpdate -y ntpdate ntp.aliyun.com 

从 master01 节点上拷贝证书文件、各master组件的配置文件和服务管理文件到 master02 节点
scp -r /opt/etcd/ root@20.0.0.33:/opt/
scp -r /opt/kubernetes/ root@20.0.0.33:/opt
scp -r /root/.kube root@20.0.0.33:/root
scp /usr/lib/systemd/system/{kube-apiserver,kube-controller-manager,kube-scheduler}.service root@20.0.0.33:/usr/lib/systemd/system/

修改配置文件kube-apiserver中的IP
vim /opt/kubernetes/cfg/kube-apiserver
----修改第五行和第七行----
#改成本机的IP地址20.0.0.33

开启组件:
systemctl start kube-apiserver.service
systemctl enable kube-apiserver.service
#开启apiserver
systemctl start kube-controller-manager.service
systemctl enable kube-controller-manager.service
#开启运行管理器
systemctl start kube-scheduler.service
systemctl enable kube-scheduler.service
#开启资源调度组件

查看node节点状态:
ln -s /opt/kubernetes/bin/* /usr/local/bin/
#创建软连接让系统可以识别
kubectl get nodes
kubectl get nodes -o wide
此时node节点并没有和master02并没有真正建立通信。是etcd里存储的信息。

部署负载均衡器

bash 复制代码
负载均衡部署
配置nginx的官方在线yum源,配置本地nginx的yum源
在两个nginx主机上操作36、37
cat > /etc/yum.repos.d/nginx.repo << 'EOF'
[nginx]
name=nginx repo
baseurl=http://nginx.org/packages/centos/7/$basearch/
gpgcheck=0
EOF

yum install nginx -y

修改nginx配置文件,配置四层反向代理负载均衡,指定k8s群集2台master的节点ip和6443端口
vim /etc/nginx/nginx.conf
events {
    worker_connections  1024;
}
#添加
stream {
    log_format  main  '$remote_addr $upstream_addr - [$time_local] $status $upstream_bytes_sent';
#日志记录格式	
#$remote_addr: 客户端的 IP 地址。
#$upstream_addr: 上游服务器的地址。
#[$time_local]: 访问时间,使用本地时间。
#$status: HTTP 响应状态码。
#$upstream_bytes_sent: 从上游服务器发送到客户端的字节数。
    
	access_log  /var/log/nginx/k8s-access.log  main;

    upstream k8s-apiserver {
        server 20.0.0.32:6443;
        server 20.0.0.33:6443;
    }
    server {
        listen 6443;
        proxy_pass k8s-apiserver;
    }
}

检查配置文件语法
nginx -t

启动nginx服务,查看已监听6443端口
systemctl start nginx
systemctl enable nginx
netstat -natp | grep nginx 

部署keepalived服务
yum install keepalived -y

修改keepalived配置文件
vim /etc/keepalived/keepalived.conf
! Configuration File for keepalived

global_defs {
   # 接收邮件地址
   notification_email {
     acassen@firewall.loc
     failover@firewall.loc
     sysadmin@firewall.loc
   }
   # 邮件发送地址
   notification_email_from Alexandre.Cassen@firewall.loc
   smtp_server 127.0.0.1
   smtp_connect_timeout 30
   router_id NGINX_MASTER	
   #lb01节点的为 NGINX_MASTER,lb02节点的为 NGINX_BACKUP
   #vrrp_strict  #注释掉
}

添加一个周期性执行的脚本
vrrp_script check_nginx {
    script "/etc/nginx/check_nginx.sh"	
    #指定检查nginx存活的脚本路径
}

vrrp_instance VI_1 {
    state MASTER
    #lb01节点的为 MASTER,lb02节点的为 BACKUP
    interface ens33
    #指定网卡名称 ens33
    virtual_router_id 51
    #指定vrid,两个节点要一致
    priority 100
    #lb01节点的为 100,lb02节点的为 90
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass 1111
    }
    virtual_ipaddress {
        20.0.0.100/24
        #指定 VIP
    }
    track_script {
        check_nginx
        #指定vrrp_script配置的脚本
    }
}

创建nginx状态检查脚本 
vim /etc/nginx/check_nginx.sh
#!/bin/bash                                                        
/usr/bin/curl -I http://localhost &>/dev/null    
if [ $? -ne 0 ];then                                            
#/etc/init.d/keepalived stop
    systemctl stop keepalived
fi 

chmod +x /etc/nginx/check_nginx.sh

启动keepalived服务(一定要先启动了nginx服务,再启动keepalived服务)
systemctl start nginx
systemctl enable nginx
systemctl start keepalived
systemctl enable keepalived

修改node节点上的bootstrap.kubeconfig,kubelet.kubeconfig配置文件为VIP:
cd /opt/kubernetes/cfg/
vim bootstrap.kubeconfig 
server: https://20.0.0.100:6443
vim kubelet.kubeconfig
server: https://20.0.0.100:6443
vim kube-proxy.kubeconfig
server: https://20.0.0.100:6443
重启kubelet和kube-proxy服务:
systemctl restart kubelet.service 
systemctl restart kube-proxy.service

在 lb01 上查看 nginx 和 node 、 master 节点的连接状态
netstat -natp | grep nginx
netstat -natp | grep 6443

在 master01 节点上操作:
测试创建pod
kubectl run nginx --image=nginx
查看Pod的状态信息
kubectl get pods
kubectl get pods -o wide
在对应网段的node节点上操作,可以直接使用浏览器或者curl命令访问
curl 172.17.36.2
kubectl exec -it nginx bash
这时在master01节点上查看nginx日志
kubectl logs nginx-dbddb74b8-nf9sk

部署 Dashboard

相当于是仪表盘是基于Web的Kubernetes用户界面。您可以使用仪表板将容器化应用程序部署到Kubernetes集群

bash 复制代码
在 master01 节点上操作
#上传 recommended.yaml 文件到 /opt/k8s 目录中
cd /opt/k8s
vim recommended.yaml
kubectl apply -f recommended.yaml

创建service account并绑定默认cluster-admin管理员集群角色:
kubectl create serviceaccount dashboard-admin -n kube-system

kubectl create clusterrolebinding dashboard-admin --clusterrole=cluster-admin --serviceaccount=kube-system:dashboard-admin

获取token值:
kubectl describe secrets -n kube-system $(kubectl -n kube-system get secret | awk '/dashboard-admin/{print $1}')

使用输出的token登录Dashboard
https://20.0.0.34:30001

将token的值复制出来到浏览器登录即可。

实验搭建完成!

解决etcd节点故障的方式

bash 复制代码
[root@k8s-master1 ~]# kubectl get cs
NAME                 STATUS      MESSAGE                                  ERROR
controller-manager   Healthy     ok                                       
scheduler            Healthy     ok                                       
etcd-1               Healthy     {"health":"true"}                        
etcd-0               Healthy     {"health":"true"}                        
etcd-2               Unhealthy   HTTP probe failed with statuscode: 503

ETCDCTL_API=3 /opt/etcd/bin/etcdctl --cacert=/opt/etcd/ssl/ca.pem --cert=/opt/etcd/ssl/server.pem --key=/opt/etcd/ssl/server-key.pem --endpoints="https://192.168.233.91:2379,https://192.168.233.93:2379,https://192.168.233.94:2379" endpoint health --write-out=table


1.将有故障的etcd节点remove出集群:
ETCDCTL_API=3 /opt/etcd/bin/etcdctl --cacert=/opt/etcd/ssl/ca.pem --cert=/opt/etcd/ssl/server.pem --key=/opt/etcd/ssl/server-key.pem --endpoints="https://192.168.233.91:2379,https://192.168.233.93:2379,https://192.168.233.94:2379" --write-out=table member list

cf4f326398a30bd2

86ec40d44e54cf0a

/opt/etcd/bin/etcdctl --cacert=/opt/etcd/ssl/ca.pem --cert=/opt/etcd/ssl/server.pem --key=/opt/etcd/ssl/server-key.pem --endpoints="https://192.168.233.91:2379,https://192.168.233.93:2379,https://192.168.233.94:2379" member remove 故障节点的id   

2、来到故障节点

rm -rf /var/lib/etcd/default.etcd/member/



修改etcd配置文件,将下面new修改为:
vim /opt/etcd/cfg/etcd 

修改前:

ETCD_INITIAL_CLUSTER_STATE="new"
修改后:

ETCD_INITIAL_CLUSTER_STATE="existing"


3、重新加入etcd集群:
/opt/etcd/bin/etcdctl --cacert=/opt/etcd/ssl/ca.pem --cert=/opt/etcd/ssl/server.pem --key=/opt/etcd/ssl/server-key.pem --endpoints="https://192.168.233.91:2379,https://192.168.233.93:2379,https://192.168.233.94:2379" member add etcd-2 --peer-urls=https://192.168.233.94:2380


4、重启etcd故障节点即可
相关推荐
振浩微433射频芯片5 小时前
433MHz在智能家居中的应用大全(二):智能安防篇——安全不容“信号死角”
网络·单片机·嵌入式硬件·物联网·智能家居
问简5 小时前
docker 镜像相关
运维·docker·容器
Benszen6 小时前
Docker容器化技术实战指南
运维·docker·容器
fengfuyao9856 小时前
基于STM32的4轴步进电机加减速控制工程源码(梯形加减速算法)
网络·stm32·算法
Hommy887 小时前
【开源剪映小助手】Docker 部署
docker·容器·开源·github·aigc
瀚高PG实验室8 小时前
审计策略修改
网络·数据库·瀚高数据库
forAllforMe8 小时前
etherCAT的协议VoE,FoE,EoE,CoE的概念和区别
网络
斯普信云原生组8 小时前
Prometheus 环境监控虚机 Redis 方案(生产实操版)
运维·docker·容器
大数据新鸟8 小时前
操作系统之虚拟内存
java·服务器·网络
喵了几个咪8 小时前
如何在 Superset Docker 容器中安装 MySQL 驱动
mysql·docker·容器·superset