k8s高可用集群搭建部署

     阅读:45

简介

k8s普通搭建出来只是单master节点,如果该节点挂掉,则整个集群都无法调度,K8s高可用集群是用多个master节点加负载均衡节点组成,外层再接高可用分布式存储集群例如ceph集群,实现计算能力+存储能力的高可用,同时,etcd也可以独立出来用外部的etcd集群

架构详解

高可用架构图

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WBwrIhIh-1646290414086)(RackMultipart20220303-4-1aeg5pm_html_80f5e022fe130409.png)]

架构详解

  • 访问链路步骤:外部域名访问 ——> node集群负载均衡 ——>ingress ——> node集群 ——> serivce ——> pod
  • 内部元数据存储步骤:master集群 or node集群 ——> etcd集群
  • 内部使用存储节点步骤:master集群 or node集群 ——> 高可用分布式存储集群
  • k8s的多台master集群被负载均衡做4层代理,做到了高可用,访问时只通过负载均衡访问
  • K8s的node节点接入master时通过master的负载均衡接入,就算挂掉一个master也无感知
  • K8s的node节点被外层负载均衡代理,pod启动后被service代理,service上的端口被ingress代理转发再到外层负载均衡,外部通过域名访问
  • K8s集群的重要元数据存储到外部etcd集群上,保障高可用和强一致性(这里我没使用外部)
  • K8s集群的pod使用存储直接使用外部高可用分布式存储集群例如ceph集群,保障性能和可用性
  • 总结:k8s的master节点使用负载均衡做统一入口实现高可用,node节点同样通过统一入口实现高可用负载均衡,并接入master的统一入口形成整个集群的高可用。这里k8s只能调度计算资源给pod,比如cpu,内存等,但是对于pod来说可靠的存储也是非常重要的,这时候就要使用外部高可用分布式存储集群接入k8s来提供稳定的存储

高可用集群搭建

前提要求

  • 3台以上机器,操作系统 CentOS7.7以上64位系统
  • 硬件配置:2GB或更多RAM,2个CPU或更多CPU,硬盘30GB或更多
  • 集群中所有机器之间网络互通
  • 可以访问外网,需要拉取镜像
  • 禁止swap分区

软件详情

  • Kubernetes 1.16.2
  • calico 3.9
  • Docker 18.09.7
  • Nginx 1.6
  • Keepalived 1.3.5

机器详情

Master节点3

10.0.1.173 10.0.1.174 10.0.1.175

worker节点3

10.0.1.176 10.0.1.177 10.0.1.178

Master负载均衡节点 2

10.0.1.179 10.0.1.180 vip: 10.0.1.200

搭建步骤

高可用负载均衡创建四层负载

nginx搭建(搭建略,179,180机器都需安装配置)

k8s_server.conf文件内容如下,代理master的6443端口,创建并加入到nginx配置文件中

stream {
        upstream k8sapi {
            server 10.0.1.173:6443;
            server 10.0.1.174:6443;
            server 10.0.1.175:6443;
        }
        
        server {
            listen 6443;
            proxy_pass k8sapi;
        }
}

启动nginx监听端口

keepalived搭建

179,180机器执行命令安装:

yum install -y keepalived

179,180机器创建脚本文件并编辑内容 vim /tmp/check_k8s.sh

#!/bin/bash
# 判断nginx是否存活,如果非存活状态则停止keepalived使vip绑定到180
nginx_nums=`ps -ef |grep 'nginx: master'|grep -v grep|wc -l`
if [ $nginx_nums == 0  ]
then
     echo 'nginx is down'
     /etc/init.d/keepalived stop
else
    echo 'nginx is running'
fi

179机器 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 192.168.200.1
   smtp_connect_timeout 30
   router_id LVS_DEVEL
   vrrp_skip_check_adv_addr
   #vrrp_strict  # 注释掉为单播模式
   vrrp_garp_interval 0
   vrrp_gna_interval 0
}

vrrp_script check_web {
   script "/tmp/check_k8s.sh"          #表示将一个脚本信息赋值给变量check_web
   interval 2                                     #执行监控脚本的间隔时间
   # weight 2                                       #利用权重值和优先级进行运算,从而降低主服务优先级使之变为备服务器(建议先忽略)
}

vrrp_instance VI_1 {
    state MASTER
    interface eth0                 # 内网网卡名,如果是ens33则改为ens33
    virtual_router_id 51
    priority 100
    advert_int 1
    nopreempt  # 非抢占模式
    unicast_src_ip 10.0.1.179    # 单播的源地址,填本机地址
    unicast_peer {
       10.0.1.180             #集群其他机器地址,有多个地址则全写上
    }
    authentication {
        auth_type PASS
        auth_pass 1111
    }
    virtual_ipaddress {
        10.0.1.200
    }
    track_script {
        check_k8s
   } 
}

179机器 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 192.168.200.1
   smtp_connect_timeout 30
   router_id LVS_DEVEL
   vrrp_skip_check_adv_addr
   # vrrp_strict  # 注释掉为单播模式
   vrrp_garp_interval 0
   vrrp_gna_interval 0
}

vrrp_script check_web {
   script "/data/scripts/check_ngx.sh"          #表示将一个脚本信息赋值给变量check_web
   interval 2                                     #执行监控脚本的间隔时间
   weight 2                                       #利用权重值和优先级进行运算,从而降低主服务优先级使之变为备服务器(建议先忽略)
}

vrrp_instance VI_1 {
    state BACKUP
    interface eth0                 # 内网网卡名,如果是ens33则改为ens33
    virtual_router_id 51
    priority 90
    nopreempt  # 非抢占模式,主机上线后不会抢占为主
    unicast_src_ip 10.0.1.180    # 单播的源地址,填本机地址
    unicast_peer {
       10.0.1.179             #集群其他机器地址,有多个地址则全写上
    }
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass 1111
    }
    virtual_ipaddress {
        10.0.1.200
    }
    track_script {
        check_web
   }
}

179,180机器启动keepalived

systemctl start keepalived

k8s基础环境安装配置:

环境准备
三台主机都需要执行如下命令

关闭防火墙和selinux

systemctl stop firewalld

systemctl disable firewalld

sed -i 's/enforcing/disabled/' /etc/selinux/config

setenforce 0

关闭swap分区

swapoff -a    # 临时关闭

vim /etc/fstab # 注释到swap那一行  永久关闭

添加主机名与IP对应关系

cat >> /etc/hosts << EOF
10.0.1.173  k8s-master-173
10.0.1.174  k8s-master-174
10.0.1.175  k8s-master-175
10.0.1.176  k8s-node-176
10.0.1.177  k8s-node-177
10.0.1.178  k8s-node-178
10.0.1.200  api.k8s.com    # 这里第一个初始化的master(我这里是173)节点要设置成 127.0.0.1  api.k8s.com
EOF

各自修改主机名(从173-178各自顺序执行)

hostnamectl set-hostname k8s-master-173
hostnamectl set-hostname k8s-master-174
hostnamectl set-hostname k8s-master-175

hostnamectl set-hostname k8s-node-176
hostnamectl set-hostname k8s-node-177
hostnamectl set-hostname k8s-node-178

将桥接的IPv4流量传递到iptables的链

cat > /etc/sysctl.d/k8s.conf << EOF
net.ipv4.ip_forward = 1
net.ipv4.tcp_tw_recycle = 0
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
EOF

sysctl --system
内核升级

所有集群节点内核升级到最新的lt 内核升级参考 linux(centos7)内核升级

docker安装

所有集群节点安装docker

参考docker安装使用文档进行安装:docker部署搭建 (注意:这里docker最好安装19.03.9版本,防止集成到k8s出现bug,这里我出现过k8s监控服务无法获取资源信息,yum install -y docker-ce-19.03.9 docker-ce-cli-19.03.9 containerd.io)

Docker配置修改,设置cgroup驱动,这里用systemd

vim /etc/docker/daemon.json

{
  "graph": "/data/docker",
  "registry-mirrors": ["https://01xxgaft.mirror.aliyuncs.com"],
  "exec-opts": ["native.cgroupdriver=systemd"],
  "log-driver": "json-file",
  "log-opts": {
    "max-size": "100m"
  },
  "storage-driver": "overlay2"
}

重启docker

systemctl restart docker
安装kubeadm,kubelet和kubectl

添加k8s阿里云YUM软件源

所有集群节点执行

cat > /etc/yum.repos.d/kubernetes.repo << EOF[kubernetes]
name=Kubernetes
baseurl=https://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64
enabled=1
gpgcheck=0
repo_gpgcheck=0
gpgkey=https://mirrors.aliyun.com/kubernetes/yum/doc/yum-key.gpg https://mirrors.aliyun.com/kubernetes/yum/doc/rpm-package-key.gpg
EOF[kubernetes]

安装

yum install -y kubelet-1.16.2 kubeadm-1.16.2 kubectl-1.16.2
初始化集群

在第一个master节点也就是173上执行,因为是第一个初始化节点hosts要设置成 127.0.0.1 api.k8s.com

注意,这里–control-plane-endpoint后面的地址和上面添加hosts到vip200的地址对应,填那个域名 我这里是api.k8s.com

kubeadm init   --control-plane-endpoint "api.k8s.com:6443" --image-repository registry.aliyuncs.com/google_containers   --kubernetes-version v1.16.0   --service-cidr=10.140.0.0/16 --pod-network-cidr=10.240.0.0/16
获取执行结果

这里执行结果中,第一条 kubeadm join apiserver.k8s:6443 --token一共有三行的,就是初始化其他master节点的命令,先记住

第二条 kubeadm join apiserver.k8s:6443 --token一共有二行的,就是初始化其他worker节点的命令,先记住

初始化另外两个master节点

这里再执行上面三行初始化master的kubeadm join xxx 命令(我这里只是示例,命令根据你实际生成的复制去node节点执行)

kubeadm join api.k8s.com:6443 --token wjpzm3.1c8vmw9ivkm8bjdr     --discovery-token-ca-cert-hash sha256:7c95e8387e00fe1babb1456239571505abea100e99b4472b2bc63730826989aa     --control-plane --certificate-key 0ee85dd36c3630729b5ec8f187335f8f0a9af9b09441f75e28767d9440cd7124

初始化三个node节点

这里再执行上面两行初始化worker的kubeadm join xxx 命令(我这里只是示例,命令根据你实际生成的复制去node节点执行)

kubeadm join api.k8s.com:6443 --token wjpzm3.1c8vmw9ivkm8bjdr     --discovery-token-ca-cert-hash sha256:7c95e8387e00fe1babb1456239571505abea100e99b4472b2bc63730826989aa

安装cni网络插件(calico)

下载yaml文件

wget http://download.stisd.cn/k8s/calico-3.9.2.yaml

修改配置文件的网段为上面init pod-network-cidr的网段地址(必须正确否则会导致集群网络问题)

sed -i 's/192.168.0.0/10.240.0.0/g' calico.yaml

安装插件

kubectl apply -f calico-3.9.2.yaml

kubectl get pod --all-namespaces -o wide

搭建完成,查看集群内节点是否就绪

kubectl get node -o wide

测试kubernetes集群

在Kubernetes集群中创建一个pod,验证是否正常运行

创建一个pod,开放对外端口访问,这里会随机映射一个端口

kubectl create deployment nginx --image=nginx

kubectl expose deployment nginx --port=80 --type=NodePort

查看pod状态,必须是running状态而且ready是1,并查看nginx svc的80端口映射到了哪个端口

kubectl get pod,svc

访问任意机器的刚刚查看的映射端口,看看是否nginx已经运行

扩展学习

点是否就绪**

kubectl get node -o wide

测试kubernetes集群

在Kubernetes集群中创建一个pod,验证是否正常运行

创建一个pod,开放对外端口访问,这里会随机映射一个端口

kubectl create deployment nginx --image=nginx

kubectl expose deployment nginx --port=80 --type=NodePort

查看pod状态,必须是running状态而且ready是1,并查看nginx svc的80端口映射到了哪个端口

kubectl get pod,svc

访问任意机器的刚刚查看的映射端口,看看是否nginx已经运行

扩展学习

集群的ingress,接入分布式存储集群,yaml配置文件?后续文章详细讲解

如果觉得该文章对你有帮助的话请给我点个👍吧,感谢