[TOC]
前言
经过三天努力,我终于在我本地虚拟机中搭建起了 k8s 集群环境。
本篇文章是我看官方文档,一步一步的实机操作流程,在此写下供各位参考。
我会把我参考的文档连接也一并放出来,官方中文文档写的很全面,不过页面跳转来跳转去的比较乱。
v1.24.0的更新,删除了对 Dockershim
的支持,我在这上面吃了亏。一开始我并没有关心当前的新版本跟旧版本有什么区别,参照着官方文档,再结合着B站的视频,混合着搭建环境,结果可谓非常惨烈……
我使用 kubeadm init
搭建的环境,各种跑不起来,搞得我一头雾水。
我把所有的日志都打了出来,甚至去翻了k8s的源代码,初步定位到问题出在运行时环境上,我反复卸载 k8s、Docker 再安装,问题依旧。
没办法,我重新部署了一个全新的虚拟机,我这次完全根据官方文档的操作步骤,一句话一句话地读,根据之前搭建环境时,对k8s中各个名词的理解,很快,不到半个小时,我在新的系统中搭建成功了!
显而易见,在旧系统上,kubelet跑不起来的原因,的确是因为我的系统环境所致。
仔细思考,出现问题以后,我一直把解决问题的突破口一直放在官方文档、搜索引擎上,而忽略了另一个方向——B站视频。
费尽千辛万苦,我从历史记录里翻到了当时我参考的视频,视频发布时间是2020年,里面对容器运行时的配置里,要求安装 cri-dockerd
这个环境。根据 readme 里的描述
This adapter provides a shim for Docker Engine that lets you control Docker via the Kubernetes Container Runtime Interface.
这个CRI是需要手动编译安装的,卸载后,我的kubelet就可以正确启动了。就是因为这个软件,导致我的kubelet一直无法启动。
在google搜索这个问题的时候,找不到相关的解决方法,我在这里把当时的报错信息贴上来,插个眼,供后续出现本问题的朋友们参考。
"Using this format as endpoint is deprecated, please consider using full url format." deprecatedFormat="" fullURLFormat="unix://"
[core] grpc: addrConn.createTransport failed to connect to { \0 \ }. Err: connection error: desc = "transport: Error while dialing dial unix: missing address". Reconnecting...
Error: failed to run Kubelet: unable to determine runtime API version: rpc error: code = Unavailable desc = connection error: desc = "transport: Error while dialing dial unix: missing address
服务器选择
穷孩子,买不起云服务器,于是只能使用本机搭建虚拟机,模拟云服务器使用并搭建K8S环境。
我的主力机是Windows平台,且我不需要虚拟机的图形化界面,所以我选择了 Hyper-V 这个虚拟化平台,相比 VMware 平台来说,Hyper-V 更轻量化一些。
Hyper-V 是一个构建于物理机底层的虚拟化环境,HostOS以及所有的虚拟机都直接通过Hyper-V使用物理机的资源。
VMware的优势在于它对图形化界面支持很好,但是它在使用物理机资源的时候,相比Hyper-V多了一层,需要经过HostOS才能调用。
用虚拟机的同学需要注意!如果你搭建完成网络插件后,网络插件无法启动,出现以下报错:
莫慌,来这里你找对博客了!
github.com/flannel-io/flannel/subnet/kube/kube.go:403: Failed to watch *v1.Node: failed to list *v1.Node: Get "https://10.96.0.1:443/api/v1/nodes?resourceVersion=3141638": dial tcp 10.96.0.1:443: i/o timeout
解决办法,非最佳实践(针对Ubuntu):
sudo vim /etc/netplan/00-installer-config.yaml
# 找到 gateway4(网关)一栏
# 将网关改成 k8s-master 的 IP 地址
# :wq 退出
sudo netplan apply
# 重启(重新应用) network
我这里认为的最佳实践应该是在宿主机中添加路由,但我这里路由添加的有瑕疵,添加过后还是无法 ping 通 10.96.0.1 这个地址。若有大佬知道该如何解决这个问题还请多多指点!
Linux 安装
Debian下载地址:Debian 离线安装版.iso 官方下载地址
在下载地址页面,可以选择右侧的DVD版本镜像。
Hyper-V虚拟机的部署、Linux的安装过程我这里就不过多叙述了,不过在安装虚拟机的时候,有这些点需要注意:
- 分区注意,若使用Debian自动的分区配置,Debian会自动创建一个swap交换分区,请务必在分区时删除swap分区。
为了方便后续K8S的部署,建议完成以下功能的配置:
- 虚拟机具有一张网卡,该网卡通过NAT访问广域网,并且拥有静态IP。
- 提前准备好必备软件:例如
sudo
、vim
等工具。 - 配置好SSH,建议使用ssh-key进行连接,减少密码使用次数。
一个偷懒的方法:
先搭建好其中一个节点,测试完没问题以后(使用 kubeadm init
后搭建成功后)
将当前 k8s 的环境卸载掉,关机,利用 Hyper-V 的虚拟机导出导入功能,或者 VmWare 的虚拟机复制功能,将这台虚拟机多复制几份,这样你就相当于有多个节点了。
K8S安装
参考文档(Kubernetes 文档/入门/生产环境/使用部署工具安装Kubernetes/使用 kubeadm 引导集群/安装 kubeadm)
第一阶段:检查阶段
本阶段,需要检查三个地方:
- 确保每个节点上 MAC 地址和 product_uuid 的唯一性
- 是否允许检查桥接流量
- 检查必须的端口
1.1 确保每个节点上 MAC 地址和 product_uuid 的唯一性
亲测了一下,如果在安装时使用上述“偷懒的方法”,会导致系统的 product_uuid
重复。
不过我在安装我的集群时,没有注意到这一点,目前看来我的集群还算一切正常,再用一段时间再看吧。
检验MAC地址命令:ip link
(Debian系)或ifconfig -a
。
校验系统product_uuid:sudo cat /sys/class/dmi/id/product_uuid
。
1.2 是否允许检查桥接流量
命令:lsmod | grep br_netfilter
如果有返回值,则通过。
若无返回值,则需要手动加载该模块sudo modprobe 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
EOF
sudo sysctl --system
1.3 检查必须的端口
命令:nc 127.0.0.1 6443
,若返回 (UNKNOWN) [127.0.0.1] 6443 (?) : Connection refused
,即表示无程序占用该端口,正常。
第二阶段:安装 runetime
2.1 安装 kubelet、kubeadm 和 kubectl
2.1.1 更新 apt 包索引并安装使用 Kubernetes apt 仓库所需要的包:
sudo apt-get update
sudo apt-get install -y apt-transport-https ca-certificates curl
2.1.2 下载 Google Cloud 公开签名秘钥:
sudo curl -fsSLo /usr/share/keyrings/kubernetes-archive-keyring.gpg https://packages.cloud.google.com/apt/doc/apt-key.gpg
2.1.3 添加 Kubernetes apt 仓库:
echo "deb [signed-by=/usr/share/keyrings/kubernetes-archive-keyring.gpg] https://apt.kubernetes.io/ kubernetes-xenial main" | sudo tee /etc/apt/sources.list.d/kubernetes.list
2.1.4 更新 apt 包索引,安装 kubelet、kubeadm 和 kubectl,并锁定其版本:
sudo apt-get update
sudo apt-get install -y kubelet kubeadm kubectl
sudo apt-mark hold kubelet kubeadm kubectl
2.2 安装容器运行时(containerd)
参考文档(Kubernetes 文档/入门/生产环境/容器运行时)
2.2.1 环境配置
cat <<EOF | sudo tee /etc/modules-load.d/containerd.conf
overlay
br_netfilter
EOF
sudo modprobe overlay
sudo modprobe br_netfilter
# 设置必需的 sysctl 参数,这些参数在重新启动后仍然存在。
cat <<EOF | sudo tee /etc/sysctl.d/99-kubernetes-cri.conf
net.bridge.bridge-nf-call-iptables = 1
net.ipv4.ip_forward = 1
net.bridge.bridge-nf-call-ip6tables = 1
EOF
# 应用 sysctl 参数而无需重新启动
sudo sysctl --system
2.2.2 安装 Docker 以及 containerd.io
参考文档(Install Docker Engine on Debian)
我这里就直接按照官方的文档,一步一步地把步骤列出来。
2.2.2.1 卸载旧的Docker版本
sudo apt-get remove docker docker-engine docker.io containerd runc
2.2.2.2 添加 Docker apt 仓库:
sudo apt-get update
sudo apt-get install \
ca-certificates \
curl \
gnupg \
lsb-release
2.2.2.3 下载 Docker GPG 秘钥
sudo mkdir -p /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/debian/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
2.2.2.4 添加 Docker apt 仓库(使用stable版)
echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/debian \
$(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
2.2.2.5 安装 最新版 Docker 以及 containerd.io
sudo apt-get update
sudo apt-get install docker-ce docker-ce-cli containerd.io docker-compose-plugin
2.2.2.6 测试 Docker 的安装情况
sudo docker run hello-world
2.2.3 配置 containerd
把apt生成的默认配置,用containerd的完整版默认配置覆盖掉。
sudo mkdir -p /etc/containerd
containerd config default | sudo tee /etc/containerd/config.toml
配置 containerd ,让其使用systemd sudo vim /etc/containerd/config.toml
在文件中找到这么几行:
[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc]
# 这里是一些其他配置,不需要改动!
[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc.options]
# 这里还有一些其他配置,不要改动
SystemdCgroup = true # <----- 找到这一行,默认值是 false ,将它的值改为 true 。
重新启动 containerd 以应用新的配置
sudo systemctl restart containerd
附:国内用户,为了确保搭建成功,请为 containerd 添加代理!
sudo vim /usr/lib/systemd/system/containerd.service
在 service
标签下,添加
Environment="HTTP_PROXY=http://127.0.0.1:8123/"
Environment="HTTPS_PROXY=http://127.0.0.1:8123/"
Environment="NO_PROXY=10.244.0.0/16,127.0.0.1,192.168.0.0/16,localhost,10.0.0.0/8,172.16.0.0/12"
重新载入systemd,并重新启动 containerd 以应用新的配置
sudo systemctl daemon-reload
sudo systemctl restart containerd
2.2.4 配置 Docker
在这个json中,可以配置
sudo mkdir /etc/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
在这个 JSON 中,可以配置以下内容,以在国内加速访问DockerHUB。
该域名需要自己去阿里云免费申请。
"registry-mirrors": [
"https://xxxxxxxx.mirror.aliyuncs.com"
],
重新启动 Docker 以应用配置
sudo systemctl enable docker
sudo systemctl daemon-reload
sudo systemctl restart docker
第三阶段:通过kubeadm配置kubelet
3.1 配置主节点
sudo kubeadm init \
--control-plane-endpoint=k8s-master01 \
--pod-network-cidr=10.244.0.0/16 \
--apiserver-advertise-address=192.168.39.5 \
--image-repository='registry.cn-hangzhou.aliyuncs.com/google_containers' \
--v=5
参数:
control-plane-endpoint
:填写当前节点的 hostname 。
(推荐)如果计划将单个控制平面 kubeadm 集群升级成高可用, 你应该指定 --control-plane-endpoint 为所有控制平面节点设置共享端点。 端点可以是负载均衡器的 DNS 名称或 IP 地址。
pod-network-cidr
:填写pod网络地址,这个网络参数根据你将要使用的第三方pod网络插件而定,若需自定义,请在安装第三方pod网络插件的同时修改安装yaml参数。((参考官方文档)安装 Pod 网络附加组件)
选择一个 Pod 网络插件,并验证是否需要为 kubeadm init 传递参数。 根据你选择的第三方网络插件,你可能需要设置 --pod-network-cidr 的值。 请参阅安装 Pod 网络附加组件。
apiserver-advertise-address
:指定API-service的网络广播接口
(可选)除非另有说明,否则 kubeadm 使用与默认网关关联的网络接口来设置此控制平面节点 API server 的广播地址。 要使用其他网络接口,请为 kubeadm init 设置 --apiserver-advertise-address=<ip-address> 参数。 要部署使用 IPv6 地址的 Kubernetes 集群, 必须指定一个 IPv6 地址,例如 --apiserver-advertise-address=fd00::101
v=5
:遇事不决,输出日志!若搭建环境时,出现因网络原因导致的卡顿,或其他原因,可以通过查看日志进行分析(运行kubeadm时输出日志)
输出:
输出的解读我已经穿插着写在输出里了,请务必仔细阅读以下输出
Your Kubernetes control-plane has initialized successfully!
To start using your cluster, you need to run the following as a regular user:
要开始使用你的集群,你需要以常规用户的身份,运行以下命令:
(用普通用户的身份运行kubectl进行管理)
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
Alternatively, if you are the root user, you can run:
或者,如果你是root用户,你可以运行:
export KUBECONFIG=/etc/kubernetes/admin.conf
You should now deploy a pod network to the cluster.
你必须现在立刻将pod网络部署到当前集群中,你可以任选一个在网址中列出的podnetwork 替换命令中的 [podnetwork] 执行。
Run "kubectl apply -f [podnetwork].yaml" with one of the options listed at:
https://kubernetes.io/docs/concepts/cluster-administration/addons/
You can now join any number of control-plane nodes by copying certificate authorities
and service account keys on each node and then running the following as root:
现在可以通过在每个节点上复制k8s控制证书,
然后以root身份运行以下内容,加入任意数量的control-plane节点
kubeadm join k8s-master01:6443 --token u029ur.f48b7cxg01bykxdv \
--discovery-token-ca-cert-hash sha256:cf3c6e95c4333ef9eee82abd5872859a6ccb23ef2850b36a5d4bf7969c3fedc8 \
--control-plane
Then you can join any number of worker nodes by running the following on each as root:
然后您可以通过以root身份运行以下命令,添加任意数量的work节点
kubeadm join k8s-master01:6443 --token u029ur.f48b7cxg01bykxdv \
--discovery-token-ca-cert-hash sha256:cf3c6e95c4333ef9eee82abd5872859a6ccb23ef2850b36a5d4bf7969c3fedc8
根据输出,我们需要做以下几个步骤:
- 使当前用户(root或普通用户)有控制 k8s 的权限
- 安装 pod 网络
- 将其他节点加入当前 k8s 集群中
萌奈酱认为kubeadm的输出足够清晰地阐述了1、3两步,所以接下来我只着重介绍 安装 pod 网络一步
3.2 在主节点上安装 第三方pod网络模块
这里我使用 kube-flannel
作为pod网络模块。
kube-flannel github项目地址
首先获取配置文件
wget https://raw.githubusercontent.com/flannel-io/flannel/master/Documentation/kube-flannel.yml
如果你在初始化 k8s 的时候,pod网络选择了 10.244.0.0/16
,那么你可以直接运行命令了;
如果不一样,那么在该配置文件中,找到 10.244.0.0/16
,并将它改成你当时设置的网络地址。
直接运行以下命令以安装pod网络插件
kubectl apply -f kube-flannel.yml
文章评论