kubernetes 高可用集群搭建
kubernetes 高可用集群搭建
概述
-
Kubernetes 作为容器集群系统, 通过健康检查+重启策略实现了 Pod 故障自我修复能力,通过调度算法实现将 Pod 分布式部署, 监控其预期副本数, 并根据 Node 失效状态自动在正常 Node 启动 Pod, 实现了应用层的高可用性。针对 Kubernetes 集群, 高可用性还应包含以下两个层面的考虑: Etcd 数据库的高可用性和 Kubernetes Master 组件的高可用性。 而 Etcd可以采用 3 个节点组建集群实现高可用, 本文将对 Master 节点高可用进行说明和实施。
-
Master 节点扮演着总控中心的角色, 通过不断与工作节点上的 Kubelet 和 kube-proxy 进行通信来维护整个集群的健康工作状态。 如果 Master 节点故障, 将无法使用 kubectl 工具或者 API 任何集群管理。
-
Master 节点主要有三个服务 kube-apiserver、 kube-controller-mansger 和 kubescheduler, 其中 kube-controller-mansger 和 kube-scheduler 组件自身通过选择机制已经实现了高可用, 所以 Master 高可用主要针对 kube-apiserver 组件, 而该组件是以 HTTP API 提供服务, 因此对他高可用与 Web 服务器类似, 增加负载均衡器对其负载均衡即可,并且可水平扩容。
多 Master 架构图:
服务器规划
首先准备几台服务器,计划部署3台master
,3台keepalived
和haproxy
,为了节约服务器,我将keepalived
和haproxy
和master
一起部署,另外准备一台服务器作为VIP
。服务器规划如下:
角色 | ip地址 |
---|---|
k8s-vip | 192.168.0.100 |
k8s-master01 | 192.168.0.11 |
k8s-master02 | 192.168.0.12 |
k8s-master03 | 192.168.0.13 |
环境初始化
注:下面的操作,三台服务器都要执行
- 检查操作系统的版本
# 此方式下安装kubernetes集群要求Centos版本要在7.5或之上
[root@k8s-master01 ~]# cat /etc/redhat-release
CentOS Linux release 7.5.1804 (Core)
2) 主机名解析
为了方便后面集群节点间的直接调用,在这配置一下主机名解析,企业中推荐使用内部DNS服务器
# 主机名成解析 编辑三台服务器的/etc/hosts文件,添加下面内容
192.168.0.100 vip
192.168.0.11 k8s-master01
192.168.0.12 k8s-master02
192.168.0.132 k8s-master03
3) 时间同步
kubernetes要求集群中的节点时间必须精确一致,这里直接使用chronyd服务从网络同步时间。
企业中建议配置内部的时间同步服务器
# 启动chronyd服务
[root@k8s-master01 ~]# systemctl start chronyd
# 设置chronyd服务开机自启
[root@k8s-master01 ~]# systemctl enable chronyd
# chronyd服务启动稍等几秒钟,就可以使用date命令验证时间了
[root@k8s-master01 ~]# date
4) 禁用iptables和firewalld服务
kubernetes和docker在运行中会产生大量的iptables规则,为了不让系统规则跟它们混淆,直接关闭系统的规则
# 1 关闭firewalld服务
[root@k8s-master01 ~]# systemctl stop firewalld
[root@k8s-master01 ~]# systemctl disable firewalld
# 2 关闭iptables服务
[root@k8s-master01 ~]# systemctl stop iptables
[root@k8s-master01 ~]# systemctl disable iptables
5) 禁用selinux
selinux是linux系统下的一个安全服务,如果不关闭它,在安装集群中会产生各种各样的奇葩问题
# 编辑 /etc/selinux/config 文件,修改SELINUX的值为disabled
# 注意修改完毕之后需要重启linux服务
SELINUX=disabled
6) 禁用swap分区
swap分区指的是虚拟内存分区,它的作用是在物理内存使用完之后,将磁盘空间虚拟成内存来使用
启用swap设备会对系统的性能产生非常负面的影响,因此kubernetes要求每个节点都要禁用swap设备
但是如果因为某些原因确实不能关闭swap分区,就需要在集群安装过程中通过明确的参数进行配置说明
# 编辑分区配置文件/etc/fstab,注释掉swap分区一行
# 注意修改完毕之后需要重启linux服务
UUID=455cc753-7a60-4c17-a424-7741728c44a1 /boot xfs defaults 0 0
/dev/mapper/centos-home /home xfs defaults 0 0
# /dev/mapper/centos-swap swap swap defaults 0 0
7)修改linux的内核参数
# 修改linux的内核参数,添加网桥过滤和地址转发功能
# 编辑/etc/sysctl.d/kubernetes.conf文件,添加如下配置:
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
net.ipv4.ip_forward = 1
# 重新加载配置
[root@k8s-master01 ~]# sysctl -p
# 加载网桥过滤模块
[root@k8s-master01 ~]# modprobe br_netfilter
# 查看网桥过滤模块是否加载成功
[root@k8s-master01 ~]# lsmod | grep br_netfilter
8)配置ipvs功能
在kubernetes中service有两种代理模型,一种是基于iptables的,一种是基于ipvs的
两者比较的话,ipvs的性能明显要高一些,但是如果要使用它,需要手动载入ipvs模块
# 1 安装ipset和ipvsadm
[root@k8s-master01 ~]# yum install ipset ipvsadmin -y
# 2 添加需要加载的模块写入脚本文件
[root@k8s-master01 ~]# cat <<EOF > /etc/sysconfig/modules/ipvs.modules
#!/bin/bash
modprobe -- ip_vs
modprobe -- ip_vs_rr
modprobe -- ip_vs_wrr
modprobe -- ip_vs_sh
modprobe -- nf_conntrack_ipv4
EOF
# 3 为脚本文件添加执行权限
[root@k8s-master01 ~]# chmod +x /etc/sysconfig/modules/ipvs.modules
# 4 执行脚本文件
[root@k8s-master01 ~]# /bin/bash /etc/sysconfig/modules/ipvs.modules
# 5 查看对应的模块是否加载成功
[root@k8s-master01 ~]# lsmod | grep -e ip_vs -e nf_conntrack_ipv4
9) 重启服务器
上面步骤完成之后,需要重新启动linux系统
[root@master01 ~]# reboot
keepalived+haproxy高可用
# 安装
[root@k8s-master01 ~]# yum -y install haproxy keepalived
# 备份keepalived配置文件
[root@k8s-master01 ~]# mv /etc/keepalived/keepalived.conf /etc/keepalived/keepalived.conf.bak
# 备份haproxy配置文件
[root@k8s-master01 ~]# mv /etc/haproxy/haproxy.cfg /etc/haproxy/haproxy.cfg.bak
编辑keepalived配置文件
[root@k8s-master01 ~]# cat > /etc/keepalived/keepalived.conf <<EOF
! Configuration File for keepalived
global_defs {
router_id k8s
script_user root //执行的用户
enable_script_security
}
vrrp_script check_haproxy {
script "killall -0 haproxy"
interval 3
weight -2
fall 10
rise 2
}
vrrp_instance VI_1 {
state MASTER
interface ens33 //网络ID ifcfg-ens33
virtual_router_id 51
priority 250
advert_int 1
authentication {
auth_type PASS
auth_pass ceb1b3ec013d66163d6ab
}
virtual_ipaddress {
192.168.0.100
}
track_script {
check_haproxy
}
}
EOF
备机1
[root@k8s-master01 ~]# cat > /etc/keepalived/keepalived.conf <<EOF
! Configuration File for keepalived
global_defs {
router_id k8s
script_user root
enable_script_security
}
vrrp_script check_haproxy {
script "killall -0 haproxy"
interval 3
weight -2
fall 10
rise 2
}
vrrp_instance VI_1 {
state BACKUP
interface ens33 //网络ID ifcfg-ens33
virtual_router_id 51
priority 200
advert_int 1
authentication {
auth_type PASS
auth_pass ceb1b3ec013d66163d6ab
}
virtual_ipaddress {
192.168.0.100
}
track_script {
check_haproxy
}
}
EOF
备机2
[root@k8s-master01 ~]# cat > /etc/keepalived/keepalived.conf <<EOF
! Configuration File for keepalived
global_defs {
router_id k8s
script_user root
enable_script_security
}
vrrp_script check_haproxy {
script "killall -0 haproxy"
interval 3
weight -2
fall 10
rise 2
}
vrrp_instance VI_1 {
state BACKUP
interface ens33 //网络ID ifcfg-ens33
virtual_router_id 51
priority 100
advert_int 1
authentication {
auth_type PASS
auth_pass ceb1b3ec013d66163d6ab
}
virtual_ipaddress {
192.168.0.100
}
track_script {
check_haproxy
}
}
EOF
编辑haproxy配置文件
[root@k8s-master01 ~]# cat > /etc/haproxy/haproxy.cfg << EOF
#---------------------------------------------------------------------
# Global settings
#---------------------------------------------------------------------
global
# to have these messages end up in /var/log/haproxy.log you will
# need to:
# 1) configure syslog to accept network log events. This is done
# by adding the '-r' option to the SYSLOGD_OPTIONS in
# /etc/sysconfig/syslog
# 2) configure local2 events to go to the /var/log/haproxy.log
# file. A line like the following can be added to
# /etc/sysconfig/syslog
#
# local2.* /var/log/haproxy.log
#
log 127.0.0.1 local2
chroot /var/lib/haproxy
pidfile /var/run/haproxy.pid
maxconn 4000
user haproxy
group haproxy
daemon
# turn on stats unix socket
stats socket /var/lib/haproxy/stats
#---------------------------------------------------------------------
# common defaults that all the 'listen' and 'backend' sections will
# use if not designated in their block
#---------------------------------------------------------------------
defaults
mode http
log global
option httplog
option dontlognull
option http-server-close
option forwardfor except 127.0.0.0/8
option redispatch
retries 3
timeout http-request 10s
timeout queue 1m
timeout connect 10s
timeout client 1m
timeout server 1m
timeout http-keep-alive 10s
timeout check 10s
maxconn 3000
#---------------------------------------------------------------------
# kubernetes apiserver frontend which proxys to the backends
#---------------------------------------------------------------------
frontend kubernetes-apiserver
mode tcp
bind *:16443
option tcplog
default_backend kubernetes-apiserver
#---------------------------------------------------------------------
# round robin balancing between the various backends
#---------------------------------------------------------------------
backend kubernetes-apiserver
mode tcp
balance roundrobin
server master1 192.168.0.11:6443 check
server master2 192.168.0.12:6443 check
server master3 192.168.0.113:6443 check
#---------------------------------------------------------------------
# collection haproxy statistics message
#---------------------------------------------------------------------
listen stats
bind *:1080
stats auth admin:admin
stats refresh 5s
stats realm HAProxy
stats uri admin
EOF
开启服务
systemctl enable keepalived
systemctl start keepalived
systemctl status keepalived
systemctl enable haproxy
systemctl start haproxy
systemctl status haproxy
安装docker
# 1 切换镜像源
[root@k8s-master01 ~]# wget https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo -O /etc/yum.repos.d/docker-ce.repo
# 2 查看当前镜像源中支持的docker版本
[root@k8s-master01 ~]# yum list docker-ce --showduplicates
# 3 安装docker 19.03.9 docker-ce 19.03.9
[root@k8s-master01 ~]# yum install -y docker-ce-19.03.9-3 docker-ce-cli-19.03.9 containerd.io
# 4 添加一个配置文件
# Docker在默认情况下使用的Cgroup Driver为cgroupfs,而kubernetes推荐使用systemd来代替cgroupfs
[root@k8s-master01 ~]# mkdir /etc/docker
[root@k8s-master01 ~]# cat <<EOF > /etc/docker/daemon.json
{
"exec-opts": ["native.cgroupdriver=systemd"],
"registry-mirrors": ["https://kn0t2bca.mirror.aliyuncs.com"],
"log-driver": "json-file",
"log-opts": {
"max-size": "100m"
},
"storage-driver": "overlay2",
"storage-opts": [
"overlay2.override_kernel_check=true"
]
}
EOF
# 5 启动docker
[root@k8s-master01 ~]# systemctl restart docker
[root@k8s-master01 ~]# systemctl enable docker
# 6 检查docker状态和版本
[root@k8s-master01 ~]# docker version
安装k8s核心
# 配置K8S的yum源
[root@k8s-master01 ~]# cat <<EOF > /etc/yum.repos.d/kubernetes.repo
[kubernetes]
name=Kubernetes
baseurl=http://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64
nabled=1
gpgcheck=1
repo_gpgcheck=1
gpgkey=http://mirrors.aliyun.com/kubernetes/yum/doc/yum-key.gpg
http://mirrors.aliyun.com/kubernetes/yum/doc/rpm-package-key.gpg
EOF
# 卸载旧版本
[root@k8s-master01 ~]# yum remove -y kubelet kubeadm kubectl
# 查看可以安装的版本
[root@k8s-master01 ~]# yum list kubelet --showduplicates | sort -r
# 安装kubelet、kubeadm、kubectl 指定版本
[root@k8s-master01 ~]# yum install -y kubelet-1.20.0 kubeadm-1.20.0 kubectl-1.20.0
# 开机启动kubelet
[root@k8s-master01 ~]# systemctl enable kubelet && systemctl start kubelet
初始化节点
拉取镜像
三台都需要执行
############下载核心镜像 kubeadm config images list:查看需要哪些镜像###########
####封装成images.sh文件
#!/bin/bash
images=(
kube-apiserver:v1.20.0
kube-proxy:v1.20.0
kube-controller-manager:v1.20.0
kube-scheduler:v1.20.0
coredns:v1.8.0
etcd:3.4.13-0
pause:3.4.1
)
for imageName in ${images[@]} ; do
docker pull registry.cn-hangzhou.aliyuncs.com/lfy_k8s_images/$imageName
done
#####封装结束
[root@k8s-master01 ~] chmod +x images.sh && ./images.sh
选择其中的一台进行初始化
########kubeadm init 一个master########################
[root@k8s-master01 ~]# kubeadm init --config=kubeadm-config.yaml --upload-certs | tee kubeadm-init.log
###完成之后根据提示执行如下命令
[root@k8s-master01 ~]# mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
kubeadm-config.yaml的文件内容如下:
此时的kubectl命令只有master01可以使用要想所有master节点都可以使用则需要将master01中的$HOME/.kube目录复制给其他master
[root@k8s-master01 ~]# scp -r $HOME/.kube k8s-master02:$HOME/
[root@k8s-master01 ~]# scp -r $HOME/.kube k8s-master03:$HOME/
其他master节点加入
[root@k8s-master01 ~]# kubeadm join 192.168.0.100:6443 --token abcdef.0123456789abcdef \
--discovery-token-ca-cert-hash sha256:37041e2b8e0de7b17fdbf73f1c79714f2bddde2d6e96af2953c8b026d15000d8 \
--control-plane --certificate-key 8d3f96830a1218b704cb2c24520186828ac6fe1d738dfb11199dcdb9a10579f8
其中查看方式如下:
# 获取token --discovery-token-ca-cert-hash
[root@k8s-master01 ~]# openssl x509 -in /etc/kubernetes/pki/ca.crt -noout -pubkey | openssl rsa -pubin -outform DER 2>/dev/null | sha256sum | cut -d' ' -f1
# 获取证书的key certificate-key
[root@k8s-master01 ~]# kubeadm init phase upload-certs --upload-certs