今日天气
  1. 博客/

使用 Kube-Vip 部署 高可用的 Kubernetes 集群

·1523 字·4 分钟· ·
k8s kube-vip containerd kubeadm
Johny
作者
Johny
熟练的 云原生搬砖师
Table of Contents

前言
#

在以前我们在私有环境下创建 Kubernetes 集群时,我们需要准备一个硬件/软件的 负载均衡器 来创建多控制平面集群,更多的情况下我们会选择使用 HAProxy + Keepalived 来实现这个功能。一般情况下我们创建2个负载均衡器的虚拟机,然后分配一个 VIP,然后使用 VIP 为负载均衡器提供服务,通过 VIP 将流量重定向到后端的某个 Kubernetes 控制器平面节点上。如下图所示:

20210616142006

接下来我们再来看看如果使用 kube-vip 的话会怎样呢?

20210616142207

可以看到,这样实现后使得架构变得更为的优雅,少了之前架构中 负载均衡 服务器的使用。

环境说明
#

  • 节点 说明

    IP地址操作系统内核版本
    192.168.8.81 (master-01)CentOS Linux release 7.9.20095.4.128-1.el7.elrepo.x86_64
    192.168.8.82 (master-02)CentOS Linux release 7.9.20095.4.128-1.el7.elrepo.x86_64
    192.168.8.83 (master-03)CentOS Linux release 7.9.20095.4.128-1.el7.elrepo.x86_64
    192.168.8.84 (node-01)CentOS Linux release 7.9.20095.4.128-1.el7.elrepo.x86_64
    192.168.8.85 (node-02)CentOS Linux release 7.9.20095.4.128-1.el7.elrepo.x86_64
    192.168.8.86 (node-03)CentOS Linux release 7.9.20095.4.128-1.el7.elrepo.x86_64
    192.168.8.100 (kube-vip 虚拟ip)
  • 软件说明

    名称版本
    kubernetesv1.20.5
    containerdv1.4.6
    rancherv2.4.15

集群部署
#

如下所示中的 节点初始化 操作,需要在所有的节点多进行操作一次。

节点初始化
#

  • 添加 hosts 记录

    cat >> /etc/hosts << EOF
    192.168.8.81 master-01
    192.168.8.82 master-02
    192.168.8.83 master-03
    192.168.8.84 node-01
    192.168.8.85 node-02
    192.168.8.86 node-03
    EOF
    
  • 关闭 swap

    swapoff -a
    sed -i 's/.*swap.*/#&/' /etc/fstab
    
  • 更改hostname

    hostnamectl set-hostname xxx # hostnamectl set-hostname master-01
    
  • 关闭防火墙

    systemctl stop firewalld
    systemctl disable firewalld
    
  • 关闭 selinux

    sed -i 's#SELINUX=enforcing#SELINUX=disabled#g' /etc/selinux/config
    grep -i  ^selinux= /etc/selinux/config 
    setenforce 0
    getenforce
    
  • 更新内核

    参考 文档步骤

  • 开启内核参数

    sudo yum install -y conntrack ipvsadm ipset jq sysstat curl iptables
    
    
    cat <<EOF | sudo tee /etc/modules-load.d/containerd.conf
    overlay
    br_netfilter
    EOF
    
    chmod a+x /etc/rc.local 
    
    cat <<EOF | sudo tee /etc/sysctl.d/99-kubernetes-cri.conf
    net.bridge.bridge-nf-call-iptables  = 1
    net.ipv4.ip_forward                 = 1
    net.bridge.bridge-nf-call-ip6tables = 1
    EOF
    
    modprobe overlay
    modprobe br_netfilter  # 执行操作,使其生效
    
    cat > /etc/rc.local << EOF
    modprobe overlay
    modprobe br_netfilter
    EOF
    
    sysctl -p /etc/sysctl.d/k8s.conf
    
  • 开启内核 ipvs 特性

    cat > /etc/sysconfig/modules/ipvs.modules <<EOF
    #!/bin/bash
    modprobe -- ip_vs
    modprobe -- ip_vs_rr
    modprobe -- ip_vs_wrr
    modprobe -- ip_vs_sh
    modprobe -- nf_conntrack_ipv4
    EOF
    
    chmod 755 /etc/sysconfig/modules/ipvs.modules \
    && bash /etc/sysconfig/modules/ipvs.modules \
    && lsmod | grep -e ip_vs -e nf_conntrack_ipv4
    
  • 安装 containerd ,设置参数优化

    sudo yum install -y yum-utils device-mapper-persistent-data lvm2 \
    && sudo yum-config-manager --add-repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo \
    && sudo yum makecache fast
    
    yum install containerd -y
    
    containerd config default > /etc/containerd/config.toml
    
    sed -i "s#k8s.gcr.io#registry.cn-hangzhou.aliyuncs.com/google_containers#g"  /etc/containerd/config.toml
    sed -i '/containerd.runtimes.runc.options/a\ \ \ \ \ \ \ \ \ \ \ \ SystemdCgroup = true' /etc/containerd/config.toml
    sed -i "s#https://registry-1.docker.io#https://registry.cn-hangzhou.aliyuncs.com#g"  /etc/containerd/config.toml
    
    systemctl daemon-reload
    systemctl enable containerd
    systemctl restart containerd
    
  • 安装 crictl 客户端

    此工具为 containerd client 端使用工具

    wget https://github.com/kubernetes-sigs/cri-tools/releases/download/v1.21.0/crictl-v1.21.0-linux-amd64.tar.gz
    
    sudo tar zxvf crictl-v1.21.0-linux-amd64.tar.gz -C /usr/local/bin
    
    cat > /etc/crictl.yaml << EOF
    runtime-endpoint: unix:///run/containerd/containerd.sock
    image-endpoint: unix:///run/containerd/containerd.sock
    timeout: 10
    debug: true
    EOF
    
  • 安装 kubernetes 部署组件

    cat <<EOF > /etc/yum.repos.d/kubernetes.repo
    [kubernetes]
    name=Kubernetes
    baseurl=http://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64
    enabled=1
    gpgcheck=0
    repo_gpgcheck=0
    gpgkey=http://mirrors.aliyun.com/kubernetes/yum/doc/yum-key.gpg http://mirrors.aliyun.com/kubernetes/yum/doc/rpm-package-key.gpg
    EOF
    
    yum list kubeadm --showduplicates | sort -r # 打印查看所有 kubeadm 版本
    
    yum install -y kubeadm-1.20.5 kubelet-1.20.5 kubectl-1.20.5
    
    systemctl enable kubelet  # 安装完成后 添加kebelet服务自启
    

    可选操作,配置 kubectl 命名补全功能

    yum install -y bash-completion
    source /usr/share/bash-completion/bash_completion
    source <(kubectl completion bash)
    echo "source <(kubectl completion bash)" >> ~/.bashrc
    

kubernetes 集群初始化
#

使用 kubeadm 首先 初始化 master-01 节点,操作的步骤如下所示

生成 kubeadm 初始化文件
#

执行初始化操作时, 控制平面地址因为填写了 vip 地址,如果 kube-vip 还未进行部署时,kubeadm init 操作将一直处于 pending 状态,直至超时,这里需要在执行初始化操作后,就立即 执行部署 kube-vip 操作。

kubeadm config print init-defaults > init_kubelet.yaml # 生成 默认的初始化配置文件

# 下面为 更改后的初始化配置文件
cat init_kubelet.yaml
apiVersion: kubeadm.k8s.io/v1beta2
bootstrapTokens:
- groups:
  - system:bootstrappers:kubeadm:default-node-token
  token: abcdef.0123456789abcdef
  ttl: 24h0m0s
  usages:
  - signing
  - authentication
kind: InitConfiguration
nodeRegistration:
  criSocket: /run/containerd/containerd.sock
---
apiServer:
  timeoutForControlPlane: 4m0s
apiVersion: kubeadm.k8s.io/v1beta2
certificatesDir: /etc/kubernetes/pki
clusterName: kubernetes
controllerManager: {}
dns:
  type: CoreDNS
etcd:
  local:
    dataDir: /var/lib/etcd
imageRepository: registry.cn-hangzhou.aliyuncs.com/google_containers
kind: ClusterConfiguration
controlPlaneEndpoint: "192.168.8.100:6443"
kubernetesVersion: v1.20.5
networking:
  dnsDomain: cluster.local
  serviceSubnet: 10.96.0.0/12
scheduler: {}
---
apiVersion: kubelet.config.k8s.io/v1beta1
kind: KubeletConfiguration
cgroupDriver: systemd
#protectKernelDefaults: false
---
apiVersion: kubeproxy.config.k8s.io/v1alpha1
kind: KubeProxyConfiguration
mode: ipvs

kubeadm init --config init_kubelet.yaml --upload-certs 

这里记录一个踩坑点,就是配置文件中所示的 “protectKernelDefaults”,添加了这个配置项后,会出现 kubelet 奔溃问题,将其注释掉后问题就解决了,下面图片中为官方文档中给出的注解。

image-20210624115549902

部署 kube-vip ,添加静态 pod 启动文件
#

kubelet 静态文件夹目录为 /etc/kubernetes/manifests/,我们只需将对应的 yaml 文件生成至这个下面即可,这个下面的 pod 生命周期将交给 kubelet 进行管理。

export VIP=192.168.8.100 # vip 地址
export INTERFACE=eth0
ctr image pull docker.io/plndr/kube-vip:0.3.1
mkdir -p /etc/kubernetes/manifests
ctr run --rm --net-host docker.io/plndr/kube-vip:0.3.1 vip \
/kube-vip manifest pod \
--interface $INTERFACE \
--vip $VIP \
--controlplane \
--services \
--arp \
--leaderElection | tee  /etc/kubernetes/manifests/kube-vip.yaml

image-20210624142906470

image-20210624142917982

image-20210624142932603

安装 CNI 网络插件
#

初始化集群后,集群还需要安装 一下 网络插件,才能算是正式可用,cni 插件有许多,这里已 cilium 做示例。

curl https://raw.githubusercontent.com/helm/helm/master/scripts/get-helm-3 | bash
helm repo add cilium https://helm.cilium.io/
helm install cilium cilium/cilium --version 1.9.4 \
--namespace kube-system

image-20210624144753427

添加 其他两台控制节点
#

  • 将初始化生成的证书 copy 至其余的两台控制平面节点

    ssh-keygen  # 生成公私钥文件 
    
    ssh-copy-id root@"node_id"  # 设置免密钥
    
    USER=root # 可定制
    CONTROL_PLANE_IPS="192.168.8.82 192.168.8.83"
    
    for host in ${CONTROL_PLANE_IPS}; do
    		ssh "${USER}"@$host "mkdir -p /etc/kubernetes/pki/ /etc/kubernetes/pki/etcd/"
        scp /etc/kubernetes/pki/ca.crt "${USER}"@$host:/etc/kubernetes/pki/
        scp /etc/kubernetes/pki/ca.key "${USER}"@$host:/etc/kubernetes/pki/
        scp /etc/kubernetes/pki/sa.key "${USER}"@$host:/etc/kubernetes/pki/
        scp /etc/kubernetes/pki/sa.pub "${USER}"@$host:/etc/kubernetes/pki/
        scp /etc/kubernetes/pki/front-proxy-ca.crt "${USER}"@$host:/etc/kubernetes/pki/
        scp /etc/kubernetes/pki/front-proxy-ca.key "${USER}"@$host:/etc/kubernetes/pki/
        scp /etc/kubernetes/pki/etcd/ca.crt "${USER}"@$host:/etc/kubernetes/pki/etcd/
        scp /etc/kubernetes/pki/etcd/ca.key "${USER}"@$host:/etc/kubernetes/pki/etcd/
    done
    

    image-20210624145312992

    image-20210624145345436

  • 控制平面节点,执行加入集群操作

    kubeadm join 192.168.8.100:6443 --token hash.hash\
         --discovery-token-ca-cert-hash sha256:hash \
         --control-plane --certificate-key key
    

    master-02 加入集群

    image-20210624145645907

    master-03 加入集群

    image-20210624145724332

刚才加入集群的 master 节点,不要忘记将 kube-vip 的静态 pod 进行创建,这样才能确保集群拥有了 HA 属性 。执行上面的 kube-vip 部署步骤

image-20210624150202416

image-20210624150219305

image-20210624150310623

添加 worker 节点
#

kubeadm join 192.168.8.100:6443 --token hash.hash\
    --discovery-token-ca-cert-hash sha256:hash

image-20210624150546402

image-20210624150607013

可选优化
#

去掉 master 节点的污点
#

如在生产环境时,请进行斟酌后再进行相关的操作。

kubectl taint nodes --all node-role.kubernetes.io/master-

参考文档
#

https://zhuanlan.zhihu.com/p/359719736

https://www.qikqiak.com/post/use-kube-vip-ha-k8s-lb/

https://inductor.medium.com/say-good-bye-to-haproxy-and-keepalived-with-kube-vip-on-your-ha-k8s-control-plane-bb7237eca9fc

ToDo
#

相关文章

Kubeadm 部署 kubernetes-v1.19.x 集群
·2153 字·5 分钟·
k8s kubeadm v1.19.x install
使用 helm 在 Kubernetes 中部署 Nexus 私服
·2270 字·5 分钟·
k8s devops helm nexus3
Kaniko Docker 镜像构建 初体验
·483 字·1 分钟·
k8s Kaniko docker install
Rancher 导入集群提示 Scheduler & Controller 不健康问题修复
·884 字·2 分钟·
k8s rancher kubekey
在 Kubernetes 中使用 localPv 部署 Gitlab
·1040 字·3 分钟·
k8s devops ingress gitlab ci-cd localpv postgres redis
使用 Helm 部署 Spinnaker 持续部署(CD)平台
·2781 字·6 分钟·
devops k8s helm spinnaker ci-cd