手把手从0到1:搭建Kubernetes集群
搭建 k8s 集群网上很多教程,如果是手工部署或者实验环境可以直接使用 MiniKube 或者 Kind,来在本地启动简单的 Kubernetes 集群进行后面的学习即可。如果是使用 MiniKube 的话,阿里云还维护了一个国内版的 MiniKube,这对于在国内的同学来说会比较友好。
下面介绍使用 kubeadm 这个 Kubernetes 半官方管理工具的工作原理。kubeadm 的初衷就是让 Kubernetes 集群的部署不再让人头疼,而且发展比较成熟,关于各种问题网上都有对应的文章来解决,我们就来使用它部署一个完整的 Kubernetes 集群。
准备工作
首先准备三台虚拟机,或者是三天试服务器,我是从企鹅️上买的三个轻量服务器,还挺便宜,但是后来看文档才知道,这所谓的轻量服务器原来就是k8s上的容器,所以我这属于是在 k8s 的容器里上搭建 k8s 集群了,搁这搁这呢。 为什么我肯定这个提供的就是一个有官方镜像 linux 的容器呢,具体是因为我买了发现他们所谓的内网在不同账号下是不能互通的,也就是说不同账号的轻量服务器分配到了不同的 node 上,内网ip只能在同一个 node 上互通,不同的node之间想互通只能去配置路由,并且配置属于自己的二层网络。所以这听起来就知道是容器了。
在本次部署中,我准备的机器配置如下:
- 2 核 CPU、 4 GB 内存(三台);
- 80 GB 磁盘;
- Centos 7.6;
- 内网互通;
- 外网访问权限不受限制。
这里的内网互通我是直接通过 iptables 来进行配置的,因为三台服务器公网ip可以互通,但是内网ip是不互通的,在 k8s 中默认是用内网ip来交互的,所以我只能用如下命令来进行配置。
sudo iptables -t nat -A OUTPUT -d <另外服务器的内网ip> -j DNAT --to-destination <另外服务器的外网ip>
保证每个节点能内网ip都 ping 通其他节点就行了。
安装 kubeadm 和 Docker
所有节点安装Docker/kubeadm/kubelet
安装 docker
$ wget https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo -O /etc/yum.repos.d/docker-ce.repo
$ yum -y install docker-ce-18.06.1.ce-3.el7
$ systemctl enable docker && systemctl start docker
$ docker --version
Docker version 18.06.1-ce, build e68fc7a
配置一下镜像地址
# cat > /etc/docker/daemon.json << EOF
{
"registry-mirrors": ["https://b9pmyelo.mirror.aliyuncs.com"]
}
EOF
添加 k8s 的 yum 源
$ cat > /etc/yum.repos.d/kubernetes.repo << EOF
[kubernetes]
name=Kubernetes
baseurl=https://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64
enabled=1
gpgcheck=0
repo_gpgcheck=0
gpgkey=https://mirrors.aliyun.com/kubernetes/yum/doc/yum-key.gpg https://mirrors.aliyun.com/kubernetes/yum/doc/rpm-package-key.gpg
EOF
安装kubeadm,kubelet和kubectl
yum install -y kubelet-1.18.0 kubeadm-1.18.0 kubectl-1.18.0
systemctl enable kubelet
K8S集群还未拉起,故这里的kubelet是无法启动的,等master初始化时会自动拉起
替换 k8s 所需组件的 docker 镜像
因为国内的镜像都拉不回来关于 k8s 所需组件的,所以需要替换一下镜像
查看 kubeadm 所需要的镜像列表:
$ kubeadm config images list
I1108 19:54:40.085559 2997 version.go:252] remote version is much newer: v1.22.3; falling back to: stable-1.18
W1108 19:54:40.592794 2997 configset.go:202] WARNING: kubeadm cannot validate component configs for API groups [kubelet.config.k8s.io kubeproxy.config.k8s.io]
k8s.gcr.io/kube-apiserver:v1.18.20
k8s.gcr.io/kube-controller-manager:v1.18.20
k8s.gcr.io/kube-scheduler:v1.18.20
k8s.gcr.io/kube-proxy:v1.18.20
k8s.gcr.io/pause:3.2
k8s.gcr.io/etcd:3.4.3-0
k8s.gcr.io/coredns:1.6.7
编写拉取shell,这里脚本里替换成所需要的组件版本就行了
$ vim ./pull_k8s_images.sh
set -o errexit
set -o nounset
set -o pipefail ##这里定义版本,按照上面得到的列表自己改一下版本号 KUBE_VERSION=v1.18.20
KUBE_PAUSE_VERSION=3.2
ETCD_VERSION=3.4.3-0
DNS_VERSION=1.6.7 ##这是原始仓库名,最后需要改名成这个
GCR_URL=k8s.gcr.io ##这里就是写你要使用的仓库
DOCKERHUB_URL=registry.aliyuncs.com/google_containers ##这里是镜像列表,新版本要把coredns改成coredns/coredns
images=(
kube-proxy:${KUBE_VERSION}
kube-scheduler:${KUBE_VERSION}
kube-controller-manager:${KUBE_VERSION}
kube-apiserver:${KUBE_VERSION}
pause:${KUBE_PAUSE_VERSION}
etcd:${ETCD_VERSION}
coredns:${DNS_VERSION}
) ##这里是拉取和改名的循环语句
for imageName in ${images[@]} ; do
docker pull $DOCKERHUB_URL/$imageName
docker tag $DOCKERHUB_URL/$imageName $GCR_URL/$imageName
docker rmi $DOCKERHUB_URL/$imageName
done
执行shell
$ chmod +x ./pull_k8s_images.sh
$ ./pull_k8s_images.sh
部署 k8s master 节点
因为我的版本是 1.18.20 的版本,所以关于 kubeadm 的配置文件 config,内容如下
vim ./kubeadm/kubeadm.yaml
apiVersion: kubeadm.k8s.io/v1beta2
kind: ClusterConfiguration
controllerManager:
extraArgs:
horizontal-pod-autoscaler-use-rest-clients: "true"
horizontal-pod-autoscaler-sync-period: "10s"
node-monitor-grace-period: "10s"
apiServer:
extraArgs:
runtime-config: "api/all=true"
kubernetesVersion: "stable-1.18"
这里的文件中 apiVersion 字段要根据不同的 k8s 进行调整,具体可以看看官网,因为不同的版本api不同,会报错~
具体可以看看这个:https://kubernetes.io/docs/reference/config-api/kubeadm-config.v1beta3/
kubeadm 初始化安装 k8s
kubeadm init --config ./kubeadm/kubeadm.yaml
最后安装完毕后会有提示:
[addons] Applied essential addon: CoreDNS
[addons] Applied essential addon: kube-proxy Your Kubernetes control-plane has initialized successfully! To start using your cluster, you need to run the following as a regular user: mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config You should now deploy a pod network to the cluster.
Run "kubectl apply -f [podnetwork].yaml" with one of the options listed at:
https://kubernetes.io/docs/concepts/cluster-administration/addons/ Then you can join any number of worker nodes by running the following on each as root: kubeadm join <master_id>:<master_port> --token <join_token> --discovery-token-ca-cert-hash <join_cert_hash>
这个 kubeadm join 命令,就是用来给这个 Master 节点添加更多工作节点(Worker)的命令。我们在后面部署 Worker 节点的时候马上会用到它,所以找一个地方把这条命令记录下来。
此外,kubeadm 还会提示我们第一次使用 Kubernetes 集群所需要的配置命令:
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
而需要这些配置命令的原因是:Kubernetes 集群默认需要加密方式访问。所以,这几条命令,就是将刚刚部署生成的 Kubernetes 集群的安全配置文件,保存到当前用户的.kube 目录下,kubectl 默认会使用这个目录下的授权信息访问 Kubernetes 集群。如果不这么做的话,我们每次都需要通过 export KUBECONFIG 环境变量告诉 kubectl 这个安全配置文件的位置。
我个人更倾向于使用 export KUBECONFIG 环境变量告诉 kubectl 这个安全配置文件的位置,因为当 k8s 发生错误重新启动的时候,可会找不到配置文件
所以
$ vim /etc/profile
在文件最后添加
export KUBECONFIG=/etc/kubernetes/admin.conf $ source /etc/profile
现在,我们就可以使用 kubectl get 命令来查看当前唯一一个节点的状态了
$ kubectl get nodes NAME STATUS ROLES AGE VERSION
master NotReady master 1d v1.18.0
在调试 Kubernetes 集群时,最重要的手段就是用 kubectl describe 来查看这个节点(Node)对象的详细信息、状态和事件(Event),我们来试一下:
$ kubectl describe node master ...
Conditions:
... Ready False ... KubeletNotReady runtime network not ready: NetworkReady=false reason:NetworkPluginNotReady message:docker: network plugin is not ready: cni config uninitialized
通过 kubectl describe 指令的输出,我们可以看到 NodeNotReady 的原因在于,我们尚未部署任何网络插件。另外,我们还可以通过 kubectl 检查这个节点上各个系统 Pod 的状态,其中,kube-system 是 Kubernetes 项目预留的系统 Pod 的工作空间(Namepsace,注意它并不是 Linux Namespace,它只是 Kubernetes 划分不同工作空间的单位):
$ kubectl get pods -n kube-system NAME READY STATUS RESTARTS AGE
coredns-78fcdf6894-j9s52 0/1 Pending 0 1h
coredns-78fcdf6894-jm4wf 0/1 Pending 0 1h
etcd-master 1/1 Running 0 2s
kube-apiserver-master 1/1 Running 0 1s
kube-controller-manager-master 0/1 Pending 0 1s
kube-proxy-xbd47 1/1 NodeLost 0 1h
kube-scheduler-master 1/1 Running 0 1s
可以看到,CoreDNS、kube-controller-manager 等依赖于网络的 Pod 都处于 Pending 状态,即调度失败。这当然是符合预期的:因为这个 Master 节点的网络尚未就绪。
部署网络插件
在 Kubernetes 项目“一切皆容器”的设计理念指导下,部署网络插件非常简单,只需要执行一句 kubectl apply 指令,以 Weave 为例:
# 安装网络插件
$ kubectl apply -f "https://cloud.weave.works/k8s/net?k8s-version=$(kubectl version | base64 | tr -d '\n')"
serviceaccount/weave-net created
clusterrole.rbac.authorization.k8s.io/weave-net created
clusterrolebinding.rbac.authorization.k8s.io/weave-net created
role.rbac.authorization.k8s.io/weave-net created
rolebinding.rbac.authorization.k8s.io/weave-net created
daemonset.apps/weave-net created
部署完成后查看所有的 pod 状态
$ kubectl get pods -n kube-system NAME READY STATUS RESTARTS AGE
coredns-78fcdf6894-j9s52 1/1 Running 0 1d
coredns-78fcdf6894-jm4wf 1/1 Running 0 1d
etcd-master 1/1 Running 0 9s
kube-apiserver-master 1/1 Running 0 9s
kube-controller-manager-master 1/1 Running 0 9s
kube-proxy-xbd47 1/1 Running 0 1d
kube-scheduler-master 1/1 Running 0 9s
weave-net-cmk27 2/2 Running 0 19s
可以看到,所有的系统 Pod 都成功启动了,而刚刚部署的 Weave 网络插件则在 kube-system 下面新建了一个名叫 weave-net-cmk27 的 Pod,一般来说,这些 Pod 就是容器网络插件在每个节点上的控制组件。
除此之外我想让pod被三个节点调度,因为k8s中默认master是不进行调度pod的,也就是此节点上不会部署pod,这个挺浪费
$ kubectl describe node master Name: master
Roles: master
Taints: node-role.kubernetes.io/master:NoSchedule
可以看到,Master 节点默认被加上了node-role.kubernetes.io/master:NoSchedule这样一个“污点”,其中“键”是node-role.kubernetes.io/master,而没有提供“值”。
这个污点是保证 master 不会被pod调度到
所以直接删除这个 taints:
$ kubectl taint nodes --all node-role.kubernetes.io/master-
部署 k8s 的 worker 节点
首先按照上面的部署“安装 kubeadm 和 Docker”
第二步,因为我希望这三个节点随便哪个都能当 master 节点来使用,所以按照“替换 k8s 所需组件的 docker 镜像”把所有master需要的组件镜像都拿来了
第三步,复制master中的 /etc/kubernetes/admin.conf 到 worker 节点的同样路径下,然后 export KUBECONFIG 环境变量
除此之外我发现在 worker join 集群的时候会出现错误:
[ERROR FileContent--proc-sys-net-bridge-bridge-nf-call-iptables]: /proc/sys/net/bridge/bridge-nf-call-iptables contents are not set to 1
解决方法:
echo "1" >/proc/sys/net/bridge/bridge-nf-call-iptables
最后在 woker 节点添加进入集群命令:
就是之前 master 节点提示的 join 命令
查看节点
$ kubectl get nodes
NAME STATUS ROLES AGE VERSION
vm-20-4-centos Ready <none> 141m v1.18.0
vm-20-6-centos Ready master 7h5m v1.18.0
vm-20-9-centos Ready <none> 169m v1.18.0
# 为 workder 节点添加 rolekubectl label nodes
vm-20-4-centoskubernetes.io/role=worker
kubectl label nodes
vm-20-9-centoskubernetes.io/role=worker
因为在k8s中根据 namespace 请求pod会请求host,我不希望请求 vm-20-4-centos 的时候会找不到解析的域名,所以我在没个node节点中还添加了以下的配置:
添加host
$ cat >> /etc/hosts << EOF
10.0.20.4 vm-20-4-centos
10.0.20.6 vm-20-6-centos
10.0.20.9 vm-20-9-centos
EOF
将桥接的IPv4流量传递到iptables的链:
$ cat > /etc/sysctl.d/k8s.conf << EOF
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
EOF
$ sysctl --system # 生效
大功告成,enjoy~~~
关于 k8s 的玩法我个人有以下几个目标:
- 关于 k8s 的可视化,可以给用户提供一个可视化的 Web 界面来查看当前集群的各种信息
- 关于 k8s 的网络插件,可以尝试各种常用的网络插件,看看他们二层网络是怎么工作原理,理解 k8s 的 CNI
- 关于 k8s 的持久性存储是怎么实现的,看看 pvc 和 pv
- 关于 k8s 中对象 operator 是怎么工作的,实现细节是如何的
这里先一个小目标
手把手从0到1:搭建Kubernetes集群的更多相关文章
- kubeadm搭建kubernetes集群之三:加入node节点
在上一章<kubeadm搭建kubernetes集群之二:创建master节点>的实战中,我们把kubernetes的master节点搭建好了,本章我们将加入node节点,使得整个环境可以 ...
- kubeadm搭建kubernetes集群之二:创建master节点
在上一章kubeadm搭建kubernetes集群之一:构建标准化镜像中我们用VMware安装了一个CentOS7虚拟机,并且打算用这个虚拟机的镜像文件作为后续整个kubernetes的标准化镜像,现 ...
- kubeadm 搭建kubernetes集群环境
需求 kubeadm 搭建kubernetes集群环境 准备条件 三台VPS(本文使用阿里云香港 - centos7.7) 一台能SSH连接到VPS的本地电脑 (推荐连接工具xshell) 安装步骤 ...
- 从0到1搭建spark集群---企业集群搭建
今天分享一篇从0到1搭建Spark集群的步骤,企业中大家亦可以参照次集群搭建自己的Spark集群. 一.下载Spark安装包 可以从官网下载,本集群选择的版本是spark-1.6.0-bin-hado ...
- 二进制搭建Kubernetes集群(最新v1.16.0版本)
目录 1.生产环境k8s平台架构 2.官方提供三种部署方式 3.服务器规划 4.系统初始化 5.Etcd集群部署 5.1.安装cfssl工具 5.2.生成etcd证书 5.2.1 创建用来生成 CA ...
- 手把手教你在CentOS上搭建Kubernetes集群
作者:ChamPly 安装CentOS 1.安装net-tools [root@localhost ~]# yum install -y net-tools 2.关闭firewalld [root@l ...
- 【Kubernetes学习笔记】-kubeadm 手动搭建kubernetes 集群
目录 K8S 组件构成 环境准备 (以ubuntu系统为例) 1. kubernetes集群机器 2. 安装 docker. kubeadm.kubelet.kubectl 2.1 在每台机器上安装 ...
- Rancher2.0导入本地RKE Kubernetes集群图解
简要说明: 使用RKE工具在192.168.3.161机器上,创建包含两个节点的Kubernetes集群,(192.168.3.162和192.168.3.163).RKE会自动在/home/用户 ...
- kubeadm搭建kubernetes集群之一:构建标准化镜像
使用docker可以批量管理多个容器,但都是在同一台电脑内进行的,这在实际生产环境中是不够用的,如何突破单机的限制?让多个电脑上的容器可以像单机上的docker-compose.yml管理的那样方便呢 ...
随机推荐
- python学习笔记(八)-模块
大型python程序以模块和包的形式组织.python标准库中包含大量的模块.一个python文件就是一个模块.1.标准模块 python自带的,不需要你安装的2.第三方模块 需要安装,别人提供的. ...
- c++ 的学习 第3集-默认参数
1.默认参数的意思就是 予以形参默认值 2. C++允许函数设置默认参数,在调用时可以根据情况省略实参.规则如下: 默认参数只能按照右到左的顺序 如果函数同时有声明.实现,默认参数只能放在函数声 ...
- P5048-[Ynoi2019 模拟赛]Yuno loves sqrt technology III【分块】
正题 题目链接:https://www.luogu.com.cn/problem/P5048 题目大意 就是这个 [QA]区间众数,但空间很小 长度为\(n\)的序列,要求支持查找区间众数出现次数. ...
- minikube addons enable ingress 启动错误
minikube addons enable ingress 启动错误 开启 minkube ingress 时错误 minikube addons enable ingress --alsologt ...
- 解决 Delegate IDE build/run actions to Maven 编译两次的问题
起因:我的电脑炸了,吸取教训,以后重要的东西千万不要存在C盘,特别是我们 IT 行业的,代码和文档都是一点一点积累的经验.突然没了,总感觉少了点啥,平时我的代码都是放在D盘,但是很多文档放在C盘,导致 ...
- C++核心编程 4 类和对象-对象的初始化和清理
构造函数和析构函数 对象的初始化和清理工作是两个非常重要的安全问题,一个对象或者变量没有初始状态,对其使用结果是未知的,同样,使用完一个对象或变量,没有及时清理,也会造成一定的安全问题.C++利用了构 ...
- 题解 最长道路tree
题目传送门 题目大意 给出一个\(n\)个点的树,每个点有点权,定义一条链的贡献为该链的点数乘上链上的权值和,求出树上所有链中的权值最大值. \(n\le 5\times 10^4\) 思路 算是我入 ...
- FastAPI 学习之路(三)
系列文章: FastAPI 学习之路(一)fastapi--高性能web开发框架 FastAPI 学习之路(二) 之前的文章分享了如何去创建一个简单的路径的请求.那么我们这次分享的如何在请求路径中,增 ...
- Appium iOS 原理
一.iOS Appium 原理 1.1 iOS 9.3 系统之前自动化测试 1.1.1 Native 自动化 这是 iOS 9.3 系统之前自动化测试的架构模式.通过 Android Appium 原 ...
- Java(25)常见异常整理
作者:季沐测试笔记 原文地址:https://www.cnblogs.com/testero/p/15228418.html 博客主页:https://www.cnblogs.com/testero ...