K8S多Master节点二进制部署、Calico、Dashboard部署

2,251 阅读9分钟

一、K8S的网络组件

1.1 flannel是什么?有什么模式?

  • flannel是k8s的pod能够实现跨Node节点通信的cni网络插件
  • 模式有:UDP(默认模式)、VXLAN(推荐使用的模式)、Host-gw(Host-gateway)(性能最好,但是配置繁琐)
  • 由于UDP模式是在用户态做转发,会多一次报文隧道封装,因此性能上会比内核态做转发的VXLAN模式差。

① flannel的udp模式工作原理(端口号默认8285)

image.png

  • 应用数据从源主机的Pod发出,经过cni0网桥接口,再由cni0转发到flannel0虚拟网卡接口
  • flannel的服务会监听flannel0接口的数据,flannel服务会将内部数据包(由Pod发出的)封装到udp报文中
  • 根据flannel在etcd维护的路由表,通过物理网卡,转发到目标主机(通过flannel在etcd中维护的路由表查询到目标Pod所在的节点IP,在udp报文外再封装节点的IP报文与MAC报文后转发到目标节点)
  • udp报文送到到目标主机的flannel的服务后,会将udp报文进行解封装,然后会通过目标主机的flannel0转发到目标主机的cni0网桥,最后再通过cni0网桥转发到目标的Pod

② flannel的VXLAN模式工作原理(官方预留端口号默认4789)(实际使用端口8472)

image.png

  • pod将数据帧(包含IP头部与报文)转发到cni0网桥,再转发到flannel.1虚拟网卡接口,flannel.1网卡会在数据帧上添加VXLAN头部作为标识,再将数据帧封装到UDP报文中
  • 根据flannel在etcd维护的路由表,封装目标主机的IP地址和MAC地址,通过物理网卡,转发到目标主机
  • 目标主机解析报文后,会通过8472端口,将数据包发送到flannel.1虚拟网卡接口,flannel.1会将udp报文进行解封装,并且解封装VXLAN头部信息,转发到网桥cni0,cni0网桥将数据帧转发到连接在网桥上的目标pod

1.2 k8s组网方案对比

  • flanne1方案

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

    • calico不使用隧道或NAT来实现转发,而是把Host当作Internet中的路由器,使用BGP同步路由,并使用iptables来做安全访问策略,完成跨Host转发。
    • 采用直接路由的方式,这种方式性能损耗最低,不需要修改报文数据,但是如果网络比较复杂场景下,路由表会很复杂,对运维同事提出了较高的要求。

1.3 flannel和calico 区别?

  • flannel使用的三种模式 udp、vxlan、host-gw

    • flannel 通常使用 vxlan 模式,采用的是叠加网络,IP隧道方式传输数据,可以实现跨子网进行传输。传输过程中需要进行封包和解包的过程,对性能有一定的影响。
    • 功能简单配置方便,利于管理,但不具有复杂的网络策略规则配置的能力
  • calico使用的三种模式 ipip、bgp、混合模式

    • calico的ipip模式,同样可以实现跨子网传输(同样采用叠加网络),但传输过程中一样需要进行封装和解封装的操作,对性能有一定的影响
    • calico的bgp模式可以直接根据bgp路由规则转发,并且传输过程中不需要封装和解封装,因此性能较好,但是只能在同一子网中使用,无法进行跨网使用;bgp模式具有更丰富的网络策略配置管理能力;但是维护起来较为复杂
  • 所以对于较小规模且网络要求简单的k8s集群,我们可以采用flannel,对于集群规模较大且要求更多的网络策略时,可以采用功能更全面的calico

二、网络组件calico

2.1 calico的模式

  • IPIP模式:在原有IP报文中封装一个新的IP报文,新的IP报文中将源地址IP和目的地址IP都修改为对端宿主机IP。calico 默认使用IPIP的模式。
  • BGP模式:将节点做为虚拟路由器通过BGP路由协议来实现集群内容器之间的网络访问。
  • cross-subnet ( ipip-bgp 混合模式):IPIP模式和BGP 模式都有对应的局限性,对于一些主机跨子网而又无法使网络设备使用BGP的场景可以使用cross-subnet

2.2 calico的组成部分

  • Calico CNI插件:主要负责与kubernetes对接,供kubelet 调用使用。
  • Felix:负责维护宿主机上的路由规则、FIB转发信息库等。
  • BIRD:负贵分发路由规则,类似路由器。
  • Confd:配置管理组件。

2.3 calico的工作原理

image.png

  • IPIP模式:
    • Calico会将容器的IP 包通过内核的IPIP 驱动直接在封装宿主机网络的IP包中,并根据路由通过tunl0 网卡发送给其他节点,这样到达目标节点以后再通过IPIP 驱动解包得到原始容器IP包,然后通过路由规则发送给veth pair设备到达目标容器。

image.png

  • BGP模式:

    • Calico是通过路由表来维护每个pod 的通信。calico的CNI插件会为每个容器设置一个veth pair设备,然后把另一端接入到宿主机网络空间,由于没有网桥,CNI插件还需要在宿主机上为每个容器的veth pair设备配置一条路由规则,用于接收传入的IP包
    • 有了这样的veth pair设备以后,容器发出的IP包就会通过,veth pair设备到达宿主机,然后宿主机根据路由规则的下一跳地址,发送给正确的网关,然后到达目标宿主机,再到达目标容器。
    • 这些路由规则都是Felix(维护BGP路由规则)维护配置的,而路由信息则是Calico BIRD组件(负责路由分发)基于BGP分发而来。
    • calico实际上是将集群里所有的节点都当做边界路由器来处理,他们一起组成了一个全互联的网络,彼此之间通过BGP交换路由,这些节点我们叫做BGP Peer。
  • 相比IPIP模式, BGP模式下不需要tunl0设备参与报文传输,报文直接通过物理网卡(比如ens33)转发到目标机器上,不会进行二次IP报文的封装,因此从性能上来看,BGP是占优势的。但是由于没有二次封包,BGP模式只能在同一个子网内使用,无法跨网段使用。

  • 目前比较常用的CNI网络组件是flannel和calico,flannel 的功能比较简单,但不具备复杂的网络策略配置能力。但calico以其性能、灵活性而闻名。Calico的功能更为全面,不仅提供主机和pod之间的网络连接,还涉及网络安全和管理,但具备复杂网络配置能力的同时,往往意味着本身的配置比较复杂,所以相对而言,比较小而简单的集群使用flannel,考虑到日后扩容,未来网络可能需要加入更多设备,配置更多网络策略,则使用calico更好。

2.4 flannel下的跨界点通讯示例

① master节点查看目前节点状态

kubectl get nodes      #查看节点服务器状态

image.png

kubectl get pods -A    #查看安装插件

image.png

② master节点创建资源

kubectl create deployment testapp --image=soscscs/myapp:v1 --replicas=3
#创建一个pod控制器为deployment(用于部署无状态应用),创建一个资源名为testapp,指定pod使用的镜像为image=soscscs/myapp:v1 ,创建3个副本

image.png

kubectl get all   #查看所有已存在的资源

image.png

kubectl get pods  #查看当前默认命名空间中的pod

image.png

kubectl get pods -owide   #查看当前默认命名空间中的pod的地址

image.png

③ work node两个节点操作

docker exec -it ca8267e568ed sh
ip a 
#两个node节点分别进入创建好的容器当中,查看容器的IP

image.png

image.png

image.png

通过上图可以看见不同节点的pod可以实现正常通信,其中是制定了一套CNI接口规范,开放其他节点来实现通信。

三、部署 Calico

① 在 master01 节点上操作

#首先,卸载flannel服务
cd /opt/k8s/
kubectl delete -f kube-flannel.yml   #删除flannel配置文件,即可删除flannel服务

#在 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"

image.png

kubectl apply -f calico.yaml

#等 Calico Pod 都 Running,节点也会准备就绪
kubectl get nodes

image.png

image.png

四、部署多master节点的K8S环境(实现高可用)

4.1 服务器准备

服务器IP地址
K8s集群master01(已部署)192.168.142.10
K8s集群node01(已部署)192.168.142.40
K8s集群node02(已部署)192.168.142.100
K8s集群master02(新添加)192.168.142.10
K8s集群负载均衡器MASTER(新添加)192.168.142.30
K8s集群负载均衡器BACKUP(新添加)192.168.142.50

image.png

4.2 master02操作系统初始化配置

#关闭防火墙
systemctl stop firewalld
systemctl disable firewalld
iptables -F && iptables -t nat -F && iptables -t mangle -F && iptables -X

#关闭selinux
setenforce 0
sed -i 's/enforcing/disabled/' /etc/selinux/config

#关闭swap
swapoff -a
sed -ri 's/.*swap.*/#&/' /etc/fstab 

#根据规划设置主机名
hostnamectl set-hostname master02

#在master添加hosts,添加各个节点的映射关系
cat >> /etc/hosts << EOF
192.168.142.10 master01
192.168.142.20 master02     #关于已经配置好的其他节点需要在映射关系文件中添加改行
192.168.142.40 node01
192.168.142.100 node02
EOF

image.png

#调整内核参数
cat > /etc/sysctl.d/k8s.conf << EOF
#开启网桥模式,可将网桥的流量传递给iptables链
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
#关闭ipv6协议
net.ipv6.conf.all.disable_ipv6=1
net.ipv4.ip_forward=1
EOF

sysctl --system

#时间同步
yum install ntpdate -y
ntpdate time.windows.com

4.3 将master01中的配置文件复制到master02上

# master01操作
scp -r etcd/ kubernetes/ master02:/opt
#将/opt目录下的etcd和kubernetes两个目录移动到master02节点的/opt目录下


# 将kubectl的配置文件复制到master02节点下
cd ~    #到达家目录下
ls -A   
#将.kube目录移至master02节点家目录下
scp -r .kube/ master02:/root

image.png

cd /lib/systemd/system
scp kube-* master02:`pwd`   #将服务文件移至master02节点

image.png

image.png

image.png

4.4 修改master节点监听地址

cd /opt/kubernetes/cfg/
vim kube-apiserver      #修改apiserver的监听地址

#若服务文件配置内容为127.0.0.1本机地址,则不做以下两个文件内容的修改
vim kube-controller-manager
vim kube-scheduler

image.png

#配置文件都修改结束后,启动服务
systemctl enable --now kube-apiserver.service
systemctl enable --now kube-controller-manager.service
systemctl enable --now kube-scheduler.service

cd /opt/kubernetes/
ln -s /opt/kubernetes/bin/* /usr/local/bin/  #将目录下的文件放入shell中进行系统的管理

image.png

4.5 主备负载均衡器配置

#关闭防火墙,并关闭开机自启
systemctl disable --now firewalld.service

#关闭开机自启
setenforce 0

#将nginx官方源镜像文件,导入/etc/yum.repos.d目录下

image.png

    ##实现负载均衡配置如下##
#两个负载均衡服务器下载nginx及keepalived服务
yum install -y nginx keepalived 

cd /etc/nginx/
#在nginx配置文件中,进行简单的四层代理配置
vim nginx.conf

#在http块上方同级块中,添加以下配置:
stream {
    upstream apiservers {
        server 192.168.142.10:6443;
        server 192.168.142.20:6443;
    }

    server {
        listen 6443;
        proxy_pass apiservers;
    }
}

#配置完成后,检查配置文件语法错误,并进行nginx服务开启
nginx -t    #查看配置文件语法错误,有以下两行内容,即文件语法没错误
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful

systemctl enable --now nginx    #开启nginx服务并开启开机自启
netstat -natp | grep nginx      #查看nginx服务是否开启
netstat -natp | grep :6443      #查看6443端口是否绑定

image.png

image.png

image.png

###实现高可用###
cd /etc/keepalived/  #keepalived主配置文件目录
vim check_nginx.sh   #做一个检测脚本,控制keepalived服务

#!/bin/bash
#判断nginx服务是否被关闭,如果服务被关闭或掉线则关闭keepalived服务
killall -0 nginx &> /dev/null

if [ $? -ne 0 ]; then
   systemctl stop keepalived
fi

chmod +x check_nginx.sh   #给予脚本执行权限

#修改keepalived主配置文件(主备调度器文件内容有区别)
vim keepalived.conf  #主配置文件仅保留以下内容
! Configuration File for keepalived

#设置route id名称
global_defs {
   router_id NGINX_MASTER    #设置router id(backup调度器名称为NGINX_BACKUP)
}

#设置监控脚本的路径
vrrp_script check_nginx {
   script "/etc/keepalived/check_nginx.sh"    

}

vrrp_instance VI_1 {
    state MASTER        #设置组的角色名称(backup调度器名称为BACKUP)
    interface ens33     #设置网卡信息/名称
    virtual_router_id 51 
    priority 100        #设置优先级(backup调度器优先级调整为90)
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass 1111
    }
    
    #设置VIP地址
    virtual_ipaddress {
        192.168.142.120     
    }
    
    #跟踪脚本
    track_script {
        check_nginx
    }
}

#主备调度器配置完成后,启动keepalive服务
systemctl start keepalived.service
systemctl enable keepalived.service 


image.png

image.png

image.png

实现高可用后,对主调度器进行nginx服务的关闭,验证VIP的转移:

image.png

image.png

image.png

4.6 修改node节点组件配置

#两个node节点均做以下修改
cd /opt/kubernetes/cfg/
#修改kubeconfig结尾的集群配置文件
vim bootstrap.kubeconfig
vim kubelet.kubeconfig
vim kube-proxy.kubeconfig
#将以上三个配置文件中的server修改为VIP地址

#修改完成后,重启kubelet服务与kube-proxy服务
systemctl restart kubelet.service kube-proxy.service

image.png

image.png

此时,查看调度器节点的nginx服务状态

netstat -natp | grep nginx

image.png

上方查看nginx状态可以看到,两个node节点向调度器进行请求连接的状态

之后调度器与node节点成功建立连接后,调度器会再去与master节点建立连接

最后将node节点的请求转发到master节点上

验证成功,高可用负载均衡K8S集群就已经搭建完毕

五、部署 Dashboard

5.1 Dashboard介绍

仪表板是基于Web的Kubernetes用户界面。我们可以使用仪表板将容器化应用程序部署到Kubernetes集群,对容器化应用程序进行故障排除,并管理集群本身及其伴随资源。您 可以使用仪表板来概述群集上运行的应用程序,以及创建或修改单个Kubehetes资源(例如deployment,job, daemonset等)。例如,我们可以使用部署向导扩展部署,启动滚 动更新,重新启动Pod或部署新应用程序。仪表板还提供有关群集中KubeInetes资源状态以及可能发生的任何错误的信息。

5.2 CoreDNS介绍

  • CoreDNS 是一个灵活可扩展的 DNS 服务器,可以作为 Kubernetes 集群 DNS,在Kubernetes1.12版本之后成为了默认的DNS服务。 与 Kubernetes 一样,CoreDNS 项目由 CNCF 托管。

  • CoreDNS在K8S中的用途,主要是用作服务发现,也就是服务(应用)之间相互定位的过程。

  • 在k8s中,用service资源代理pod,通过暴露service资源的固定地址(集群IP),来解决以上POD资源变化产生的IP变动问题,但是针对service还存在以下问题:

    • service IP地址难以记忆
    • service资源可能也会被销毁和创建
    • pod ip本身也有需要暴漏的需求
  • 为了解决以上问题,引入了coredns,在K8S,其主要用于服务发现,也就是服务(应用)之间相互定位的过程

5.3 部署CoreDNS

① node节点安装镜像

#在所有 node 节点上操作
#上传 coredns.tar 到 /opt 目录中
cd /opt
docker load -i coredns.tar

image.png

② master节点运行

#在 master01 节点上操作
#上传 coredns.yaml 文件到 /opt/k8s 目录中,部署 CoreDNS 
cd /opt/k8s
kubectl apply -f coredns.yaml

image.png

kubectl get pods -n kube-system 
NAME                                       READY   STATUS    RESTARTS   AGE
calico-kube-controllers-659bd7879c-fz4lz   1/1     Running   0          13m
calico-node-65m8m                          1/1     Running   0          13m
calico-node-c2zgk                          1/1     Running   0          13m
coredns-6954c77b9b-rjsrp                   1/1     Running   0          21s

#DNS 解析测试
kubectl get svc -A #查看集群中的服务信息(包括服务名称,所属命名空间)
kubectl get pods   #查看集群中的容器,并使用容器id进入容器
kubectl exec -it testapp-75bb94f97b-mjrc4 sh   #进入容器中进行解析操作

#进入容器后进行解析
/ # nslookup kube-dns.kube-system.svc.cluster.local   #解析格式nslookup 服务名称.命名空间.完整的域名

nslookup: can't resolve '(null)': Name does not resolve    
#上方报错可以忽略,下方为正常解析内容
Name:      kube-dns.kube-system.svc.cluster.local
Address 1: 10.0.0.2 kube-dns.kube-system.svc.cluster.local

image.png

5.3 部署 Dashboard

//在 master01 节点上操作
#上传 recommended.yaml 文件到 /opt/k8s 目录中,部署 CoreDNS 
cd /opt/k8s
vim recommended.yaml
#默认Dashboard只能集群内部访问,修改Service为NodePort类型,暴露到外部:
kind: Service
apiVersion: v1
metadata:
  labels:
    k8s-app: kubernetes-dashboard
  name: kubernetes-dashboard
  namespace: kubernetes-dashboard
spec:
  ports:
    - port: 443
      targetPort: 8443
      nodePort: 30001     #添加
  type: NodePort          #添加
  selector:
    k8s-app: kubernetes-dashboard

image.png

#加载配置
kubectl apply -f recommended.yaml

#创建service account并绑定默认cluster-admin管理员集群角色
kubectl create serviceaccount dashboard-admin -n kube-system    #创建serviceaccount资源账户dashboard-admin,并且在kube-system命名空间当中进行创建
kubectl create clusterrolebinding dashboard-admin --clusterrole=cluster-admin --serviceaccount=kube-system:dashboard-admin    #做个RBAC资源绑定,进行角色绑定,资源名称为dashboard-admin,用户为kube-system:dashboard-admin
kubectl describe secrets -n kube-system $(kubectl -n kube-system get secret | awk '/dashboard-admin/{print $1}')

#使用输出的token登录Dashboard
https://192.168.142.40:30001
#登录不要使用谷歌浏览器,谷歌浏览器内置会自动拦截该服务

#如何获取进入Dashboard界面的token信息
kubectl get secret -n kube-system    #获取资源的名称
kubectl describe secrets -n kube-system dashboard-admin-token-xlc5b   #获取该资源的token信息

image.png

image.png

image.png

image.png