快速搭建一个k8s集群
准备工作
为了更加深入的了解和学习 kubernetes,最好能够亲自动手搭建一下集群,虽然大多数时候大家都使用的各大云厂商直接提供的服务。这里再次安利一下在之前的文章中介绍过的 multipass,需要详细了解的可以戳传送门(https://multipass.run/),快速的用 multipass 开两台虚拟机:
# k8s 控制平面要去至少2核2G
multipass launch --name=primary --cpus=2 --mem=2G
# 开一台节点
multipass launch --name=k8s-001
安装容器运行时
Kubernetes 使用容器运行时接口(Container Runtime Interface,CRI)与容器运行时进行交互,当前流运行时及套接字路径如下:
运行时 |
域套接字 |
---|---|
Docker |
/var/run/dockershim.sock |
containerd |
/run/containerd/containerd.sock |
CRI-O |
/var/run/crio/crio.sock |
实际上docker在底层也是依赖于 containerd 的,对细节感兴趣可以进行深入了解,这里不赘述。当 Kubernetes 启动时候会自动扫描以上目录,来决定与哪个容器运行时进行交互,如果同时检测到 Docker 和 containerd,则优先选择 Docker。
docker 安装
为所有节点都安装 docker,直接安装 docker,使用 docker 作为容器运行时。
sudo apt-get update
sudo apt install docker.io
注意事项
docker 默认使用的是 cgroupfs 驱动,而 kubelet 默认使用的是 systemd 驱动,kubernetes要求容器运行时和 kubelet 必须使用相同的 cgroup 驱动,否则 kubelet 进程会启动失败,报错如下:
Sep 30 17:31:36 primary kubelet[25761]: E0930 17:31:36.330893 25761 server.go:294] "Failed to run kubelet" err="failed to run Kubelet: misconfiguration: kubelet cgroup driver: \"systemd\" is different from docker cgroup driver: \"cgroupfs\""
检查配置 docker 的 cgroup 驱动
sudo docker info | grep "Cgroup"
为 docker 指定 cgroup 驱动:
vim /etc/docker/daemon.json
添加如下选项:
{
"exec-opts": ["native.cgroupdriver=systemd"]
}
重启docker:
sudo systemctl restart docker.service
创建集群
安装kubeadm、kubelet 和 kubectl
使用官方推荐的 kubeadm 来建立集群,相关软件安装如下:
## 更新镜像源,添加 Kubernetes apt 仓库
sudo apt-get update
sudo apt-get install -y apt-transport-https ca-certificates curl
sudo curl -fsSLo /usr/share/keyrings/kubernetes-archive-keyring.gpg https://packages.cloud.google.com/apt/doc/apt-key.gpg
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
## 安装 kubelet、kubeadm 和 kubectl,并锁定其版本
sudo apt-get update
sudo apt-get install -y kubelet kubeadm kubectl
sudo apt-mark hold kubelet kubeadm kubectl
初始化控制平面节点
这里使用 multipass 创建 primary 作为控制平面节点,初始化控制节点如下:
kubeadm init --control-plane-endpoint={ip或DNS名称}
## 这里指定一个 multipass 虚拟机 ip 进行初始化
kubeadm init --control-plane-endpoint=192.168.64.2
初始化完成后按照提示执行以下命令,设置用户:
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
节点加入集群
在节点 k8s-001 上执行:
kubeadm join <control-plane-host>:<control-plane-port> --token <token> --discovery-token-ca-cert-hash sha256:<hash>
如果未能记录下初始化集群返回的 token 和 cert-hash,可以使用如下方式在控制平台节点获取。
获取 token:
kubeadm token list
TOKEN TTL EXPIRES USAGES DESCRIPTION EXTRA GROUPS
k1ddxs.c9teg184zsnjtn9c 23h 2021-10-01T09:35:42Z authentication,signing The default bootstrap token generated by 'kubeadm init'. system:bootstrappers:kubeadm:default-node-token
获取 cert-hash:
openssl x509 -pubkey -in /etc/kubernetes/pki/ca.crt | openssl rsa -pubin -outform der 2>/dev/null | openssl dgst -sha256 -hex | sed 's/^.* //'
在节点执行如下命令加入集群:
sudo kubeadm join 192.168.64.2:6443 --token k1ddxs.c9teg184zsnjtn9c --discovery-token-ca-cert-hash sha256:3946a554a1593fa03b669823493dc951e096c86d96421aec4e15741be6639df6
安装 Pod 网络组件
官方推荐了很多网络组件,这里我们就使用官方提到的,非常简单的能够满足 Kubernetes 所需要的覆盖网络的 Flannel,安装也是非常的简单:
kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml
配置 kubelet 网段如下:
sudo vim /etc/kubernetes/manifests/kube-controller-manager.yaml
为 kubelet 添加启动如下启动参数:
- --allocate-node-cidrs=true
- --cluster-cidr=10.244.0.0/16
重启 kubelet 进程:
sudo systemctl restart kubelet.service
查看集群节点是否正常:
kubectl get nodes
NAME STATUS ROLES AGE VERSION
k8s-001 Ready <none> 3h18m v1.22.2
primary Ready control-plane,master 3h33m v1.22.2
总结
看似创建一个 kubernetes 集群非常顺利,但其中还是有几点需要特别关注:
一定要检查容器运行时的 cgroup 驱动 和 kubelet 使用的是否一致,否则 kubelet 会启动不起来。
一定别忘记安装网络组件,否则集群节点状态始终都是 NotReady 的状态。
一定要为集群分配 CIDR 网段。
另外安装中可能会遇到其他原因导致的 kubelet 启动失败的问题,可以使用
sudo journalctl -xeu kubelet
查看启动日志进行问题定位。