The k8s construction of high availability and load balancing

1. Environmental description

This method is used in production environments
Highly available tool: kept
Load balancing: haproxy (or nginx, lvs)
The versions of docker, kubedm and kubelet programs are shown in the figure below:


Virtual machine:

2. Main process steps

System environment configuration - kernel upgrade to above 4.19 - docker installation ----- kubedm installation ----- keepalived installation of high availability components ----- haproxy installation configuration ----- kubedm initialization ----- adding master or node nodes

3. Detailed steps

All nodes need to operate until initialization:
Step 1: change the host configuration file:

cat /etc/hosts
 
 127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4
::1         localhost localhost.localdomain localhost6 localhost6.localdomain6
192.168.247.100 k8s-master1
192.168.247.101 k8s-master2
192.168.247.103 k8s-node1
192.168.247.90  k8s-master-vip

Step 2: close the firewall, selinux, swap, etc. on all nodes:

systemctl disable --now firewalld
systemctl disable --now NetworkManager

#selinux   /etc/sysconfig/selinux
SELINUX=disabled

swapoff -a && sysctl -w vm.swappiness=0
#/etc/fstab comment out the swap partition

Step 3: configure ntp time synchronization for all hosts:

yum install -y ntp

Configuration on server master1:

driftfile /var/lib/ntp/drift

restrict default nomodify notrap nopeer noquery  #nomodify is not allowed to modify the server time. notrap is not allowed to log in to noquery. nopeer does not provide client time query. nopeer is used to prevent the host from trying to peer with the server
#The default is to reject all clients, and control the connectable clients through restrict

restrict 127.0.0.1 #Allow any operation on this machine
restrict ::1

restrict 192.168.247.0 mask 255.255.255.0 nomodify notrap  #Change this to the network segment to which your virtual machine belongs
#Allow the host in the 192.168.247.0 network segment to operate operations other than modifying the server time and login

server 210.72.145.44 prefer  #National Time Service Center 
server 0.cn.pool.ntp.org    
server 1.cn.pool.ntp.org

server 127.127.1.0   #Local time

restrict 0.cn.pool.ntp.org nomodify notrap noquery
restrict 1.cn.pool.ntp.org nomodify notrap noquery
restrict 210.72.145.44 nomodify notrap noquery

fudge 127.127.1.0 stratum 10    

includefile /etc/ntp/crypto/pw

keys /etc/ntp/keys

disable monitor

master2 and node1 configuration:

driftfile /var/lib/ntp/drift

restrict default nomodify notrap nopeer noquery

restrict 127.0.0.1 
restrict ::1
restrict 192.168.247.100 nomodify notrap noquery

server 192.168.247.100

includefile /etc/ntp/crypto/pw

keys /etc/ntp/keys

disable monitor

Then start ntp service and set startup:

systemctl enable --now ntpd

Modify limit of all nodes:

vim /etc/security/limits.conf
# Add the following at the end
* soft nofile 655360
* hard nofile 131072
* soft nproc 655350
* hard nproc 655350
* soft memlock unlimited
* hard memlock unlimited

master1 configures ssh password free login to other nodes. Other nodes are available or not:

ssh-keygen -t rsa
for i in k8s-master1 k8s-master2 k8s-node1;do ssh-copy-id -i .ssh/id_rsa.pub $i;done

Step 4: replace the repo source. You can choose 163 mirror source

Step 5: add kubernetes repo source and execute the following steps:

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

Step 6: install the required basic software:

yum install -y yum-utils device-mapper-persistent-data lvm2
yum install wget jq psmisc vim net-tools telnet yum-utils device-mapper-persistent-data lvm2 -y

Step 6: after restarting, start upgrading the kernel, download the kernel rpm package, download the network disk: link:

https://pan.baidu.com/s/14Pg_LllldqTrLZaAlbqP3A
Extraction code: 5i2e


Upgrading the kernel is also required for all machines. Transfer these two files to all nodes.

Install kernel:

cd /root && yum localinstall -y kernel-ml*

Modify the kernel startup sequence and execute:

grub2-set-default  0 && grub2-mkconfig -o /etc/grub2.cfg

grubby --args="user_namespace.enable=1" --update-kernel="$(grubby --default-kernel)"

Restart and check the kernel version:

grubby --default-kernel
uname -r

Step 7: install ipvsadm and module

yum install ipvsadm ipset sysstat conntrack libseccomp -y

Execute separately:

modprobe -- ip_vs
modprobe -- ip_vs_rr
modprobe -- ip_vs_wrr
modprobe -- ip_vs_sh
modprobe -- nf_conntrack

Execution:

vim /etc/modules-load.d/ipvs.conf 
	# Add the following
ip_vs
ip_vs_lc
ip_vs_wlc
ip_vs_rr
ip_vs_wrr
ip_vs_lblc
ip_vs_lblcr
ip_vs_dh
ip_vs_sh
ip_vs_fo
ip_vs_nq
ip_vs_sed
ip_vs_ftp
ip_vs_sh
nf_conntrack
ip_tables
ip_set
xt_set
ipt_set
ipt_rpfilter
ipt_REJECT
ipip

Restart service:

systemctl enable --now systemd-modules-load.service

Kernel parameters for opening k8s:

cat <<EOF > /etc/sysctl.d/k8s.conf
net.ipv4.ip_forward = 1
net.bridge.bridge-nf-call-iptables = 1
net.bridge.bridge-nf-call-ip6tables = 1
fs.may_detach_mounts = 1
vm.overcommit_memory=1
vm.panic_on_oom=0
fs.inotify.max_user_watches=89100
fs.file-max=52706963
fs.nr_open=52706963
net.netfilter.nf_conntrack_max=2310720

net.ipv4.tcp_keepalive_time = 600
net.ipv4.tcp_keepalive_probes = 3
net.ipv4.tcp_keepalive_intvl =15
net.ipv4.tcp_max_tw_buckets = 36000
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_max_orphans = 327680
net.ipv4.tcp_orphan_retries = 3
net.ipv4.tcp_syncookies = 1
net.ipv4.tcp_max_syn_backlog = 16384
net.ipv4.ip_conntrack_max = 65536
net.ipv4.tcp_max_syn_backlog = 16384
net.ipv4.tcp_timestamps = 0
net.core.somaxconn = 16384
EOF
sysctl --system

Restart again.
Check whether the module is loaded:

lsmod | grep --color=auto -e ip_vs -e nf_conntrack



Step 8: install docker
Add docker source repo:

yum-config-manager \
    --add-repo \
    https://download.docker.com/linux/centos/docker-ce.repo

Install directly using yum. The default version is the latest version:

yum install -y docker-ce docker-ce-cli containerd.io

There is a kernel driver problem here. kubelet now uses systemd, so we must change the docker driver to systemd.
View docker driver:

docker info |grep Cgroup 

Modification:

cat > /etc/docker/daemon.json <<EOF
{
  "exec-opts": ["native.cgroupdriver=systemd"]
}
EOF

Set and start docker:

systemctl daemon-reload && systemctl enable --now docker

Step 9: install k8s
The installation is relatively simple. After configuring the kuberneter warehouse, you can use yum directly:

yum install -y kubeadm

#When installing kubedm, kubelet, kubectl and other packages will be installed automatically

Change k8s default warehouse address to domestic address:

cat >/etc/sysconfig/kubelet<<EOF
KUBELET_EXTRA_ARGS="--cgroup-driver=systemd --pod-infra-container-image=registry.cn-hangzhou.aliyuncs.com/google_containers/pause-amd64:3.2"
EOF

To set Kubelet to boot automatically:

systemctl daemon-reload
systemctl enable --now kubelet

Step 10: keepalived installation configuration

yum install -y keepalived

master1 configuration:
/etc/keepalived/keepalived.conf

! Configuration File for keepalived

global_defs {
   router_id 1  #Unique identification
}

vrrp_script chk_apiserver {
   script "/etc/keepalived/check_apiserver.sh"
   interval 5
   
}

vrrp_instance VI_1 {
    state MASTER  #Master node
    interface ens33  #Change this place to your de network card name 
    virtual_router_id 51
    priority 100   #The higher the weight value, the better
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass 1111
    }
    virtual_ipaddress {
        192.168.247.90
    
     }
    track_script {
        chk_apiserver

     } 
}

master2:
vim /etc/keepalived/keepalived.conf

! Configuration File for keepalived

global_defs {
   router_id 1  
}

vrrp_script chk_apiserver {
   script "/etc/keepalived/check_apiserver.sh"
   interval 5
   
}

vrrp_instance VI_1 {
    state BACKUP   #Change this to backup
    interface ens33
    virtual_router_id 51
    priority 90
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass 1111
    }
    virtual_ipaddress {
        192.168.247.90
    
     }
    track_script {
        chk_apiserver

     }
    
}

Both masters 1 and 2 need to configure the monitoring script chk_apiserver:
/etc/keepalived/check_apiserver.sh

 #!/bin/bash

err=0
for k in $(seq 1 3)
do
    check_code=$(pgrep haproxy)
    if [[ $check_code == "" ]]; then
        err=$(expr $err + 1)
        sleep 1
        continue
    else
        err=0
        break
    fi
done

if [[ $err != "0" ]]; then
    echo "systemctl stop keepalived"
    /usr/bin/systemctl stop keepalived
    exit 1
else
    exit 0
fi

Grant Execution Authority:

chmod +x /etc/keepalived/check_apiserver.sh

Set startup and start the service:

systemctl enable --now keepalived

Step 11: deploy haproxy
The contents of files deployed by master1 and master2 are the same

yum install -y haproxy

Configuration file / etc / haproxy / haproxy cfg :

global
  maxconn  2000
  ulimit-n  16384
  log  127.0.0.1 local0 err
  stats timeout 30s

defaults
  log global
  mode  http
  option  httplog
  timeout connect 5000
  timeout client  50000
  timeout server  50000
  timeout http-request 15s
  timeout http-keep-alive 15s

frontend monitor-in
  bind *:33305
  mode http
  option httplog
  monitor-uri /monitor

frontend k8s-master
  bind 0.0.0.0:16443
  bind 127.0.0.1:16443
  mode tcp
  option tcplog
  tcp-request inspect-delay 5s
  default_backend k8s-master

backend k8s-master
  mode tcp
  option tcplog
  option tcp-check
  balance roundrobin
  default-server inter 10s downinter 5s rise 2 fall 2 slowstart 60s maxconn 250 maxqueue 256 weight 100
  server k8s-master1	192.168.247.100:6443  check
  server k8s-master2	192.168.247.101:6443  check

The host 16443 port is mapped to the 6443 of the backend 192.168.247.100 and 101, which is the port of the apiserver.

Step 12: cluster initialization
This is mainly to join another master and add nodes through the join after successfully initializing one master. You don't have to perform init initialization all the time. I originally thought that each master performs init initialization, and the back-end agent seems to work, but the node node also needs to be added once, which is very troublesome. k8s has a unique addition method. Join can become a master, and there is information about node nodes.
Write yaml file:
vim new.yaml

apiVersion: kubeadm.k8s.io/v1beta3
bootstrapTokens:
- groups:
  - system:bootstrappers:kubeadm:default-node-token
  token: 7t2weq.bjbawausm0jaxury
  ttl: 24h0m0s
  usages:
  - signing
  - authentication
kind: InitConfiguration
localAPIEndpoint:
  advertiseAddress: 192.168.247.100   #This is the local ip address
  bindPort: 6443   Local machine apiserver port
nodeRegistration:
  criSocket: /var/run/dockershim.sock
  imagePullPolicy: IfNotPresent
  name: k8s-master1
  taints:
  - effect: NoSchedule
    key: node-role.kubernetes.io/master
---
apiServer:
  certSANs:
  - 192.168.247.90   #Here is the vip address generated by keepalived
  timeoutForControlPlane: 4m0s
apiVersion: kubeadm.k8s.io/v1beta3
certificatesDir: /etc/kubernetes/pki
clusterName: kubernetes
controlPlaneEndpoint: 192.168.247.90:16443   #Front end address used for load balancing
controllerManager: {}
dns: {}
etcd:
  local:
    dataDir: /var/lib/etcd
imageRepository: registry.aliyuncs.com/google_containers   #Mirror warehouse address
kind: ClusterConfiguration
kubernetesVersion: v1.23.1   #kubelet version
networking:
  dnsDomain: cluster.local
  podSubnet: 172.168.0.0/12   #Define pod network segment
  serviceSubnet: 10.96.0.0/12   #Define service segment
scheduler: {}

This file should be given to each server. Although it is only used for 192.168.247.100 initialization, it is necessary for each machine to pull the image. The image warehouse in this file can obtain the image.

If this configuration file is outdated, you can update it:

kubeadm config migrate --old-config new.yaml --new-config new2.yaml

Now I use new Yaml file to obtain the required images for three images. Other servers do not need to change this yaml file anywhere:

kubeadm config images pull --config /root/new.yaml

If there is an error - v5 or something, the image address cannot be accessed. You can try two more available warehouse image addresses:

daocloud.io/daocloud
registry.cn-hangzhou.aliyuncs.com/google_containers

#Directly replace registry aliyuncs. com/google_ Containers is the address

After pulling down, only master1 needs to be operated:
init initialization:

kubeadm init --config /root/new.yaml  --upload-certs

If it fails, there may be two reasons: the yaml file is not configured correctly, especially the ip address. Also, docker and kubelet have different drivers.

After success, just follow the command given by it. It includes the join method of master and the add method of node. Remember to save the join command

master1 execution:

mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config

The initialization of master1 has been completed. Next, start kubelet and add the following three machines:

systemctl enable --now kubelet

Step 13: add master2 and node1 to the cluster
master2: enter the command prompt after the initialization of master1

kubeadm join 192.168.247.90:16443 --token 7t2weq.bjbawausm0jaxury \
	--discovery-token-ca-cert-hash sha256:7e2075c5cccf6b2dc6a00b05f5b1520929307f3e1be29d5a97ca2784789c4363 \
	--control-plane --certificate-key 0adf0a50a83b02423a084983e7add740ea6420a6f72edebad35921940d2f5ffe

Then, as the master node, it also performs:

mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config

node1:

kubeadm join 192.168.247.90:16443 --token 7t2weq.bjbawausm0jaxury \
	--discovery-token-ca-cert-hash sha256:7e2075c5cccf6b2dc6a00b05f5b1520929307f3e1be29d5a97ca2784789c4363 

View on master1:

kubectl get node



As can be seen from the above figure, the cluster dns can't work because we haven't added the calio network yet.

Step 14: add calio network
Just master1: Download yaml file:

curl https://docs.projectcalico.org/manifests/calico.yaml -O

Replace the ip address inside with the pod address of our cluster, which is new In yaml:
Uncomment and change to our cluster

Master 1 loads calio Yaml file:

kubectl apply -f calico.yaml

Let's look again:

Cluster setup is now complete.

Keywords: Operation & Maintenance Docker Kubernetes Load Balance

Added by traffic on Thu, 20 Jan 2022 15:28:06 +0200