高可用架构

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 ens160
virtual_router_id 50
priority 150
advert_int 1
authentication {
auth_type PASS
auth_pass 1111
}
virtual_ipaddress {
172.27.34.130
}
}

master02

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

master03

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

启动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格式->保存即可

kubeadm实现k8s高可用集群环境部署与配置的更多相关文章

  1. ProxySQL Cluster 高可用集群环境部署记录

    ProxySQL在早期版本若需要做高可用,需要搭建两个实例,进行冗余.但两个ProxySQL实例之间的数据并不能共通,在主实例上配置后,仍需要在备用节点上进行配置,对管理来说非常不方便.但是Proxy ...

  2. Centos7.5基于MySQL5.7的 InnoDB Cluster 多节点高可用集群环境部署记录

    一.   MySQL InnoDB Cluster 介绍MySQL的高可用架构无论是社区还是官方,一直在技术上进行探索,这么多年提出了多种解决方案,比如MMM, MHA, NDB Cluster, G ...

  3. 大数据高可用集群环境安装与配置(09)——安装Spark高可用集群

    1. 获取spark下载链接 登录官网:http://spark.apache.org/downloads.html 选择要下载的版本 2. 执行命令下载并安装 cd /usr/local/src/ ...

  4. 大数据高可用集群环境安装与配置(06)——安装Hadoop高可用集群

    下载Hadoop安装包 登录 https://mirrors.tuna.tsinghua.edu.cn/apache/hadoop/common/ 镜像站,找到我们要安装的版本,点击进去复制下载链接 ...

  5. 大数据高可用集群环境安装与配置(07)——安装HBase高可用集群

    1. 下载安装包 登录官网获取HBase安装包下载地址 https://hbase.apache.org/downloads.html 2. 执行命令下载并安装 cd /usr/local/src/ ...

  6. 大数据高可用集群环境安装与配置(03)——设置SSH免密登录

    Hadoop的NameNode需要启动集群中所有机器的Hadoop守护进程,这个过程需要通过SSH登录来实现 Hadoop并没有提供SSH输入密码登录的形式,因此,为了能够顺利登录每台机器,需要将所有 ...

  7. 大数据高可用集群环境安装与配置(08)——安装Ganglia监控集群

    1. 安装依赖包和软件 在所有服务器上输入命令进行安装操作 yum install epel-release -y yum install ganglia-web ganglia-gmetad gan ...

  8. 大数据高可用集群环境安装与配置(04)——安装JAVA运行环境

    Hadoop运行在java环境,所以在安装Hadoop之前,需要安装好jdk 提前下载好jdk安装包(jdk-8u161-linux-x64.tar.gz),将它上传到指定的安装目录当中,然后运行安装 ...

  9. 大数据高可用集群环境安装与配置(02)——配置ntp服务

    NTP服务概述 NTP服务器[Network Time Protocol(NTP)]是用来使计算机时间同步化的一种协议,它可以使计算机对其服务器或时钟源(如石英钟,GPS等等)做同步化,它可以提供高精 ...

随机推荐

  1. P3467(矩形覆盖问题)

    描述:https://www.luogu.com.cn/problem/P3467 1.考虑如果整个建筑物链是等高的,一张高为链高,宽为整个建筑物宽的海报即可完全覆盖: 2.若有两个不等高的元素组成建 ...

  2. python学习笔记 Day4

    1.函数返回值分析 li = [1,2,3,4] li2 = [1,2,3,4] def f1(args): args.append(55) li = f1(li) print(li) f1(li2) ...

  3. 【译】Using .NET for Apache Spark to Analyze Log Data

    .NET for Spark可用于处理成批数据.实时流.机器学习和ad-hoc查询.在这篇博客文章中,我们将探讨如何使用.NET for Spark执行一个非常流行的大数据任务,即日志分析. 1 什么 ...

  4. STM32 标准库3.5修改默认外部8M晶振为16M晶振

    ST官方标准库V3.5默认的外部晶振频率为8M,实际使用中外部晶振需要修改为16M: 经过实验,修改有效,具体的patch如下: 修改 HSE_VALUE 值 diff --git "a/L ...

  5. python学习第八天--异常和异常处理

    Exception 常用异常: AssertionError 断言语句失败 AttributeError 尝试访问未知的对象属性 IndexError 索引超出序列值 keyError 查找一个不存在 ...

  6. 设计模式之GOF23代理模式03

    动态代理 public class StarHandler implements InvocationHandler{  Star realStar; public StarHandler(Star ...

  7. [hdu4631 Sad Love Story]最近点对,枚举

    题意:S是平面内点的集合,初始为空,每次向集合里面加入一个点P(x,y),询问S内最近点对的距离的平方和 思路:设当前集合的答案为D,则找到集合里面横坐标在(x-√D,x+√D)内的数,用它们来更新答 ...

  8. Linux,Unix,GNU 到底有什么样的渊源?

    Linux,Unix, GNU,你可能经常听到这些名字被放在一起,比如 “Linux是类Unix系统”, “Linux其实应该叫 GNU/Linux” 等等.为什么会有这些说法,这些名词的历史渊源和背 ...

  9. Django使用channel实现websocket

    channel 什么是channel? channel是第三方工具包,对于不支持websocket协议的框架可以借助此包实现websocket 安装 终端安装: pip3 install channe ...

  10. layui常见弹窗使用方法

    1:confim类型使用方法 layui.use('layer', function(){ layer.confirm('是否立即上传卷宗信息?', {    btn: ['是','否'],    t ...