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

在 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

在 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

在所有 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

开始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/ [email protected]:/opt/
scp -r /opt/kubernetes/ [email protected]:/opt
scp -r /root/.kube [email protected]:/root
scp /usr/lib/systemd/system/{kube-apiserver,kube-controller-manager,kube-scheduler}.service [email protected]:/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里存储的信息。

部署负载均衡器

负载均衡部署
配置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 {
     [email protected]
     [email protected]
     [email protected]
   }
   # 邮件发送地址
   notification_email_from [email protected]
   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集群

在 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节点故障的方式

[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故障节点即可

你可能感兴趣的:(kubernetes,网络,容器)