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 架构图:




使用rook在kubernetes集群中部署ceph_java


服务器规划

首先准备几台服务器,计划部署3台master,3台keepalivedhaproxy,为了节约服务器,我将keepalivedhaproxymaster一起部署,另外准备一台服务器作为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

环境初始化

注:下面的操作,三台服务器都要执行

  1. 检查操作系统的版本
# 此方式下安装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