1. kubeadm简介
《使用kubeadm升级K8S集群》一文中,了解了k8s集群中常见组件,并且使用kubeadm对k8s集群进行了升级。本文中,会学习使用kubeadm安装部署k8s集群。
Kubeadm is a tool built to provide kubeadm init and kubeadm join as best-practice “fast paths” for creating Kubernetes clusters.
参考文档:
2. 安装流程
目标:搭建一个k8s集群,包括master和node01两个节点,节点系统为centos7.6.1810。
master节点ip为192.168.56.200,node01节点ip为192.168.56.201。
1、环境准备。
2、在master节点和node01节点安装kubeadm。
3、初始化master节点,创建k8s集群(记得安装网络插件)。
4、node01节点加入到k8s集群。
5、验证安装。
3. 环境准备
1、配置主机名
2、配置IP地址
4. 安装docker
参考Docker入门,安装Docker
5. 允许iptables检查桥接流量
允许 iptables 检查桥接流量,允许流量转发
1 | cat <<EOF | sudo tee /etc/modules-load.d/k8s.conf |
所有节点都要执行。
6. 安装kubeadm+kubelet+kubectl
参考安装kubeadm。
6.1. 准备kubernetes.repo配置
1 | cat <<EOF | sudo tee /etc/yum.repos.d/kubernetes.repo |
如果不能连通google,kubernetes.repo中的baseurl就替换成aliyun
1 | cat <<EOF | sudo tee /etc/yum.repos.d/kubernetes.repo |
所有节点都要执行。
6.2. SELinux设置为permissive模式
将 SELinux 设置为 permissive 模式(相当于将其禁用)
1 | sudo setenforce 0 |
6.3. 安装kubeadm+kubelet+kubectl
1、安装默认版本的kubeadm+kubelet+kubectl
1 | sudo yum install -y kubelet kubeadm kubectl --disableexcludes=kubernetes |
centos安装这些组件时如果报错:[Errno -1] repomd.xml signature could not be verified for kubernetes
不考虑安全性的话,最简单的解决办法是修改 /etc/yum.repos.d/kubernetes.repo 文件,设置 repo_gpgcheck=0
2、查看kubelet版本kubelet --version
如果想要安装指定版本的k8s,比如1.22.15,那么需要安装指定版本的kubeadm、kubelet和kubectl。
1 | sudo yum remove -y kubelet kubeadm kubectl |
下文中kubeadm.conf中的版本也需要同步修改kubernetesVersion: 1.22.15
7. 关闭swap
Swap disabled. You MUST disable swap in order for the kubelet to work properly.
如官方文档所说,kubelet正常工作的前提是关闭swap,否则kubeadm执行初始化时会报错:
“–cgroups-per-qos enabled, but –cgroup-root was not specified. defaulting to /“
“Failed to run kubelet” err=”failed to run Kubelet: running with swap on is not supported, please disable swap!
报错查看方法:
1 | systemctl status kubelet |
1、临时关闭swapswapoff -a
2、永久关闭swapsed -i '/ swap / s/^/#/' /etc/fstab
或者编辑 /etc/fstab,手动注释掉swap配置。
1 | #/dev/mapper/centos-swap swap swap defaults 0 0 |
无论是master节点,还是worker节点,记得都要关闭swap。
8. 配置cgroup驱动
Both the container runtime and the kubelet have a property called “cgroup driver”, which is important for the management of cgroups on Linux machines.
如官方文档所说,cgroup驱动对于在linux中管理cgroups中非常重要。
因此需要正确配置 kubelet 的 cgroup 驱动以匹配 kubeadm 集群中的容器运行时的 cgroup 驱动,详情参考 配置 cgroup 驱动
否则kubeadm执行初始化时会报错:
[kubelet-check] It seems like the kubelet isn’t running or healthy.
The kubelet is not running
The kubelet is unhealthy due to a misconfiguration of the node in some way (required cgroups disabled)
这是因为, docker 和 kubelet 服务中的cgroup不一致,docker默认使用cgroupfs,kubelet默认使用systemd
cgroup驱动查看方法:
1 | docker system info | grep -i driver |
方法一:kubelet匹配docker
编辑kubeadm.conf,添加kubelet的cgroup配置,指定驱动为cgroupfs
1 |
|
方法二:docker匹配kubelet
编辑 /etc/docker/daemon.json ,添加:
1 | { |
重启docker
1 | systemctl daemon-reload |
这里选择方法二,因为官方更加推荐,可以避免后续kubeadm升级可能引发的cgroup驱动问题。
9. 初始化master节点
参考Installing kubeadm on your hosts。
9.1. 下载镜像文件
kubeadm默认从gcr.io下载k8s组件镜像,国内需要科学上网,或者更改为国内源。本文选择更改为国内源。
1、导出一份默认配置文件kubeadm config print init-defaults > kubeadm.conf
默认配置内容为:
1 | apiVersion: kubeadm.k8s.io/v1beta3 |
2、下载地址改为国内镜像源
编辑kubeadm.conf,imageRepository改为国内源
1 | imageRepository: registry.cn-hangzhou.aliyuncs.com/google_containers |
3、指定配置文件,执行下载kubeadm config images pull --config kubeadm.conf
[config/images] Pulled registry.cn-hangzhou.aliyuncs.com/google_containers/kube-apiserver:v1.23.0
[config/images] Pulled registry.cn-hangzhou.aliyuncs.com/google_containers/kube-controller-manager:v1.23.0
[config/images] Pulled registry.cn-hangzhou.aliyuncs.com/google_containers/kube-scheduler:v1.23.0
[config/images] Pulled registry.cn-hangzhou.aliyuncs.com/google_containers/kube-proxy:v1.23.0
[config/images] Pulled registry.cn-hangzhou.aliyuncs.com/google_containers/pause:3.6
[config/images] Pulled registry.cn-hangzhou.aliyuncs.com/google_containers/etcd:3.5.1-0
[config/images] Pulled registry.cn-hangzhou.aliyuncs.com/google_containers/coredns:v1.8.6
9.2. k8s集群配置
编辑kubeadm.conf,指定k8s集群配置,详情参考kubeadm 配置 (v1beta2)
9.2.1. advertiseAddress
修改 localAPIEndpoint.advertiseAddress 字段,也就是apiserver对外开放的地址,这里改为master节点地址(因为没有配置高可用)
1 | localAPIEndpoint: |
如果在执行初始前不指定可用的advertiseAddress,那么kubeadm init
初始化时会报错:
Error getting node” err=”node “node” not found
9.2.2. 指定节点名称
修改 nodeRegistration.name 字段,这个字段会作为执行初始化的这个master节点的名称。建议改为master节点的主机名,否则默认就会叫node。
1 | nodeRegistration: |
如果在执行初始化前没有指定节点名字,想要修改的话,需要修改kubeadm.conf后重新部署k8s集群。
不重新部署k8s集群,是否可以直接编辑修改节点的名称?kubectl edit nodes/node
,修改如下:
1 | metadata: |
很遗憾,不可以,会报错:
error: At least one of apiVersion, kind and name was changed
9.2.3. 指定pod ip范围
添加 networking.podSubnet 字段,指定pod ip范围(pod-network-cidr)
1 | networking: |
关于pod ip范围和servcie ip范围的设置,可以参考子网划分详解与子网划分实例精析和详解网络分类ABC
如果在执行初始化前没有指定pod ip范围,也是可以正常初始化的,但是后面会导致CNI插件无法正常启动。比如kube-flannel会报错:
Error registering network: failed to acquire lease: node “node” pod cidr not assigned
后期想要修改的话,需要修改kubeadm.conf后重新部署k8s集群。
不重新部署k8s集群,能否补救?这个是可以的
编辑 /etc/kubernetes/manifests/kube-controller-manager.yaml ,添加参数:
1 | - command: |
然后重启kubelet:systemctl restart kubelet
9.3. 执行初始化
1 | #rm -rf /etc/kubernetes/manifests/ |
完成后,屏幕输出会提示创建配置文件,以及添加worker node的join命令,记录下来。
例如:
1 | kubeadm join 192.168.56.200:6443 --token abcdef.0123456789abcdef \ |
PS:如果忘记了添加worker node的join命令,可以重新生成。
1 | kubeadm token create --help |
生成新的join命令后,之前的join命令同样可以使用。
9.4. 创建配置文件
1 | mkdir -p $HOME/.kube |
9.5. 验证安装
1 | docker ps -a |
9.6. 验证发现问题
问题一:coredns处于pending状态
查看coredns报错信息:
1 | kubectl get deployment/coredns -n kube-system -o yaml |
Warning FailedScheduling 2m57s (x36 over 38m) default-scheduler 0/1 nodes are available: 1 node(s) had taint {node.kubernetes.io/not-ready: }, that the pod didn’t tolerate.
原来是coredns默认无法部署在master节点,因为没有配置容忍。参考污点和容忍度进行配置即可。kubectl edit deployment/coredns -n kube-system -o yaml
tolerations部分添加:
1 | tolerations: |
问题二:coredns无法启动
问题一解决后,coredns可以调度了,但是无法启动。kubectl describe pods/coredns-55b7b56cf8-jv2dc -n kube-system
network is not ready: container runtime network not ready: NetworkReady=false reason:NetworkPluginNotReady message:docker: network plugin is not ready: cni config uninitialized
仔细研读使用 kubeadm 创建集群,原来问题一是符合预期的,master节点还没有ready,因为缺少cni插件。
9.7. 安装CNI插件
参考集群网络系统选择一个cni插件,这里我们选择flannel。
1 | kubectl apply -f https://raw.githubusercontent.com/flannel-io/flannel/master/Documentation/kube-flannel.yml |
10. node01加入k8s集群
1、使用join命令,添加node01节点到集群
1 | kubeadm join 192.168.56.200:6443 --token abcdef.0123456789abcdef \ |
2、验证结果
在master节点执行:kubectl get nodes
看到master节点和node01节点都是Ready的状态,说明安装成功。
11. 开发模式
出于安全原因,k8s集群默认不会在控制节点(master节点)上调度Pod。如果我们希望可以在master节点上调度Pod,比如在开发测试时,可以去掉master节点的污点。kubectl taint nodes --all node-role.kubernetes.io/master-
12. 验证安装
12.1. 手动验证
1 | kubectl get nodes |
1 | kubectl run nginx |
12.2. test-infra
1、拉取源码go get -u k8s.io/test-infra/kubetest
2、执行kubetest
1 | kubetest --extract=v1.11.3 |
12.3. Smoke Test
按照Smoke Test文档操作一遍。
12.4. sonobuoy
官网地址:sonobuoy
源码地址:vmware-tanzu/sonobuoy
13. 节点重启后coredns启动问题
master节点重启后,发现coredns无法正常启动。
Warning Unhealthy 2m1s (x22 over 5m) kubelet Readiness probe failed: HTTP probe failed with statuscode: 503
[ERROR] plugin/errors: HINFO: read udp 10.244.0.7:48010->202.106.195.68:53: i/o timeout
[INFO] plugin/ready: Still waiting on: “kubernetes”
参考How to solve CoreDNS always stuck at “waiting for kubernetes”?,发现需要关闭防火墙,低级错误!
1 | systemctl status firewalld |
14. 集群配置更改
执行kubeadm init
初始化后,kubeadm.conf中的内容就写入到了k8s集群了configmap,可以通过kubectl命令查看。kubectl get cm kubeadm-config -n kube-system -oyaml
如果想要修改配置,可以直接修改kubeadm-config这个configmap,详情参考重新配置 kubeadm 集群。