2022.08.23,Kubernetes v1.25新版本发布啦!
很多Kubernetes的安装教程都已经老旧了,版本不一致的教程会让你多走很多弯路,想安装最新版本(v1.25.0)Kubernetes集群的客观请往下看。
本文容器运行时使用的是:containerd,注意不是Docker Engine。
说明:
v1.24 之前的 Kubernetes 版本直接集成了 Docker Engine 的一个组件,名为 dockershim。
这种特殊的直接整合不再是 Kubernetes 的一部分 (这次删除被作为 v1.20
发行版本的一部分宣布)。
所以这里v1.25使用containerd作为容器运行时。
文章目录
- 环境准备及说明:
- 服务器准备:
- 前置操作:
- 1. 禁用交换分区
- 2. 关闭防火墙
- 3. 禁用SELinux
- 4. 设置时区
- 5. hosts设置
- 6. 安装containerd
- 7. 修改cgroupfs 驱动
- 8. [转发 IPv4 并让 iptables 看到桥接流量](https://kubernetes.io/zh-cn/docs/setup/production-environment/container-runtimes/#%E8%BD%AC%E5%8F%91-ipv4-%E5%B9%B6%E8%AE%A9-iptables-%E7%9C%8B%E5%88%B0%E6%A1%A5%E6%8E%A5%E6%B5%81%E9%87%8F)
- 9. 安装kubelet、kubeadm、kubectl
- 使用 kubeadm 创建集群
环境准备及说明:
服务器准备:
Centos和Ubuntu都可以,某些细节上会有略微区别,文章中会注明。
我的环境:Ubuntu(20.04)。使用Mulitpass构建了三台ubuntu系统的虚拟机。
blueMac:~ blue$ multipass list
Name State IPv4 Image
k8s-master Running 192.168.64.3 Ubuntu 20.04 LTS
k8s-node1 Running 192.168.64.4 Ubuntu 20.04 LTS
k8s-node2 Running 192.168.64.5 Ubuntu 20.04 LTS
macOS下Multipass搭建ubuntu 20.04虚拟机请参考这篇文章:
https://blog.csdn.net/qq_34628724/article/details/126872890
ubuntu 20.04安装docker 20.10.18请参考这篇文章:
https://blog.csdn.net/qq_34628724/article/details/126873666
前置操作:
1. 禁用交换分区
swapoff -a #临时
#永久
sed -i '/swap/s/^\(.*\)$/#\1/g' /etc/fstab
#or vim /etc/fsta,注释swap这一行
/swap.img none swap sw 0 0
#reboot后永久生效
2. 关闭防火墙
虚拟机默认关闭了防火墙,没关闭的执行以下命令:
systemctl stop firewalld
systemctl disable firewalld
ufw status
3. 禁用SELinux
ubuntu:默认没开启
centos:
setenforce 0
sed -i "s/SELINUX=enforcing/SELINUX=disabled/g" /etc/selinux/config
4. 设置时区
sudo timedatectl set-timezone Asia/Shanghai
sudo systemctl restart rsyslog
5. hosts设置
192.168.64.3 k8s-master
192.168.64.4 k8s-node1
192.168.64.5 k8s-node2
6. 安装containerd
已经安装过docker的,containerd.io包含了containerd和runc,但不包含 CNI 插件。按此步骤安装CNI插件。
没有安装过docker的,按此步骤安装containerd、runc、CNI插件。
7. 修改cgroupfs 驱动
注意: 很多教程因为使用的是docker,所以会修改docker的cgroup驱动为systemd,如下:
#修改docker-driver vim /etc/docker/daemon.json , 新增以下行
"exec-opts": ["native.cgroupdriver=systemd"],
#重启docker
systemctl daemon-reload
systemctl restart docker
但是:我们用的是containerd,按如下方式修改cgroup驱动,同时把自定义镜像、重载沙箱镜像一并修改了:
mv /etc/containerd/config.toml /etc/containerd/config.toml.orig #备份
containerd config default > /etc/containerd/config.toml #生成默认配置文件
# vim /etc/containerd/config.toml,如下修改对应行
[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc.options]
......
Root = ""
ShimCgroup = ""
SystemdCgroup = true # 将false改为true
[plugins."io.containerd.tracing.processor.v1.otlp"]
endpoint = "https://docker.mirrors.ustc.edu.cn/" #改成中科大镜像源,可按需修改成阿里、华为等镜像源
insecure = false
protocol = ""
[plugins."io.containerd.grpc.v1.cri"]
netns_mounts_under_state_dir = false
restrict_oom_score_adj = false
#sandbox_image = "k8s.gcr.io/pause:3.6"
sandbox_image = "registry.aliyuncs.com/google_containers/pause:3.8" # 修改成这样
#重启containerd
systemctl daemon-reload
systemctl restart containerd
8. 转发 IPv4 并让 iptables 看到桥接流量
通过运行 lsmod | grep br_netfilter
来验证 br_netfilter
模块是否已加载。
若要显式加载此模块,请运行 sudo modprobe br_netfilter
。
为了让 Linux 节点的 iptables 能够正确查看桥接流量,请确认 sysctl
配置中的 net.bridge.bridge-nf-call-iptables
设置为 1。
cat <<EOF | sudo tee /etc/modules-load.d/k8s.conf
overlay
br_netfilter
EOF
sudo modprobe overlay
sudo modprobe br_netfilter
# 设置所需的 sysctl 参数,参数在重新启动后保持不变
cat <<EOF | sudo tee /etc/sysctl.d/k8s.conf
net.bridge.bridge-nf-call-iptables = 1
net.bridge.bridge-nf-call-ip6tables = 1
net.ipv4.ip_forward = 1
EOF
# 应用 sysctl 参数而不重新启动
sudo sysctl --system
9. 安装kubelet、kubeadm、kubectl
有条件的可按此步骤直接通过Google Cloud下载安装。
国内用户通过阿里云的源下载安装工具包:
#更新 apt 包索引并安装使用 Kubernetes apt 仓库所需要的包
sudo apt-get update
sudo apt-get install -y apt-transport-https ca-certificates curl
#下载 Google Cloud 公开签名秘钥(用阿里云替换)
curl -s https://mirrors.aliyun.com/kubernetes/apt/doc/apt-key.gpg | sudo apt-key add -
sudo tee /etc/apt/sources.list.d/kubernetes.list <<EOF
deb https://mirrors.aliyun.com/kubernetes/apt/ kubernetes-xenial main
EOF
#下载并锁定版本
sudo apt-get update
sudo apt-get install -y kubelet kubeadm kubectl
sudo apt-mark hold kubelet kubeadm kubectl
#设置kubelet开机启动
systemctl daemon-reload
systemctl enable kubelet && systemctl start kubelet
#如果有需要安装指定版本的,也一起附上命令
apt-get install -y kubelet=1.23.5-00 kubeadm=1.23.5-00 kubectl=1.23.5-00
为了避免不必要的错误,以上操作在所有节点都执行。
使用 kubeadm 创建集群
生成默认配置文件:
以下操作在 k8s-master 节点执行。
kubeadm config print init-defaults > kubeadm.yaml
需要修改一些参数,附上我的kubeadm.yaml
:
apiVersion: kubeadm.k8s.io/v1beta3
bootstrapTokens:
- groups:
- system:bootstrappers:kubeadm:default-node-token
token: abcdef.0123456789abcdef
ttl: 24h0m0s
usages:
- signing
- authentication
kind: InitConfiguration
localAPIEndpoint:
advertiseAddress: 192.168.64.3 #修改为master的ip
bindPort: 6443
nodeRegistration:
criSocket: unix:///var/run/containerd/containerd.sock
imagePullPolicy: IfNotPresent
name: k8s-master #修改为master节点的hostname
taints: null
---
apiServer:
timeoutForControlPlane: 4m0s
apiVersion: kubeadm.k8s.io/v1beta3
certificatesDir: /etc/kubernetes/pki
clusterName: kubernetes
controllerManager: {}
dns: {}
etcd:
local:
dataDir: /var/lib/etcd
imageRepository: registry.aliyuncs.com/google_containers #修改为阿里云镜像源
kind: ClusterConfiguration
kubernetesVersion: 1.25.0 #可以指定版本
networking:
dnsDomain: cluster.local
serviceSubnet: 10.96.0.0/12
podSubnet: 10.244.0.0/12 #指定service和pod的子网络地址,根据需要自行修改
scheduler: {}
关于镜像下载:
注意:不需要手动去一个一个镜像下载然后替换tag,也不用写成shell脚本,如下执行即可:
#可以提前下载镜像,避免init初始化时漫长的等待
#查看所需镜像及版本
kubeadm config images list
#下载镜像
kubeadm config images pull --image-repository=registry.aliyuncs.com/google_containers
关于kubelet:
如果此时使用systemctl status kubelet
会发现kubelet 现在每隔几秒就会重启,因为它陷入了一个等待 kubeadm 指令的死循环,无需在意,control-plane启动好了就正常了。
**注意:**很多教程会让你修改kubelet的Cgroup驱动,比如:
修改/etc/systemd/system/kubelet.service.d/10-kubeadm.conf
文件,在KUBELET_KUBECONFIG_ARGS
尾部增加--cgroup-driver=cgroupfs
;或者是修改/var/lib/kubelet/kubeadm-flags.env
,在KUBELET_KUBECONFIG_ARGS
尾部增加--cgroup-driver=systemd
。
**但是:**我们不需要。在版本 1.22 中,如果用户没有在 KubeletConfiguration
中设置 cgroupDriver
字段, kubeadm init
会将它设置为默认值 systemd
。v1.22版本以上应该也是如此,如果不放心,我们也可以显示的设置systemd
:
# kubeadm.yaml增加以下内容:
---
kind: KubeletConfiguration
apiVersion: kubelet.config.k8s.io/v1beta1
cgroupDriver: systemd
开始初始化:
kubeadm init --config kubeadm.yaml
这是一个漫长的过程,取决于你的网络状况,一开始会先下载所需镜像,可以启动另一个窗口,crictl images
可以看到陆续在下载所需的镜像,也可以按上面步骤提前下载再进行初始化,速度会快很多。
成功后出现如下内容:
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: #root用户执行这个
export KUBECONFIG=/etc/kubernetes/admin.conf
......
Then you can join any number of worker nodes by running the following on each as root: #重点:记住这个命令
kubeadm join 192.168.64.3:6443 --token abcdef.0123456789abcdef \
--discovery-token-ca-cert-hash sha256:5483215764fb45bc4f86325a2bd90326e51a37a2637275a0e3bf77e0d30c6263
kubeadm启动master:
#默认情况下,出于安全考虑,你的集群不会在master(控制面节点)上部署Pod。如果你想在控制面节点上部署Pod,执行:
kubectl taint nodes --all node-role.kubernetes.io/master-
#将 Master 恢复成 Master Only 状态
kubectl taint nodes <node-name> node-role.kubernetes.io/master=:NoSchedule
配置pod网络
如果无法访问raw.githubusercontent.com,先配置hosts,增加如下(可能会变更,可通过https://www.ipaddress.com/查看):
140.82.113.3 github.com
185.199.108.133 raw.githubusercontent.com
185.199.109.133 raw.githubusercontent.com
185.199.110.133 raw.githubusercontent.com
185.199.111.133 raw.githubusercontent.com
这里使用calico网络插件,附上官网,我们安装的是最新版v3.24。
安装 Tigera Calico:
kubectl create -f https://raw.githubusercontent.com/projectcalico/calico/v3.24.1/manifests/tigera-operator.yaml
安装 Calico:
kubectl create -f https://raw.githubusercontent.com/projectcalico/calico/v3.24.1/manifests/custom-resources.yaml
确认所有 pod 都在运行:
watch kubectl get pods -n calico-system
控制平面节点隔离:
如果出现master无法部署pod的情况,查看taint并删除:
kubectl taint nodes --all node-role.kubernetes.io/control-plane-
成功则提示:node/k8s-master untainted
**注意:**默认情况下,出于安全原因,你的集群不会在控制平面节点上调度 Pod。很多教程里写的是kubectl taint nodes --all node-role.kubernetes.io/control-plane- node-role.kubernetes.io/master-
,注意这个node-role.kubernetes.io/master-
在v1.25中已经被弃用了,所以我们把这个选项去掉,否则命令执行会报错error: taint "node-role.kubernetes.io/master" not found
。
如何将 Master 恢复成 Master Only 状态:
kubectl taint nodes <node-name> node-role.kubernetes.io/master=:NoSchedule
使用以下命令确认您现在在集群中有一个节点:
此时我们的master节点从NotReady变成Ready了!下一步,添加worker节点。
# kubectl get nodes -o wide
NAME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIME
k8s-master Ready control-plane 3h33m v1.25.0 192.168.64.3 <none> Ubuntu 20.04.4 LTS 5.4.0-125-generic containerd://1.6.8
添加worker节点:
在从节点 k8s-node1、k8s-node2 执行:
kubeadm join 192.168.64.3:6443 --token abcdef.0123456789abcdef --discovery-token-ca-cert-hash sha256:5483215764fb45bc4f86325a2bd90326e51a37a2637275a0e3bf77e0d30c6263 --v=5
此时执行kubectl get nodes
可以看到三个节点都已经变成Ready状态了!
NAME STATUS ROLES AGE VERSION
k8s-master Ready control-plane 9h v1.25.0
k8s-node1 Ready <none> 5h50m v1.25.0
k8s-node2 Ready <none> 5h43m v1.25.0
关于报错:
如果遇到这种报错:
Unfortunately, an error has occurred:
timed out waiting for the condition
This error is likely caused by:
- The kubelet is not running
- The kubelet is unhealthy due to a misconfiguration of the node in some way (required cgroups disabled)
If you are on a systemd-powered system, you can try to troubleshoot the error with the following commands:
- 'systemctl status kubelet'
- 'journalctl -xeu kubelet'
注意查看systemctl status kubelet
和journalctl -xeu kubelet
的输出,里面隐藏了报错原因。
如果出现“network”之类的error,那问题大概率是pod网络配置出现问题。
如果出现“cgroup”之类的error,那有可能是containerd和kubelet的cgroup driver不一致。
如果出现镜像pull之类的error,那可能是网络问题导致镜像拉取不下来,比如 sandbox_image 的镜像默认是从这这 k8s.gcr.io/pause:3.6 拉取的。
报错后需执行kubeadm reset
进行环境清理,然后再重新执行kubeadm init
操作。