k8s高可用集群搭建部署
简介
k8s普通搭建出来只是单master节点,如果该节点挂掉,则整个集群都无法调度,K8s高可用集群是用多个master节点加负载均衡节点组成,外层再接高可用分布式存储集群例如ceph集群,实现计算能力+存储能力的高可用,同时,etcd也可以独立出来用外部的etcd集群
架构详解
高可用架构图
架构详解
1.访问链路步骤:外部域名访问 ——> node集群负载均衡 ——>ingress ——> node集群 ——> serivce ——> pod内部元数据存储步骤:master集群 or node集群 ——> etcd集群
2.内部使用存储节点步骤:master集群 or node集群 ——> 高可用分布式存储集群
3.k8s的多台master集群被负载均衡做4层代理,做到了高可用,访问时只通过负载均衡访问
4.K8s的node节点接入master时通过master的负载均衡接入,就算挂掉一个master也无感知
5.K8s的node节点被外层负载均衡代理,pod启动后被service代理,service上的端口被ingress代理转发再到外层负载均衡,外部通过域名访问
6.K8s集群的重要元数据存储到外部etcd集群上,保障高可用和强一致性(这里我没使用外部)
7.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.9
Keepalived 1.3.5
master节点不能跟node节点安装在一起
机器详情
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机器都需安装配置)安装时候nginx要求至少1.9版本以上,并且开启--with-stream模块
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 8443; 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 } }
180机器 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 enablekeepalived
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
vi /etc/hostname 这里也要修改
将桥接的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
最好优化一下time_wait
netstat -n | awk '/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}'
vi /etc/sysctl.conf
#表示开启SYN Cookies。当出现SYN等待队列溢出时,启用cookies来处理,可防范少量SYN攻击,默认为0,表示关闭 net.ipv4.tcp_syncookies = 1 #表示开启重用。允许将TIME-WAIT sockets重新用于新的TCP连接,默认为0,表示关闭 net.ipv4.tcp_tw_reuse = 1 #表示开启TCP连接中TIME-WAIT sockets的快速回收,默认为0,表示关闭 net.ipv4.tcp_tw_recycle = 1 #表示如果套接字由本端要求关闭,这个参数决定了它保持在FIN-WAIT-2状态的时间 net.ipv4.tcp_fin_timeout=30
/sbin/sysctl -p
内核升级
所有集群节点内核升级到最新的lt 内核升级参考 linux(centos7)内核升级
shutdown -r now
docker安装
所有集群节点安装docker
参考docker安装使用文档进行安装:docker部署搭建
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=1 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
安装
yum install -y kubelet-1.23.6 kubeadm-1.23.6 kubectl-1.23.6
systemctl enable kubelet &&systemctl start kubelet
如果安装高版本1.24以上回报错
k8s初始化 报错Error getting node“ err=“node
原因是k8s 已经弃用了docker了,如果安装的kubelet kubeadm kubectl
是V1.24就会出现以上错误,安装的时候指定一下1.23版本
初始化集群
在第一个master节点也就是173上执行,因为是第一个初始化节点hosts要设置成 127.0.0.1 api.k8s.com
注意,这里–control-plane-endpoint后面的地址和上面添加hosts到vip200的地址对应,填那个域名 我这里是api.k8s.com,kubernetes-version对应安装版本
kubeadm init --control-plane-endpoint "api.k8s.com:8443" --image-repository registry.aliyuncs.com/google_containers --kubernetes-version v1.24.3 --service-cidr=172.17.0.0/16 --pod-network-cidr=172.30.0.0/16
如果出现错误:
kubeadm init 报错 ”unknown service runtime.v1alpha2.RuntimeService”
解决:
rm /etc/containerd/config.toml
systemctl restart containerd
安装失败后需要重新reset kubeadm reset
获取执行结果
这里执行结果中,第一条 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 https://github.com/xuwei777/xw_yaml/blob/main/calico-3.9.2.yaml
修改配置文件的网段为上面init pod-network-cidr的网段地址(必须正确否则会导致集群网络问题)
sed -i 's/192.168.0.0/10.240.0.0/g' calico-3.9.2.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已经运行