文章目录
1. 前言
在前面的“入门篇”我们了解了 Docker 和容器技术,掌握了 Kubernetes 的基本对象、原理和操作方法,一路走下来收获很多。
现在你应该对 Kubernetes 和容器编排有了一些初步的认识,那么接下来,让我们继续深入研究 Kubernetes 的其他 API 对象,也就是那些在 Docker 中不存在的但对云计算、集群管理至关重要的概念。
不过在那之前,我们还需要有一个比 minikube 更真实的 Kubernetes 环境,它应该是一个多节点的 Kubernetes 集群,这样更贴近现实中的生产系统,能够让我们尽快地拥有实际的集群使用经验。
所以在今天,我们就来暂时忘掉 minikube,改用 kubeadm(https://kubernetes.io/zh/docs/reference/setup-tools/kubeadm/)搭建出一个新的 Kubernetes 集群,一起来看看更真实的云原生环境。
2. 什么是 kubeadm?
之前我们使用的都是 minikube,它非常简单易用,不需要什么配置工作,就能够在单机环境里创建出一个功能完善的 Kubernetes 集群,给学习、开发、测试都带来了极大的便利。
不过 minikube 还是太“迷你”了,方便的同时也隐藏了很多细节,离真正生产环境里的计算集群有一些差距,毕竟许多需求、任务只有在多节点的大集群里才能够遇到,相比起来,minikube 真的只能算是一个“玩具”。
那么,多节点的 Kubernetes 集群是怎么从无到有地创建出来的呢?
2.1 kubeadm 介绍
Kubernetes 是很多模块构成的,而实现核心功能的组件像 apiserver、etcd、scheduler 等本质上都是可执行文件,所以也可以采用和其他系统差不多的方式,使用 Shell 脚本或者 Ansible 等工具打包发布到服务器上。
不过 Kubernetes 里的这些组件的配置和相互关系实在是太复杂了,用 Shell、Ansible 来部署的难度很高,需要具有相当专业的运维管理知识才能配置、搭建好集群,而且即使这样,搭建的过程也非常麻烦。
为了简化 Kubernetes 的部署工作,让它能够更“接地气”,社区里就出现了一个专门用来在集群中安装 Kubernetes 的工具,名字就叫“kubeadm”,意思就是“Kubernetes 管理员”。
2.2 kubeadm 原理
kubeadm,原理和 minikube 类似,也是用容器和镜像来封装 Kubernetes 的各种组件,但它的目标不是单机部署,而是要能够轻松地在集群环境里部署 Kubernetes,并且让这个集群接近甚至达到生产级质量。
而在保持这个高水准的同时,kubeadm 还具有了和 minikube 一样的易用性,只要很少的几条命令,如 init、join、upgrade、reset 就能够完成 Kubernetes 集群的管理维护工作,这让它不仅适用于集群管理员,也适用于开发、测试人员。
3. kubeadm 实验环境的架构是什么样的?
在使用 kubeadm 搭建实验环境之前,我们先来看看集群的架构设计,也就是说要准备好集群所需的硬件设施。
这里我画了一张系统架构图,图里一共有 3 台主机,当然它们都是使用虚拟机软件 VirtualBox/VMWare 虚拟出来的,下面我来详细说明一下:
所谓的多节点集群,要求服务器应该有两台或者更多,为了简化我们只取最小值,所以这个 Kubernetes 集群就只有两台主机,一台是 Master 节点,另一台是 Worker 节点。当然,在完全掌握了 kubeadm 的用法之后,你可以在这个集群里添加更多的节点。
3.1 Master 节点
Master 节点需要运行 apiserver、etcd、scheduler、controller-manager 等组件,管理整个集群,所以对配置要求比较高,至少是 2 核 CPU、4GB 的内存。
3.2 Worker 节点
Worker 节点没有管理工作,只运行业务应用,所以配置可以低一些,为了节省资源我给它分配了 1 核 CPU 和 1GB 的内存,可以说是低到不能再低了。
3.3 辅助节点
基于模拟生产环境的考虑,在 Kubernetes 集群之外还需要有一台起辅助作用的服务器。
它的名字叫 Console,意思是控制台,我们要在上面安装命令行工具 kubectl,所有对 Kubernetes 集群的管理命令都是从这台主机发出去的。这也比较符合实际情况,因为安全的原因,集群里的主机部署好之后应该尽量少直接登录上去操作。
要提醒你的是,Console 这台主机只是逻辑上的概念,不一定要是独立,你在实际安装部署的时候完全可以复用之前 minikube 的虚拟机,或者直接使用 Master/Worker 节点作为控制台。
这 3 台主机共同组成了我们的实验环境,所以在配置的时候要注意它们的网络选项,必须是在同一个网段,你可以再回顾一下之前准备,保证它们使用的是同一个“Host-Only”(VirtualBox)或者“自定”(VMWare Fusion)网络。
3.4 安装前的准备工作
不过有了架构图里的这些主机之后,我们还不能立即开始使用 kubeadm 安装 Kubernetes,因为 Kubernetes 对系统有一些特殊要求,我们必须还要在 Master 和 Worker 节点上做一些准备。
这些工作的详细信息你都可以在 Kubernetes 的官网上找到,但它们分散在不同的文档里,比较凌乱,所以我把它们整合到了这里,包括修改主机名、修改 Docker 配置、修改网络设置、修改交换分区这四步。
3.4.1 修改主机名
由于 Kubernetes 使用主机名来区分集群里的节点,所以每个节点的 hostname 必须不能重名。你需要修改“/etc/hostname”这个文件,把它改成容易辨识的名字。比如 Master 节点就叫 master,Worker 节点就叫 worker:
sudo vi /etc/hostname
#或者这样修改
sduo hostnamectl set-hostname master
3.4.2 修改 Docker 配置
虽然 Kubernetes 目前支持多种容器运行时,但 Docker 还是最方便最易用的一种,所以我们仍然继续使用 Docker 作为 Kubernetes 的底层支持,使用 apt 安装 Docker Engine(可参考之前文档)
安装完成后需要你再对 Docker 的配置做一点修改,在“/etc/docker/daemon.json”里把 cgroup 的驱动程序改成 systemd ,然后重启 Docker 的守护进程,具体的操作我列在了下面:
cat <<EOF | sudo tee /etc/docker/daemon.json
{
"exec-opts": ["native.cgroupdriver=systemd"],
"log-driver": "json-file",
"log-opts": {
"max-size": "100m"
},
"storage-driver": "overlay2"
}
EOF
sudo systemctl enable docker
sudo systemctl daemon-reload
sudo systemctl restart docker
3.4.3 修改网络设置
为了让 Kubernetes 能够检查、转发网络流量,你需要修改 iptables 的配置,启用“br_netfilter”模块:
cat <<EOF | sudo tee /etc/modules-load.d/k8s.conf
br_netfilter
EOF
cat <<EOF | sudo tee /etc/sysctl.d/k8s.conf
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
net.ipv4.ip_forward=1 # better than modify /etc/sysctl.conf
EOF
sudo sysctl --system
3.4.4 修改交换分区
需要修改“/etc/fstab”,关闭 Linux 的 swap 分区,提升 Kubernetes 的性能:
sudo swapoff -a
sudo sed -ri '/\sswap\s/s/^#?/#/' /etc/fstab
完成之后,最好记得重启一下系统,然后给虚拟机拍个快照做备份,避免后续的操作失误导致重复劳动。
4. 安装kubeadm
4.1 选用国内软件源
现在我们就要安装 kubeadm 了,在 Master 节点和 Worker 节点上都要做这一步。
kubeadm 可以直接从 Google 自己的软件仓库下载安装,但国内的网络不稳定,很难下载成功,需要改用其他的软件源,这里我选择了国内的某云厂商:
sudo apt install -y apt-transport-https ca-certificates curl
curl https://mirrors.aliyun.com/kubernetes/apt/doc/apt-key.gpg | sudo apt-key add -
cat <<EOF | sudo tee /etc/apt/sources.list.d/kubernetes.list
deb https://mirrors.aliyun.com/kubernetes/apt/ kubernetes-xenial main
EOF
sudo apt update
4.1.1 获取 kubeadm、kubelet 和 kubectl
更新了软件仓库,我们就可以用 apt install 获取 kubeadm、kubelet 和 kubectl 这三个安装必备工具了。apt 默认会下载最新版本,但我们也可以指定版本号,比如使用和 minikube 相同的“1.23.3”:
sudo apt install -y kubeadm=1.23.3-00 kubelet=1.23.3-00 kubectl=1.23.3-00
4.1.2 验证kubeadm、kubelet 和 kubectl 版本
kubeadm version
kubectl version --client
4.1.3 锁定软件版本,避免意外升级导致错误
另外按照 Kubernetes 官网的要求,我们最好再使用命令 apt-mark hold ,锁定这三个软件的版本,避免意外升级导致版本错误:
sudo apt-mark hold kubeadm kubelet kubectl
4.2 下载 Kubernetes 组件镜像
前面我说过,kubeadm 把 apiserver、etcd、scheduler 等组件都打包成了镜像,以容器的方式启动 Kubernetes,但这些镜像不是放在 Docker Hub 上,而是放在 Google 自己的镜像仓库网站 gcr.io,而它在国内的访问很困难,直接拉取镜像几乎是不可能的。
所以我们需要采取一些变通措施,提前把镜像下载到本地。
使用命令 kubeadm config images list 可以查看安装 Kubernetes 所需的镜像列表,参数 --kubernetes-version 可以指定版本号:
kubeadm config images list --kubernetes-version v1.23.3
k8s.gcr.io/kube-apiserver:v1.23.3
k8s.gcr.io/kube-controller-manager:v1.23.3
k8s.gcr.io/kube-scheduler:v1.23.3
k8s.gcr.io/kube-proxy:v1.23.3
k8s.gcr.io/pause:3.6
k8s.gcr.io/etcd:3.5.1-0
k8s.gcr.io/coredns/coredns:v1.8.6
知道了镜像的名字和标签就好办了,我们有两种方法可以比较容易地获取这些镜像。
-
minikube获取
利用 minikube。因为 minikube 本身也打包了 Kubernetes 的组件镜像,所以完全可以从它的节点里把这些镜像导出之后再拷贝过来。
具体做法也很简单,先启动 minikube,然后 minikube ssh 登录进虚拟节点,用 docker save -o 命令把相应版本的镜像都保存下来,再用 minikube cp 拷贝到本地,剩下的事情就不用我多说了: -
国内的镜像网站下载
第一种方法安全可靠,不过操作上麻烦了些,所以就有了第二种方法,从国内的镜像网站下载然后再用 docker tag 改名,能够使用 Shell 编程实现自动化:
第二种方法速度快,但也有隐患,万一网站不提供服务,或者改动了镜像就比较危险了。
所以你可以把这两种方法结合起来,先用脚本从国内镜像仓库下载,然后再用 minikube 里的镜像做对比,只要 IMAGE ID 是一样就说明镜像是正确的。
repo=registry.aliyuncs.com/google_containers
for name in `kubeadm config images list --kubernetes-version v1.23.3`; do
src_name=${name#k8s.gcr.io/}
src_name=${src_name#coredns/}
docker pull $repo/$src_name
docker tag $repo/$src_name $name
docker rmi $repo/$src_name
done
这张截图就是 Kubernetes 1.23.3 的镜像列表(amd64/arm64),你在安装时可以参考:
4.3 安装 Master 节点
kubeadm 的用法非常简单,只需要一个命令 kubeadm init 就可以把组件在 Master 节点上运行起来,不过它还有很多参数用来调整集群的配置,你可以用 -h 查看。这里我只说一下我们实验环境用到的 3 个参数:
- –pod-network-cidr,设置集群里 Pod 的 IP 地址段。
- –apiserver-advertise-address,设置 apiserver 的 IP 地址,对于多网卡服务器来说很重要(比如 VirtualBox 虚拟机就用了两块网卡),可以指定 apiserver 在哪个网卡上对外提供服务。
- –kubernetes-version,指定 Kubernetes 的版本号。
下面的这个安装命令里,我指定了 Pod 的地址段是“10.10.0.0/16”,apiserver 的服务地址是“192.168.10.210”,Kubernetes 的版本号是“1.23.3”:
PS: apiserver-advertise-address 后面写的是master 节点的地址
sudo kubeadm init \
--pod-network-cidr=10.10.0.0/16 \
--apiserver-advertise-address=192.168.221.130 \
--kubernetes-version=v1.23.3
因为我们已经提前把镜像下载到了本地,所以 kubeadm 的安装过程很快就完成了,它还会提示出接下来要做的工作
意思是要在本地建立一个“.kube”目录,然后拷贝 kubectl 的配置文件,你只要原样拷贝粘贴就行。
另外还有一个很重要的“kubeadm join”提示,其他节点要加入集群必须要用指令里的 token 和 ca 证书,所以这条命令务必拷贝后保存好:
Then you can join any number of worker nodes by running the following on each as root:
kubeadm join 192.168.221.130:6443 --token 67jpai.5vwfdcap6wug88j5 \
--discovery-token-ca-cert-hash sha256:49107c0be6c39f2118756fbaed5adec8f8ddce69d6bc9e011f2dea0f4c2df8c2
- 出现的报错
解决办法:
#①首先,清空一下上一次初始化产生的文件
rm -rf /etc/kubernetes/*
rm -rf ~/.kube/*
rm -rf /var/lib/etcd/*
#②然后,停用端口,先下载个包
apt-get install -y lsof
lsof -i :6443|grep -v "PID"|awk '{print "kill -9",$2}'|sh
lsof -i :10250|grep -v "PID"|awk '{print "kill -9",$2}'|sh
lsof -i :10257|grep -v "PID"|awk '{print "kill -9",$2}'|sh
lsof -i :10259|grep -v "PID"|awk '{print "kill -9",$2}'|sh
将占用的端口挨个停用,报错的是哪些就停用哪些,别照搬
#③重新加载一下
sudo kubeadm reset
4.3.1 检查kubernetes版本和状态
kubectl version
kubectl get node
你会注意到 Master 节点的状态是“NotReady”,这是由于还缺少网络插件,集群的内部网络还没有正常运作。
4.3.1.1 kubernetes 不显示Server 版本
kubectl version --short
Client Version: v1.23.3
The connection to the server localhost:8080 was refused - did you specify the right host or port?
解决办法:
#1.将主节点(master)中的“/etc/kubernetes/admin.conf”文件拷贝到从节点相同目录下
#若master节点也是worker节点,可以不执行
#2.配置环境变量
echo "export KUBECONFIG=/etc/kubernetes/admin.conf" >> ~/.bash_profile
#3.立即生效
source ~/.bash_profile
4.3.1.2 思考交流
此处机器临时保持状态或者关闭还要在做一边才能看到服务版本,这是因为什么?
5. 安装Flannel 网络插件
Kubernetes 定义了 CNI 标准,有很多网络插件,这里我选择最常用的 Flannel,可以在它的 GitHub 仓库里(https://github.com/flannel-io/flannel/)找到相关文档。
它安装也很简单,只需要使用项目的“kube-flannel.yml”在 Kubernetes 里部署一下就好了。不过因为它应用了 Kubernetes 的网段地址,你需要修改文件里的“net-conf.json”字段,把 Network 改成刚才 kubeadm 的参数 --pod-network-cidr 设置的地址段。
比如在这里,就要修改成“10.10.0.0/16”:
net-conf.json: |
{
"Network": "10.10.0.0/16",
"Backend": {
"Type": "vxlan"
}
}
改好后,你就可以用 kubectl apply 来安装 Flannel 网络了:
cd /k8s
#下载
git clone https://github.com/flannel-io/flannel.git
#git 下来后按上述修改文件的"net-conf.json"字段,/k8s/flannel/Documentation/kube-flannel.yml
kubectl apply -f /k8s/flannel/Documentation/kube-flannel.yml
5.1 查看节点状态
稍等一小会,等镜像拉取下来并运行之后,你就可以执行 kubectl get node 来看节点状态:
kubectl get node
这时你应该能够看到 Master 节点的状态是“Ready”,表明节点网络也工作正常了。
6. 安装worker 节点
如果你成功安装了 Master 节点,那么 Worker 节点的安装就简单多了,只需要用之前拷贝的那条 kubeadm join 命令就可以了,记得要用 sudo 来执行:
sudo \
kubeadm join 192.168.221.130:6443 --token 67jpai.5vwfdcap6wug88j5 \
--discovery-token-ca-cert-hash sha256:49107c0be6c39f2118756fbaed5adec8f8ddce69d6bc9e011f2dea0f4c2df8c2
它会连接 Master 节点,然后拉取镜像,安装网络插件,最后把节点加入集群。
当然,这个过程中同样也会遇到拉取镜像的问题,你可以如法炮制,提前把镜像下载到 Worker 节点本地,这样安装过程中就不会再有障碍了。
6.1 查看节点状态
Worker 节点安装完毕后,执行 kubectl get node ,就会看到两个节点都是“Ready”状态:
6.2 运行nginx 测试
kubectl run ngx --image=nginx:alpine
kubectl get pod -o wide
会看到 Pod 运行在 Worker 节点上,IP 地址是“10.10.1.2”,表明我们的 Kubernetes 集群部署成功。
7. kubeadm 部署kubernetes 集群小结
把 Master 节点和 Worker 节点都安装好,我们今天的任务就算是基本完成了。后面 Console 节点的部署工作更加简单,它只需要安装一个 kubectl,然后复制“config”文件就行,你可以直接在 Master 节点上用“scp”远程拷贝,例如:
scp `which kubectl` chrono@192.168.10.208:~/
scp ~/.kube/config chrono@192.168.10.208:~/.kube
今天的过程多一些,要点我列在了下面:
- kubeadm 是一个方便易用的 Kubernetes 工具,能够部署生产级别的 Kubernetes 集群。
- 安装 Kubernetes 之前需要修改主机的配置,包括主机名、Docker 配置、网络设置、交换分区等。
- Kubernetes 的组件镜像存放在 gcr.io,国内下载比较麻烦,可以考虑从 minikube 或者国内镜像网站获取。
- 安装 Master 节点需要使用命令 kubeadm init,安装 Worker 节点需要使用命令 kubeadm join,还要部署 Flannel 等网络插件才能让集群正常工作。
因为这些操作都是各种 Linux 命令,全手动敲下来确实很繁琐,所以我把这些步骤都做成了 Shell 脚本放在了 GitHub 上(https://github.com/chronolaw/k8s_study/tree/master/admin),你可以下载后直接运行。
转载:https://blog.csdn.net/admin321123/article/details/128104181