实际搭建多节点的Kubernetes集群
什么是 kubeadm
kubeadm,原理和 minikube 类似,也是用容器和镜像来封装 Kubernetes 的各种组件,但它的目标不是单机部署,而是要能够轻松地在集群环境里部署 Kubernetes,并且让这个集群接近甚至达到生产级质量。
而在保持这个高水准的同时,kubeadm 还具有了和 minikube 一样的易用性,只要很少的几条命令,如 init、join、upgrade、reset 就能够完成 Kubernetes 集群的管理维护工作,这让它不仅适用于集群管理员,也适用于开发、测试人员。
实验环境的架构是什么样的
在使用 kubeadm 搭建实验环境之前,我们先来看看集群的架构设计,也就是说要准备好集群所需的硬件设施。
这里我画了一张系统架构图,图里一共有 3 台主机,当然它们都是使用虚拟机软件 VirtualBox/VMWare 虚拟出来的,下面我来详细说明一下:
所谓的多节点集群,要求服务器应该有两台或者更多,为了简化我们只取最小值,所以这个 Kubernetes 集群就只有两台主机,一台是 Master 节点,另一台是 Worker 节点。当然,在完全掌握了 kubeadm 的用法之后,你可以在这个集群里添加更多的节点。
Master 节点需要运行 apiserver、etcd、scheduler、controller-manager 等组件,管理整个集群,所以对配置要求比较高,至少是 2 核 CPU、4GB 的内存。
而 Worker 节点没有管理工作,只运行业务应用,所以配置可以低一些,为了节省资源我给它分配了 1 核 CPU 和 1GB 的内存,可以说是低到不能再低了。
基于模拟生产环境的考虑,在 Kubernetes 集群之外还需要有一台起辅助作用的服务器。
它的名字叫 Console,意思是控制台,我们要在上面安装命令行工具 kubectl,所有对 Kubernetes 集群的管理命令都是从这台主机发出去的。这也比较符合实际情况,因为安全的原因,集群里的主机部署好之后应该尽量少直接登录上去操作。
它的名字叫 Console,意思是控制台,我们要在上面安装命令行工具 kubectl,所有对 Kubernetes 集群的管理命令都是从这台主机发出去的。这也比较符合实际情况,因为安全的原因,集群里的主机部署好之后应该尽量少直接登录上去操作。
它的名字叫 Console,意思是控制台,我们要在上面安装命令行工具 kubectl,所有对 Kubernetes 集群的管理命令都是从这台主机发出去的。这也比较符合实际情况,因为安全的原因,集群里的主机部署好之后应该尽量少直接登录上去操作。
安装前的准备工作
不过有了架构图里的这些主机之后,我们还不能立即开始使用 kubeadm 安装 Kubernetes,因为 Kubernetes 对系统有一些特殊要求,我们必须还要在 Master 和 Worker 节点上做一些准备。
这些工作的详细信息你都可以在 Kubernetes 的官网上找到,但它们分散在不同的文档里,比较凌乱,所以我把它们整合到了这里,包括改主机名、改 Docker 配置、改网络设置、改交换分区这四步。
第一,由于 Kubernetes 使用主机名来区分集群里的节点,所以每个节点的 hostname 必须不能重名。你需要修改“/etc/hostname”这个文件,把它改成容易辨识的名字,比如 Master 节点就叫 master,Worker 节点就叫 worker:
1 | sudo vi /etc/hostname |
第二,虽然 Kubernetes 目前支持多种容器运行时,但 Docker 还是最方便最易用的一种,所以我们仍然继续使用 Docker 作为 Kubernetes 的底层支持,使用 apt 安装 Docker Engine
安装完成后需要你再对 Docker 的配置做一点修改,在“/etc/docker/daemon.json”里把 cgroup 的驱动程序改成 systemd ,然后重启 Docker 的守护进程,具体的操作我列在了下面:
1 | cat <<EOF | sudo tee /etc/docker/daemon.json |
第三,为了让 Kubernetes 能够检查、转发网络流量,你需要修改 iptables 的配置,启用“br_netfilter”模块:
1 |
|
第四,你需要修改“/etc/fstab”,关闭 Linux 的 swap 分区,提升 Kubernetes 的性能:
1 | sudo swapoff -a |
完成之后,最好记得重启一下系统,然后给虚拟机拍个快照做备份,避免后续的操作失误导致重复劳动。
安装 kubeadm
好,现在我们就要安装 kubeadm 了,在 Master 节点和 Worker 节点上都要做这一步。
kubeadm 可以直接从 Google 自己的软件仓库下载安装,但国内的网络不稳定,很难下载成功,需要改用其他的软件源,这里我选择了国内的某云厂商:
1 | sudo apt install -y apt-transport-https ca-certificates curl |
更新了软件仓库,我们就可以用 apt install 获取 kubeadm、kubelet 和 kubectl 这三个安装必备工具了。apt 默认会下载最新版本,但我们也可以指定版本号,比如使用和 minikube 相同的“1.23.3”:
1 | sudo apt install -y kubeadm=1.23.3-00 kubelet=1.23.3-00 kubectl=1.23.3-00 |
安装完成之后,你可以用 kubeadm version、kubectl version 来验证版本是否正确:
1 | kubeadm version |
另外按照 Kubernetes 官网的要求,我们最好再使用命令 apt-mark hold ,锁定这三个软件的版本,避免意外升级导致版本错误:
1 | sudo apt-mark hold kubeadm kubelet kubectl |
下载 Kubernetes 组件镜像
前面我说过,kubeadm 把 apiserver、etcd、scheduler 等组件都打包成了镜像,以容器的方式启动 Kubernetes,但这些镜像不是放在 Docker Hub 上,而是放在 Google 自己的镜像仓库网站 gcr.io,而它在国内的访问很困难,直接拉取镜像几乎是不可能的。
所以我们需要采取一些变通措施,提前把镜像下载到本地。
使用命令 kubeadm config images list 可以查看安装 Kubernetes 所需的镜像列表,参数 –kubernetes-version 可以指定版本号:
1 | kubeadm config images list --kubernetes-version v1.23.3 |
知道了镜像的名字和标签就好办了,我们有两种方法可以比较容易地获取这些镜像。
第一种方法是利用 minikube。因为 minikube 本身也打包了 Kubernetes 的组件镜像,所以完全可以从它的节点里把这些镜像导出之后再拷贝过来。
具体做法也很简单,先启动 minikube,然后 minikube ssh 登录进虚拟节点,用 docker save -o 命令把相应版本的镜像都保存下来,再用 minikube cp 拷贝到本地,剩下的事情就不用我多说了:
这种方法安全可靠,不过操作上麻烦了些,所以就有了第二种方法,从国内的镜像网站下载然后再用 docker tag 改名,能够使用 Shell 编程实现自动化:
1 | repo=registry.aliyuncs.com/google_containers |
第二种方法速度快,但也有隐患,万一网站不提供服务,或者改动了镜像就比较危险了。
所以你可以把这两种方法结合起来,先用脚本从国内镜像仓库下载,然后再用 minikube 里的镜像做对比,只要 IMAGE ID 是一样就说明镜像是正确的。
这张截图就是 Kubernetes 1.23.3 的镜像列表(amd64/arm64),你在安装时可以参考:
安装 Master 节点
准备工作都做好了,现在就可以开始正式安装 Kubernetes 了,我们先从 Master 节点开始。
kubeadm 的用法非常简单,只需要一个命令 kubeadm init 就可以把组件在 Master 节点上运行起来,不过它还有很多参数用来调整集群的配置,你可以用 -h 查看。这里我只说一下我们实验环境用到的 3 个参数:
- –pod-network-cidr,设置集群里 Pod 的 IP 地址段。
- –apiserver-advertise-address,设置 apiserver 的 IP 地址,对于多网卡服务器来说很重要(比如 VirtualBox 虚拟机就用了两块网卡),可以指定 apiserver 在哪个网卡上对外提供服务。【需要指定master主机ip地址】。
- –kubernetes-version,指定 Kubernetes 的版本号。
下面的这个安装命令里,我指定了 Pod 的地址段是“10.10.0.0/16”,apiserver 的服务地址是“192.168.10.210”,Kubernetes 的版本号是“1.23.3”:
1 | sudo kubeadm init \ |
F&Q
Kubeadm初始化报错:[ERROR CRI]: container runtime is not running:
问题
1 | master@k8s-master:~$ ./kubeadm_init.sh |
解决办法
1 | rm -rf /etc/containerd/config.toml |
输入后再次执行kubeadm init,正常运行
参考
- https://blog.csdn.net/qq_43580215/article/details/125153959
- https://github.com/containerd/containerd/issues/4581
新节点如何加入到k8s集群中
新节点如何加入到k8s集群中?第一遍执行有提示,后续的话,可以执行这条命令显示加入方式
1 | kubeadm token create --print-join-command |