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 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高可用集群环境部署与配置的更多相关文章
- ProxySQL Cluster 高可用集群环境部署记录
ProxySQL在早期版本若需要做高可用,需要搭建两个实例,进行冗余.但两个ProxySQL实例之间的数据并不能共通,在主实例上配置后,仍需要在备用节点上进行配置,对管理来说非常不方便.但是Proxy ...
- Centos7.5基于MySQL5.7的 InnoDB Cluster 多节点高可用集群环境部署记录
一. MySQL InnoDB Cluster 介绍MySQL的高可用架构无论是社区还是官方,一直在技术上进行探索,这么多年提出了多种解决方案,比如MMM, MHA, NDB Cluster, G ...
- 大数据高可用集群环境安装与配置(09)——安装Spark高可用集群
1. 获取spark下载链接 登录官网:http://spark.apache.org/downloads.html 选择要下载的版本 2. 执行命令下载并安装 cd /usr/local/src/ ...
- 大数据高可用集群环境安装与配置(06)——安装Hadoop高可用集群
下载Hadoop安装包 登录 https://mirrors.tuna.tsinghua.edu.cn/apache/hadoop/common/ 镜像站,找到我们要安装的版本,点击进去复制下载链接 ...
- 大数据高可用集群环境安装与配置(07)——安装HBase高可用集群
1. 下载安装包 登录官网获取HBase安装包下载地址 https://hbase.apache.org/downloads.html 2. 执行命令下载并安装 cd /usr/local/src/ ...
- 大数据高可用集群环境安装与配置(03)——设置SSH免密登录
Hadoop的NameNode需要启动集群中所有机器的Hadoop守护进程,这个过程需要通过SSH登录来实现 Hadoop并没有提供SSH输入密码登录的形式,因此,为了能够顺利登录每台机器,需要将所有 ...
- 大数据高可用集群环境安装与配置(08)——安装Ganglia监控集群
1. 安装依赖包和软件 在所有服务器上输入命令进行安装操作 yum install epel-release -y yum install ganglia-web ganglia-gmetad gan ...
- 大数据高可用集群环境安装与配置(04)——安装JAVA运行环境
Hadoop运行在java环境,所以在安装Hadoop之前,需要安装好jdk 提前下载好jdk安装包(jdk-8u161-linux-x64.tar.gz),将它上传到指定的安装目录当中,然后运行安装 ...
- 大数据高可用集群环境安装与配置(02)——配置ntp服务
NTP服务概述 NTP服务器[Network Time Protocol(NTP)]是用来使计算机时间同步化的一种协议,它可以使计算机对其服务器或时钟源(如石英钟,GPS等等)做同步化,它可以提供高精 ...
随机推荐
- P3467(矩形覆盖问题)
描述:https://www.luogu.com.cn/problem/P3467 1.考虑如果整个建筑物链是等高的,一张高为链高,宽为整个建筑物宽的海报即可完全覆盖: 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) ...
- 【译】Using .NET for Apache Spark to Analyze Log Data
.NET for Spark可用于处理成批数据.实时流.机器学习和ad-hoc查询.在这篇博客文章中,我们将探讨如何使用.NET for Spark执行一个非常流行的大数据任务,即日志分析. 1 什么 ...
- STM32 标准库3.5修改默认外部8M晶振为16M晶振
ST官方标准库V3.5默认的外部晶振频率为8M,实际使用中外部晶振需要修改为16M: 经过实验,修改有效,具体的patch如下: 修改 HSE_VALUE 值 diff --git "a/L ...
- python学习第八天--异常和异常处理
Exception 常用异常: AssertionError 断言语句失败 AttributeError 尝试访问未知的对象属性 IndexError 索引超出序列值 keyError 查找一个不存在 ...
- 设计模式之GOF23代理模式03
动态代理 public class StarHandler implements InvocationHandler{ Star realStar; public StarHandler(Star ...
- [hdu4631 Sad Love Story]最近点对,枚举
题意:S是平面内点的集合,初始为空,每次向集合里面加入一个点P(x,y),询问S内最近点对的距离的平方和 思路:设当前集合的答案为D,则找到集合里面横坐标在(x-√D,x+√D)内的数,用它们来更新答 ...
- Linux,Unix,GNU 到底有什么样的渊源?
Linux,Unix, GNU,你可能经常听到这些名字被放在一起,比如 “Linux是类Unix系统”, “Linux其实应该叫 GNU/Linux” 等等.为什么会有这些说法,这些名词的历史渊源和背 ...
- Django使用channel实现websocket
channel 什么是channel? channel是第三方工具包,对于不支持websocket协议的框架可以借助此包实现websocket 安装 终端安装: pip3 install channe ...
- layui常见弹窗使用方法
1:confim类型使用方法 layui.use('layer', function(){ layer.confirm('是否立即上传卷宗信息?', { btn: ['是','否'], t ...