体验Istio (二): Kubeadm 安装 K8s 集群
用 Kubeadm 部署一个测试用的双节点集群
在这一篇中我们将使用kubeadm基于ubuntu22.04部署一个控制、工作节点分离的双节点集群用于测试,没有高可用加入,使用kubeadm的原因首先是它支持生产级部署,稳定性上没问题,而这里的测试环境也没有基础设施自动化相关的需求。注意,在部署k8s方面,官方文档已经非常详尽,此处不再做太多的细节说明,如果有细节问题请查看列出的官方参考,或者可以通过评论提出问题。
这里需要注意kubeadm的版本,它决定了k8s的版本,参考istio的Getting Started文档,里面指出了能够支持的k8s最新版本为1.28。所以我们的根参考文档是k8s1.28的文档:https://v1-28.docs.kubernetes.io/docs/setup/production-environment/tools/kubeadm/,注意链接中的v1-28
字样,博客中所有官方文档链接都是1.28版本的。
如果你从k8s官网进入文档,记得在文档右上角切换版本:
准备
有两个节点:
- m,master节点,运行控制面组件
- w,worker节点,运行应用负载
基础环境
参考Before you begin,这里仅列出容易出现问题的点:
- 最低配置为2c2g
- 集群内机器hostname、mac、product_uuid唯一,k8s利用后两者标识不同的节点
- 必须关闭swap,因为cgroupv1不支持swap,kubeadm虽然已经包含支持swap的beat特性但默认关闭,并且默认情况下它检测到使用swap会退出,实际上,swap是内存昂贵时代的解决方案,以降低服务质量(换入换出会对程序性能产生很大的影响)来换取可用性,但以当今的服务量级,服务质量下降可能带来其他更多的问题,所以大多数情况下都不建议开启swap,内存不够可以增加,也不必再关注swap内存回收的细节,感兴趣可以阅读为什么 Linux 需要 Swapping
- 在每个节点安装容器运行时,在本系列第一篇中已经部署了contianerd
在后面的安装k8s集群部分还有一些准备工作。
安装kubeadm和组件
在每个节点安装kubeadm、kubelet,在需要命令行客户端的节点安装kubectl,参考Installing kubeadm, kubelet and kubectl,因为是全新安装所以不必关注k8s组件版本兼容规则,需要注意三点:
- 安装istio支持的1.28版本,使用1.28版本文档中的命令就会安装1.28的最新修订版本
- 为kubelet指定cgroup driver为systemd,与容器运行时保持一致
- 别遗漏命令
sudo apt-mark hold kubelet kubeadm kubectl
以锁定版本,否则自动升级会带来比较大的风险。
以上步骤中不太清晰的是配置kubelet的cgroup driver,需要在m节点创建配置文件kubeadm-config.yaml
并在kubeadm初始化时使用,这个文件会被kubeadm传递成为所有节点的/var/lib/kubelet/config.yaml
文件,并会保存为kube-system
namespace下的configmap对象。可以从Configuring the kubelet cgroup driver文档获取最小配置,已经修改kubernetesVersion
:
kind: ClusterConfiguration
apiVersion: kubeadm.k8s.io/v1beta3
kubernetesVersion: v1.28.0
---
kind: KubeletConfiguration
apiVersion: kubelet.config.k8s.io/v1beta1
cgroupDriver: systemd
使用配置文件的详细信息可以从Using kubeadm init with a configuration file文档中看到,如果执行命令kubeadm config print init-defaults
可以看到输出中kubernetesVersion
的值为1.28.0
,虽然当前的实际版本是1.28.5
。
安装k8s集群
准备
主要是对网络、容器运行时和镜像的准备。
在本系列第一篇的基础环境部分介绍了测试环境的网络架构,在所有节点执行命令ip route show
可以看到指向默认网关的接口为nat网络接口,kubeadm与其他k8s组件一样使用与默认网关关联接口的ip作为工作ip,对于这个ip的要求是:
- 固定的ip,因为它会被自动写入到很多配置当中去
- 节点间能够通过工作ip互通
网络配置文件/etc/netplan/00-installer-config.yaml
示例:
# This is the network config written by 'subiquity'
network:
ethernets:
enp0s3: # 仅主机网络接口
addresses:
- 192.168.56.60/24
enp0s8: # nat网络接口
dhcp4: false # 静态ip
routes: # 默认网关
- to: default
via: 10.0.2.1
addresses:
- 10.0.2.51/24
nameservers: # dns
addresses:
- 8.8.8.8
version: 2
另外,参考Troubleshooting kubeadm文档的Pods are not accessible via their Service IP部分可知,对于virtualbox,需要确保命令hostname -i
能够返回一个路由可达的地址,具体的方法是将/etc/hosts
文件中与主机名对应的127.0.0.1
修改为该节点的工作ip,/etc/hosts
部分示例:
127.0.0.1 localhost
10.0.2.51 ubuntu-dev60-k8sm1
执行命令kubeadm config images list
可以看到kubeadm需要的镜像,其中pause镜像为registry.k8s.io/pause:3.9
,所以需要执行命令sudo vim /etc/containerd/config.toml
,修改配置文件中sandbox_image
的值与之匹配。在本系列第一篇中已经为contianerd配置了对应仓库的mirror,kubeadm初始化时可以直接pull镜像,不用提前准备,当然也可以预先在每个节点执行命令sudo kubeadm config images pull
拉取镜像,这样在初始化的时候能够更加快速的看到反馈。拉取至本地的镜像可以执行命令sudo crictl images list
查看。
初始化控制平面m节点
在初始化控制平面节点之前,首先应该确定初始化命令的参数,之前已经为设置cgroup dirver准备了一个配置文件,不做高可用的话主要是考虑网络插件的诉求,此时所有节点上未添加cni插件配置,/etc/cni/net.d/
目录为空。
官方在Installing Addons文档中列出了不完全的网络插件列表,流行网络插件的对比可以参考rancher的文档CNI 网络插件,这里选择flannel,从项目主页可以看到它默认使用10.244.0.0/16
作为pod cidr(包含在kube-flannel.yml
文件中),插件的cidr必须与kubeadm中ClusterConfiguration中的对应设置保持一致,否则flannel pod无法启动。一个问题是flannel的默认cidr很容易看到,kubeadm却不容易(前面提到的打印初始化默认配置看不到),可以参考kubeadm Configuration (v1beta3)文档,其中的podSubnet
配置对应kubeadm命令行参数--pod-network-cidr
(文档中并没有提到两项配置的对应关系),可以看到其默认值是10.244.0.0/24
,必须使之保持一致的话,修改哪一方都是可以的。还有一个问题,对于kubeadm来说参数--pod-network-cidr
与 --config
无法同时使用,否则会产生错误can not mix '--config' with arguments [pod-network-cidr]
。这里选择在kubeadm-config.yaml
中添加目前需要的配置,最终的配置内容为:
kind: ClusterConfiguration
apiVersion: kubeadm.k8s.io/v1beta3
kubernetesVersion: v1.28.0
networking:
podSubnet: "10.244.0.0/16"
---
kind: KubeletConfiguration
apiVersion: kubelet.config.k8s.io/v1beta1
cgroupDriver: systemd
现在,在m节点执行初始化命令:
sudo kubeadm init --config kubeadm-config.yaml
当看到这样的输出信息时:
Your Kubernetes control-plane has initialized successfully!
To start using your cluster, you need to run the following as a regular user:
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:
export KUBECONFIG=/etc/kubernetes/admin.conf
You should now deploy a pod network to the cluster.
Run "kubectl apply -f [podnetwork].yaml" with one of the options listed at:
https://kubernetes.io/docs/concepts/cluster-administration/addons/
Then you can join any number of worker nodes by running the following on each as root:
kubeadm join 10.0.3.15:6443 --token b4ci5u.nwpagzl6cq4y035n \
--discovery-token-ca-cert-hash sha256:cf300f9a479d5988c3d8a655530866d2abb69581812dae1626cad16dd3e381bb
说明控制面节点已经初始化成功(不能等同于节点部署成功),接下来按照输出中提示的命令配置kubectl访问集群的凭证($HOME/.kube/config
),完成后就可以执行命令kubectl get pods -A
查看pod的状态。可以看到coredns pod因为网络插件未就绪而处于pending状态。接下来执行命令安装网络插件flannel,参考Deploying Flannel with kubectl,为避免网络缓慢,可以提前准备kube-flannel.yml
文件:
kubectl apply -f https://github.com/flannel-io/flannel/releases/latest/download/kube-flannel.yml
flannel会在/etc/cni/net.d
目录下创建网络配置。当看到所有的pod都处于running状态后,说明节点部署成功。
处理初始化失败
如果初始化过程失败,参考Clean up文档reset后再修复问题重新初始化,文档中命令假定root用户,如果用sudo提权,注意执行命令sudo sh -c "iptables -F && iptables -t nat -F && iptables -t mangle -F && iptables -X"
清理iptables,还有一些清理行为是包含在kubeadm命令输出中的,同样需要注意。
加入工作节点
现在可以在其他节点执行初始化打印中的join命令加入w节点了。
其余操作从Managed node labels开始根据情况自行处理即可,主要关注的是控制面节点隔离(禁止工作负载调度至控制面节点)。
安装容器管理工具kuboard
k8s的dashboard有些简陋,这里安装一个轻量的管理界面kuboard以简化对k8s的操作。参考安装 Kuboard v3 - 内建用户库,这里不使用docker,而是使用nerdctl(注意修改ip与挂载至容器的本地目录):
sudo nerdctl run -d \
--restart=unless-stopped \
--name=kuboard \
-p 80:80/tcp \
-p 10081:10081/tcp \
-e KUBOARD_ENDPOINT="http://192.168.56.60:80" \
-e KUBOARD_AGENT_SERVER_TCP_PORT="10081" \
-v /home/ian/opt/kuboard/data:/data \
eipwork/kuboard:v3
总结
虽然k8s的官方文档很详尽,但是想要一帆风顺也不容易。本篇因为没有使用高可用架构,相对简单一些,如果使用高可用,就需要使用一个负载均衡(例如kube-vip)来分发访问多个控制面节点的流量,更进一步的话可以把存储etcd集群放到外部(参考Options for Highly Available Topology)。
从部署过程可以看出,kubeadm无法自动化众多的准备工作,如果规模化使用,需要结合标准的操作系统镜像和ansible之类的自动化工具,可以尝试看看其他部署工具的方案。
k8s做了很多抽象,是一个复杂度很高的基础设施,在下一篇中会直接部署istio的demo应用,然后在下下篇中会对k8s相关的概念做一个整体的介绍,再然后才能谈得上体验istio。对于k8s,建议至少刷一遍官方文档。
更多推荐
所有评论(0)