5

「云原生」稳定性和可扩展性更强的k8s高可用方案讲解与实战操作

 1 year ago
source link: https://www.51cto.com/article/740851.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

在前面我的文章里或者网上其它资料讲高可用方案,基本上大多数使用Keepalived VIP的方案,但是这种方案并不是最佳的,还有更优的高可用方案,下面将详细介绍。

5574678224857fbc43a55422ca2bc57408ce48.png
653aa9095231998fd683056fd64a5c88f467e9.png

三、开始部署

(1)节点信息

hostname

local-168-182-110

192.168.182.110

master

local-168-182-111

192.168.182.110

local-168-182-112

192.168.182.110

local-168-182-113

192.168.182.113

master

local-168-182-130

192.168.182.130

master

(2)前期准备(所有节点)

1)配置hosts

192.168.182.110 local-168-182-110
192.168.182.111 local-168-182-111
192.168.182.112 local-168-182-112
192.168.182.113 local-168-182-113
192.168.182.130 local-168-182-130

2)配置互信

# 直接一直回车就行
ssh-keygen

ssh-copy-id -i ~/.ssh/id_rsa.pub root@local-168-182-110
ssh-copy-id -i ~/.ssh/id_rsa.pub root@local-168-182-111
ssh-copy-id -i ~/.ssh/id_rsa.pub root@local-168-182-112
ssh-copy-id -i ~/.ssh/id_rsa.pub root@local-168-182-113
ssh-copy-id -i ~/.ssh/id_rsa.pub root@local-168-182-130

3)时间同步

yum install chrony -y
systemctl start chronyd
systemctl enable chronyd
systemctl status chronyd
chronyc sources

4)关闭防火墙

systemctl stop firewalld
systemctl disable firewalld

5)禁用SELinux

# 临时关闭
setenforce 0
# 永久禁用
sed -i 's/^SELINUX=enforcing$/SELINUX=disabled/' /etc/selinux/config

6)关闭swap

# 临时关闭;关闭swap主要是为了性能考虑
swapoff -a
# 可以通过这个命令查看swap是否关闭了
free
# 永久关闭        
sed -ri 's/.*swap.*/#&/' /etc/fstab

7)设置bridge-nf-call-iptables

cat <<EOF | sudo tee /etc/modules-load.d/k8s.conf
overlay
br_netfilter
EOF

sudo modprobe overlay
sudo modprobe br_netfilter

# 设置所需的 sysctl 参数,参数在重新启动后保持不变
cat <<EOF | sudo tee /etc/sysctl.d/k8s.conf
net.bridge.bridge-nf-call-iptables  = 1
net.bridge.bridge-nf-call-ip6tables = 1
net.ipv4.ip_forward                 = 1
EOF

# 应用 sysctl 参数而不重新启动
sudo sysctl --system

(3)安装容器docker(所有节点)

# 配置yum源
cd /etc/yum.repos.d ; mkdir bak; mv CentOS-Linux-* bak/
# centos7
wget -O /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo

# 安装yum-config-manager配置工具
yum -y install yum-utils
# 设置yum源
yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
# 安装docker-ce版本
yum install -y docker-ce
# 启动并设置开机自启
# 设置为开机自启并现在立刻启动服务 --now:立刻启动服务
systemctl enable --now docker

# 查看版本号
docker --version
# 查看版本具体信息
docker version

# Docker镜像源设置
# 修改文件 /etc/docker/daemon.json,没有这个文件就创建
# 配置docker cgroup 驱动程序systemd
# 添加以下内容后,重启docker服务:
cat >/etc/docker/daemon.json<<EOF
{
   "registry-mirrors": ["http://hub-mirror.c.163.com"],
    "exec-opts": ["native.cgroupdriver=systemd"]
}
EOF
# 加载
systemctl restart docker

# 查看
systemctl status docker

(4)配置k8s yum源(所有节点)

cat > /etc/yum.repos.d/kubernetes.repo << EOF
[k8s]
name=k8s
enabled=1
gpgcheck=0
baseurl=https://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64/
EOF

(5)开始安装kubeadm,kubelet和kubectl(所有节点)

# 查找所有的版本,这里选择1.23.x版本
yum --showduplicates list kubelet

# disableexcludes=kubernetes:禁掉除了这个kubernetes之外的别的仓库
yum install -y kubelet-1.23.6 kubeadm-1.23.6 kubectl-1.23.6 --disableexcludes=kubernetes

# 设置为开机自启并现在立刻启动服务 --now:立刻启动服务
systemctl enable --now kubelet

# 查看状态,这里需要等待一段时间再查看服务状态,启动会有点慢
systemctl status kubelet

# 查看版本
kubectl version
yum info kubeadm

(6)使用 kubeadm 初始化集群(第一个master节点)

最好提前把镜像下载好,这样安装快

docker pull registry.aliyuncs.com/google_containers/kube-apiserver:v1.23.6
docker pull registry.aliyuncs.com/google_containers/kube-controller-manager:v1.23.6
docker pull registry.aliyuncs.com/google_containers/kube-scheduler:v1.23.6
docker pull registry.aliyuncs.com/google_containers/kube-proxy:v1.23.6
docker pull registry.aliyuncs.com/google_containers/pause:3.6
docker pull registry.aliyuncs.com/google_containers/etcd:3.5.1-0
docker pull registry.aliyuncs.com/google_containers/coredns:v1.8.6

集群初始化

kubeadm init \
  --apiserver-advertise-address=192.168.182.110 \
  --image-repository registry.aliyuncs.com/google_containers \
  --kubernetes-version v1.23.6 \
  --control-plane-endpoint=192.168.182.110 \
  --service-cidr=10.1.0.0/16 \
  --pod-network-cidr=10.244.0.0/16 \
  --v=5
# –image-repository string:    这个用于指定从什么位置来拉取镜像(1.13版本才有的),默认值是k8s.gcr.io,我们将其指定为国内镜像地址:registry.aliyuncs.com/google_containers
# –kubernetes-version string:  指定kubenets版本号,默认值是stable-1,会导致从https://dl.k8s.io/release/stable-1.txt下载最新的版本号,我们可以将其指定为固定版本(v1.22.1)来跳过网络请求。
# –apiserver-advertise-address  指明用 Master 的哪个 interface 与 Cluster 的其他节点通信。如果 Master 有多个 interface,建议明确指定,如果不指定,kubeadm 会自动选择有默认网关的 interface。这里的ip为master节点ip,记得更换。
# –pod-network-cidr             指定 Pod 网络的范围。Kubernetes 支持多种网络方案,而且不同网络方案对  –pod-network-cidr有自己的要求,这里设置为10.244.0.0/16 是因为我们将使用 flannel 网络方案,必须设置成这个 CIDR。
# --control-plane-endpoint     cluster-endpoint 是映射到该 IP 的自定义 DNS 名称,这里配置hosts映射:127.0.0.1   cluster-endpoint。 这将允许你将 --control-plane-endpoint=cluster-endpoint 传递给 kubeadm init,并将相同的 DNS 名称传递给 kubeadm join。 稍后你可以修改 cluster-endpoint 以指向高可用性方案中的负载均衡器的地址。
f7b007d422ce4411ec384540ebb69ef3febe83.png
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config

查看节点信息

kubectl get nodes
f4eff31901cc6bc1a3f8655d22144b8f118392.png

发现节点是NotReady状态,查看日志是因为没有装CNI网络插件,接下来就开始安装Calico 网络插件,当然也可以选择其它网络插件。

(7)安装Calico网络插件

wget https://docs.projectcalico.org/manifests/calico.yaml
kubectl apply -f calico.yaml

# 查看
kubectl get all -n kube-system|grep calico

# 等calico pod都正常了,再查看节点状态
kubectl get pods -A
kubectl get nodes
31ef46b035683c5660f21525e00fbcf114b96e.png

(8)配置IPVS(所有节点)

1)加载ip_vs相关内核模块

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

所有节点验证开启了ipvs:

lsmod |grep ip_vs

2)安装ipvsadm工具

yum install ipset ipvsadm -y

3)编辑kube-proxy配置文件,mode修改成ipvs

kubectl edit  configmap -n kube-system  kube-proxy

4)重启kube-proxy

# 先查看
kubectl get pod -n kube-system | grep kube-proxy
# 再delete让它自拉起
kubectl get pod -n kube-system | grep kube-proxy |awk '{system("kubectl delete pod "$1" -n kube-system")}'
# 再查看
kubectl get pod -n kube-system | grep kube-proxy

(9)master节点加入集群

One or more conditions for hosting a new control plane instance is not satisfied. unable to add a new control plane instance to a cluster that doesn't have a stable controlPlaneEndpoint address

【解决】添加如下配置:

# controlPlaneEndpoint: 192.192.168.110
kubectl edit cm kubeadm-config -n kube-system
a58e80105a5d3d293d7438cc553cfeea39a4cb.png

开始执行下面的命令将master节点加入集群

# 在第一个master节点上执行以下获取执行命令
# 证如果过期了,可以使用下面命令生成新证书上传,这里会打印出certificate key,后面会用到
CERT_KEY=`kubeadm init phase upload-certs --upload-certs|tail -1`

# 其中 --ttl=0 表示生成的 token 永不失效. 如果不带 --ttl 参数, 那么默认有效时间为24小时. 在24小时内, 可以无数量限制添加 worker.
echo `kubeadm token create --print-join-command --ttl=0` " --control-plane --certificate-key $CERT_KEY --v=5"

# 拿到上面打印的命令在需要添加的节点上执行

# --control-plane 标志通知 kubeadm join 创建一个新的控制平面。加入master必须加这个标记
# --certificate-key ... 将导致从集群中的 kubeadm-certs Secret 下载控制平面证书并使用给定的密钥进行解密。这里的值就是上面这个命令(kubeadm init phase upload-certs --upload-certs)打印出的key。

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

等网络插件自动安装完后,再查看节点状态

kubectl get nodes
e5422c3392099d6b48c479f6ba8133f58e293f.png

(10)修改master节点指向自己apiserver

1)修改配置

cd /etc/kubernetes
# 修改/etc/kubernetes/admin.conf,/etc/kubernetes/kubelet.conf文件中的server ip改成127.0.0.1
vi /etc/kubernetes/admin.conf
vi /etc/kubernetes/kubelet.conf

# 覆盖配置
cp /etc/kubernetes/admin.conf ~/.kube/config

2)删除旧的证书,生成新证书

cd /etc/kubernetes/pki

# 先备份
mv apiserver.key apiserver.key.bak
mv apiserver.crt apiserver.crt.bak

# 使用如下命令生成,分别在三个master节点上执行
kubeadm init phase certs apiserver --apiserver-advertise-address 192.168.182.110 --apiserver-cert-extra-sans "127.0.0.1,10.1.0.1"

kubeadm init phase certs apiserver --apiserver-advertise-address 192.168.182.113 --apiserver-cert-extra-sans "127.0.0.1,10.1.0.1"

kubeadm init phase certs apiserver --apiserver-advertise-address 192.168.182.130 --apiserver-cert-extra-sans "127.0.0.1,10.1.0.1"
#  --apiserver-cert-extra-sans "127.0.0.1":设置了这个,之后加入节点验证证书阶段就不会报错了。

3)修改apiserver

kubectl -n kube-system edit cm kubeadm-config -o yaml
597d5cc13eb825c2c1a0213854eb5dbf874fd7.png

4)修改kube-prxoy配置

kubectl edit cm kube-proxy -oyaml -n kube-system
f9b493d12da7cbb77a9670c79787338ad0dcfc.png
kubectl delete pod -n kube-system `kubectl get pods  -n kube-system|grep kube-proxy|awk '{print $1}'`

5)重启docker和kubelet

systemctl restart docker kubelet

(11)node节点上安装nginx

这里使用nginx四层代理

mv /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo.backup
wget -O /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo
yum makecache
yum install epel-release
yum -y install nginx
yum -y install nginx-all-modules.noarch

配置nginx,在nginx.conf添加如下配置:

stream {                          #实现四层代理功能
    upstream kube_apiserver {            #定义集群,kube_apiserver是集群名称,可自行定义
        least_conn;# 默认调度策略是轮询,在轮询中,如果服务器down掉了,会自动剔除该服务器。
        server local-168-182-110:6443 max_fails=3 fail_timeout=30s;   #集群组是三台服务器k8s apiserver组成
        server local-168-182-113:6443 max_fails=3 fail_timeout=30s;
        server local-168-182-130:6443 max_fails=3 fail_timeout=30s;
    }
    server {                            #定义一个服务
        listen 127.0.0.1:6443;             #需要监听的端口
        proxy_pass kube_apiserver;       #调用集群
        proxy_connect_timeout 10s;                  # 连接超时时间
        proxy_timeout 300s;                         # 端口保持时间
    }
}

(12)node节点加入集群

# 在第一个master节点上执行以下获取执行命令
# 证如果过期了,可以使用下面命令生成新证书上传,这里会打印出certificate key,后面会用到
CERT_KEY=`kubeadm init phase upload-certs --upload-certs|tail -1`

# 其中 --ttl=0 表示生成的 token 永不失效. 如果不带 --ttl 参数, 那么默认有效时间为24小时. 在24小时内, 可以无数量限制添加 worker.
echo `kubeadm token create --print-join-command --ttl=0` " --certificate-key $CERT_KEY --v=5"
# 示例如下:
kubeadm join 127.0.0.1:6443 --token esczfh.6ckynzi6wfj8jhnk --discovery-token-ca-cert-hash sha256:bc8fb85184ed235b88afdba38f0a17976d353abb10d0739d25df452745d1eed8  --certificate-key a126867ad4d91721f157660df77cdea7862ebda8371280c3025c4cc45c23b85f --v=5
b58dbc8086950c6c2e12800c67d7a8ce70296f.png

修改/etc/kubernetes/kubelet.conf配置

076be510193ca97da1a699802afdf7900893a2.png
systemctl restart kubelet

等网络插件自动安装完后,再查看节点状态

kubectl get nodes
kubectl get pods -A
1879e1974ef120233a7794100a6d98926edd33.png

(13)卸载

kubeadm reset
rm -rf /etc/kubernetes/*
rm -fr ~/.kube
rm -fr /var/lib/etcd

四、高可用故障模式测试

(1)master节点故障模拟(一个master故障)

# 关机192.168.182.110
showdown -h now
# 在其它master节点上查看节点状态
kubectl get nodes
35a385d68525b7bae68074cb7ee905e8064e1b.png

【结论】如上图可知,挂一个master节点不影响集群。

(2)master节点故障模拟(两个master故障)

# 关机192.168.182.113
showdown -h now
# 在其它master节点上查看节点状态
kubectl get nodes
f60797220e8de23feea758d1b4881f5ae1ac39.png

【结论】如上图可知,挂两个master节点,整个集群不可用,还是之前说的,三个master节点只允许挂一个master节点,这里就不细说了。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK