vlambda博客
学习文章列表

快速搭建一个k8s集群

准备工作

为了更加深入的了解和学习 kubernetes,最好能够亲自动手搭建一下集群,虽然大多数时候大家都使用的各大云厂商直接提供的服务。这里再次安利一下在之前的文章中介绍过的 multipass,需要详细了解的可以戳传送门(https://multipass.run/),快速的用 multipass 开两台虚拟机:

## k8s 控制平面要去至少2核2Gmultipass 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 updatesudo 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 updatesudo apt-get install -y apt-transport-https ca-certificates curlsudo curl -fsSLo /usr/share/keyrings/kubernetes-archive-keyring.gpg https://packages.cloud.google.com/apt/doc/apt-key.gpgecho "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 updatesudo apt-get install -y kubelet kubeadm kubectlsudo 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/.kubesudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/configsudo 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 GROUPSk1ddxs.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 VERSIONk8s-001 Ready <none> 3h18m v1.22.2primary Ready control-plane,master 3h33m v1.22.2

总结

看似创建一个 kubernetes 集群非常顺利,但其中还是有几点需要特别关注:

  • 一定要检查容器运行时的 cgroup 驱动 和 kubelet 使用的是否一致,否则 kubelet 会启动不起来。

  • 一定别忘记安装网络组件,否则集群节点状态始终都是 NotReady 的状态。

  • 一定要为集群分配 CIDR 网段。

另外安装中可能会遇到其他原因导致的 kubelet 启动失败的问题,可以使用

sudo journalctl -xeu kubelet

查看启动日志进行问题定位。