kubeadm实现k8s高可用集群环境部署与配置

高可用架构

k8s集群的高可用实际是k8s各核心组件高可用,这里使用主备模式,架构如下:
在这里插入图片描述
主备模式高可用架构说明:

核心组件 高可用模式 高可用实现方式
apiserver 主备 keepalived
controller-manager 主备 leader election
scheduler 主备 leader election
etcd 集群 kubeadm
  • apiserver 通过keepalived实现高可用,当某个节点故障时触发keepalived vip 转移;
  • controller-manager k8s内部通过选举方式产生领导者(由--leader-elect 选型控制,默认为true),同一时刻集群内只有一个controller-manager组件运行;
  • scheduler k8s内部通过选举方式产生领导者(由--leader-elect 选型控制,默认为true),同一时刻集群内只有一个scheduler组件运行;
  • etcd 通过运行kubeadm方式自动创建集群来实现高可用,部署的节点数为奇数,3节点方式最多容忍一台机器宕机。

部署环境

k8s版本

kubelet version|kubeadm version|kubectl version
|---|---|---|---
|v1.15.1|v1.15.1|v1.15.1

主机配置

Centos版本|系统内核|docker version|flannel version|Keepalived version|
---|---|---|---|----|---
|7.8.2003|4.4.223|19.03.9|v0.11.0|v1.3.5|

主机列表

主机名 ip 主机配置 备注
master01 192.168.213.181 4U4G control plane
master02 192.168.213.182 4U4G control plane
master03 192.168.213.183 4U4G control plane
node01 192.168.213.192 2U2G node
node02 192.168.213.192 2U2G node
VIP 192.168.213.200 4U4G 在control plane上浮动

私有仓库

主机名 ip 主机配置 备注
docker-registry 192.168.213.129 2U1G reg.zhao.com

其他准备

系统初始化,docker安装,k8s(kubelet、kubeadm和kubectl)安装省略

  • kubelet 运行在集群所有节点上,用于启动Pod和容器
  • kubeadm 用于初始化集群,启动集群
  • kubectl 用于和集群通信,部署和管理应用,查看各种资源,创建、删除和更新各种组件

启动kubelet并设置开机启动 systemctl enable kubelet && systemctl start kubelet

keepalived安装

在所有master节点上安装

安装keepalived

[root@master01 ~]# yum -y install keepalived

keepalived配置

master01

[root@master01 ~]# cat /etc/keepalived/keepalived.conf 
! Configuration File for keepalived
global_defs {
   router_id master01
}
vrrp_instance VI_1 {
    state MASTER 
    interface ens33
    virtual_router_id 50
    priority 150
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass 1111
    }
    virtual_ipaddress {
        192.168.213.200
    }
}

master02

[root@master02 ~]# cat /etc/keepalived/keepalived.conf 
! Configuration File for keepalived
global_defs {
   router_id master02
}
vrrp_instance VI_1 {
    state BACKUP 
    interface ens33
    virtual_router_id 50
    priority 100
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass 1111
    }
    virtual_ipaddress {
        192.168.213.200
    }
}

master03

[root@master03 ~]# cat /etc/keepalived/keepalived.conf 
! Configuration File for keepalived
global_defs {
   router_id master03
}
vrrp_instance VI_1 {
    state BACKUP 
    interface ens33
    virtual_router_id 50
    priority 100
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass 1111
    }
    virtual_ipaddress {
        192.168.213.200
    }
}

启动keepalived并设置开机启动

[root@master01 ~]# systemctl start keepalived
[root@master01 ~]# systemctl enable keepalived

VIP查看

在这里插入图片描述

配置master节点

初始化master01节点

master01初始化

#初始化的配置文件
[root@master01 ~]# cat kubeadm-config.yaml
apiVersion: kubeadm.k8s.io/v1beta2
kind: ClusterConfiguration
kubernetesVersion: v1.15.1
apiServer:
  certSANs:		##填写所有kube-apiserver节点的hostname、IP、VIP
  - master01
  - master02
  - master03
  - node01
  - node02
  - 192.168.213.181
  - 192.168.213.182
  - 192.168.213.183
  - 192.168.213.191
  - 192.168.213.192
  - 192.168.213.200
controlPlaneEndpoint: "192.168.213.200:6443"
networking:
  podSubnet: "10.244.0.0/16"
[root@master01 ~]# kubeadm init --config=kubeadm-config.yaml|tee kubeadim-init.log

记录kubeadm join的输出,后面需要这个命令将备master节点和node节点加入集群中

Then you can join any number of worker nodes by running the following on each as root:

kubeadm join 192.168.213.200:6443 --token ebx4uz.9y3twsnoj9yoscoo \
    --discovery-token-ca-cert-hash sha256:1bc280548259dd8f1ac53d75e918a8ec99c234b13f4fe18a71435bbbe8cb26f3

加载环境变量

[root@master01 ~]# echo "export KUBECONFIG=/etc/kubernetes/admin.conf" >> ~/.bash_profile
[root@master01 ~]# source .bash_profile

安装flannel网络

[root@master01 ~]# kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/2140ac876ef134e0ed5af15c65e414cf26827915/Documentation/kube-flannel.yml

备master节点加入集群

配置免密登录

配置master01到master02、master03免密登录

#创建秘钥
[root@master01 ~]# ssh-keygen -t rsa
#将秘钥同步至master02,master03
[root@master01 ~]# ssh-copy-id -i /root/.ssh/id_rsa.pub root@192.168.213.182
[root@master01 ~]# ssh-copy-id -i /root/.ssh/id_rsa.pub root@192.168.213.183
#免密登陆测试
[root@master01 ~]# ssh master02
[root@master01 ~]# ssh 192.168.213.183

master01分发证书

在master01上运行脚本cert-main-master.sh,将证书分发至master02和master03

[root@master01 ~]# cat cert-main-master.sh
USER=root # customizable
CONTROL_PLANE_IPS="192.168.213.182 192.168.213.183"
for host in ${CONTROL_PLANE_IPS}; do
    scp /etc/kubernetes/pki/ca.crt "${USER}"@$host:
    scp /etc/kubernetes/pki/ca.key "${USER}"@$host:
    scp /etc/kubernetes/pki/sa.key "${USER}"@$host:
    scp /etc/kubernetes/pki/sa.pub "${USER}"@$host:
    scp /etc/kubernetes/pki/front-proxy-ca.crt "${USER}"@$host:
    scp /etc/kubernetes/pki/front-proxy-ca.key "${USER}"@$host:
    scp /etc/kubernetes/pki/etcd/ca.crt "${USER}"@$host:etcd-ca.crt
    # Quote this line if you are using external etcd
    scp /etc/kubernetes/pki/etcd/ca.key "${USER}"@$host:etcd-ca.key
done
[root@master01 ~]# ./cert-main-master.sh

备master节点移动证书至指定目录

在master02,master03上运行脚本cert-other-master.sh,将证书移至指定目录

[root@master02 ~]# cat cert-other-master.sh
USER=root # customizable
mkdir -p /etc/kubernetes/pki/etcd
mv /${USER}/ca.crt /etc/kubernetes/pki/
mv /${USER}/ca.key /etc/kubernetes/pki/
mv /${USER}/sa.pub /etc/kubernetes/pki/
mv /${USER}/sa.key /etc/kubernetes/pki/
mv /${USER}/front-proxy-ca.crt /etc/kubernetes/pki/
mv /${USER}/front-proxy-ca.key /etc/kubernetes/pki/
mv /${USER}/etcd-ca.crt /etc/kubernetes/pki/etcd/ca.crt
# Quote this line if you are using external etcd
mv /${USER}/etcd-ca.key /etc/kubernetes/pki/etcd/ca.key
[root@master02 ~]# ./cert-other-master.sh 

备master节点加入集群

在master02和master03节点上运行加入集群的命令

kubeadm join 192.168.213.200:6443 --token ebx4uz.9y3twsnoj9yoscoo \
    --discovery-token-ca-cert-hash sha256:1bc280548259dd8f1ac53d75e918a8ec99c234b13f4fe18a71435bbbe8cb26f3

备master节点加载环境变量

此步骤是为了在备master节点上也能执行kubectl命令

scp master01:/etc/kubernetes/admin.conf /etc/kubernetes/
echo "export KUBECONFIG=/etc/kubernetes/admin.conf" >> ~/.bash_profile
source .bash_profile

node节点加入集群

加入集群

在node节点运行初始化master生成的加入集群的命令

kubeadm join 192.168.213.200:6443 --token ebx4uz.9y3twsnoj9yoscoo \
    --discovery-token-ca-cert-hash sha256:1bc280548259dd8f1ac53d75e918a8ec99c234b13f4fe18a71435bbbe8cb26f3

集群节点查看

[root@master01 ~]# kubectl get nodes
[root@master01 ~]# kubectl get pod -o wide -n kube-system 

所有control plane节点处于ready状态,所有的系统组件也正常
在这里插入图片描述

对接私有仓库

私有仓库配置省略,在所有节点上执行以下步骤

修改daemon.json

[root@master01 ~]# cat /etc/hosts
127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4
::1         localhost localhost.localdomain localhost6 localhost6.localdomain6
192.168.213.181 master01
192.168.213.182 master02
192.168.213.183 master03
192.168.213.191 node01
192.168.213.192 node02
192.168.213.129 reg.zhao.com
[root@master01 ~]# cat /etc/docker/daemon.json
{
    "registry-mirrors": ["https://sopn42m9.mirror.aliyuncs.com"],
    "exec-opts": ["native.cgroupdriver=systemd"],
    "log-driver": "json-file",
        "log-opts": {
            "max-size": "100m"
        },
    "insecure-registries": ["https://reg.zhao.com"]
}
[root@master01 ~]# systemctl daemon-reload
[root@master01 ~]# systemctl restart docker

创建认证secret

使用Kuberctl创建docker register认证secret

[root@master01 ~]# kubectl create secret docker-registry myregistrykey --docker-server=https://reg.zhao.com --docker-username=admin --docker-password=Harbor12345 --docker-email=""
secret/myregistrykey created
[root@master02 ~]# kubectl get secrets
NAME                  TYPE                                  DATA   AGE
default-token-6mrjd   kubernetes.io/service-account-token   3      18h
myregistrykey         kubernetes.io/dockerconfigjson        1      19s

在创建Pod的时通过imagePullSecret引用myregistrykey

imagePullSecrets:
  - name: myregistrykey

集群功能测试

测试私有仓库

[root@master02 ~]# cat test_sc.yaml
apiVersion: v1
kind: Pod
metadata:
  name: foo
spec:
  containers:
    - name: foo
      image: reg.zhao.com/zhao/myapp:v1.0
#  imagePullSecrets:
#    - name: myregistrykey

在这里插入图片描述在这里插入图片描述打开注释,应用密钥,可以拉取到镜像
在这里插入图片描述

测试集群高可用

测试master节点高可用

通过ip查看apiserver所在节点,通过leader-elect查看scheduler和controller-manager所在节点

[root@master01 ~]# ip a|grep ens33
[root@master01 ~]# kubectl get endpoints kube-scheduler -n kube-system -o yaml |grep holderIdentity
[root@master01 ~]# kubectl get endpoints kube-controller-manager -n kube-system -o yaml |grep holderIdentity

在这里插入图片描述

组件名 所在节点
apiserver master01
controller-manager master01
scheduler master01
关闭master01,模拟宕机,master01状态为NotReady
[root@master01 ~]# init 0

VIP飘到了master02,controller-manager和scheduler也发生了迁移
在这里插入图片描述

组件名 所在节点
apiserver master02
controller-manager master03
scheduler master02

测试node节点高可用

K8S 的pod-eviction在某些场景下如节点 NotReady,资源不足时,会把 pod 驱逐至其它节点

Kube-controller-manager 周期性检查节点状态,每当节点状态为 NotReady,并且超出 pod-eviction-timeout 时间后,就把该节点上的 pod 全部驱逐到其它节点,其中具体驱逐速度还受驱逐速度参数,集群大小等的影响。最常用的 2 个参数如下:
pod-eviction-timeout:NotReady 状态节点超过该时间后,执行驱逐,默认 5 min
node-eviction-rate:驱逐速度,默认为 0.1 pod/秒

创建pod,维持副本数3

[root@master02 ~]# cat myapp_deploy.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: myapp-deploy
  namespace: default
spec:
  replicas: 3
  selector:
    matchLabels:
      app: myapp
      release: stabel
  template:
    metadata:
      labels:
        app: myapp
        release: stabel
        env: test
    spec:
      containers:
      - name: myapp
        image: library/nginx
        imagePullPolicy: IfNotPresent
        ports:
        - name: http
          containerPort: 80

可以看到pod分布在node01和node02节点上
在这里插入图片描述关闭node02,模拟宕机,node02状态为NotReady
在这里插入图片描述可以看到 NotReady 状态节点超过指定时间后,pod被驱逐到 Ready 的节点上,deployment维持运行3个副本

问题

初始化master节点失败

如果初始化失败,可执行kubeadm reset后重新初始化

[root@master01 ~]# kubeadm reset
#非root用户还须执行rm -rf $HOME/.kube/config

flanne文件下载失败

方法一:可以直接下载kube-flannel.yml文件,然后再执行apply
方法二:配置域名解析
在https://site.ip138.com查询服务器IP
在这里插入图片描述echo "151.101.76.133 raw.Githubusercontent.com" >>/etc/hosts

节点状态NotReady

在节点机器上执行journalctl -f -u kubelet查看kubelet的输出日志信息如下:

Container runtime network not ready: NetworkReady=false reason:NetworkPluginNotReady message:docker: network plugin is not ready: cni config uninitialized

出现这个错误的原因是网络插件没有准备好,在节点上执行命令 docker images|grep flannel 查看flannel镜像是否已经成功拉取,这个花费的时间可能会很长

如果很长时间仍然没有拉下来flannel镜像,可以使用如下方法解决

docker save把主节点上的flannel镜像保存为压缩文件(或在官方仓库https://github.com/coreos/flannel/releases下载镜像传到主机上,要注意版本对应),在节点机器上执行docker load加载镜像

[root@master02 ~]# docker save -o my_flannel.tar quay.io/coreos/flannel:v0.11.0-amd64
[root@master02 ~]# scp my_flannel.tar node01:/root
[root@node01 ~]# docker load < my_flannel.tar

unexpected token `$’do\r”

shell,运行出错:syntax error near unexpected token `$’do\r”

原因:Linux和windows下的回车换行符不兼容

解决方法:将windows下面的CR LF,转换为Linux下面的LF
用notepad++打开文件,编辑->档案格式转换->转换为UNIX格式->保存即可

posted @ 2020-06-02 16:52  遇见你我看到光  阅读(1692)  评论(0编辑  收藏  举报