一、环境准备
本次k8s集群环境的搭建,选择是的模式支持docker作为容器运行时的1.22.x版本,因为之后的版本就不在默认支持docker。新版本kubernets环境搭建过程会在别人文章中详细介绍,这里不在赘述。
本次Kubernetes集群环境搭建,采用的是一个管理节点和一个工作节点的方式,因此集群环境不具备高可用性,仅能用于开发和测试使用。
操作系统选择:6.6.0-72.0.0.76.oe2403sp1.aarch64
准备两台虚拟机,本次是在HIS平台申请ARM架构的虚拟机,信息如下:
| 主机名 | 角色 | 操作系统 | 节点IP |
|---|---|---|---|
| k8s-master01 | 管理节点 | oe2403sp1.aarch64 | xx.xx.xx.71 |
| k8s-worker01 | 工作节点 | oe2403sp1.aarch64 | xx.xx.xx.47 |
说明:
- 主机之间的操作系统版本不强制要求相同,不同的操作系统或者相同操作系统版本不同的主机之间也是可以用来搭建k8s集群环境的。例如:集群环境添加新的工作节点,不要求新的节点的操作系统,安装的软件版本等和集群节点保持一致。
- 主机名称建议设置自定义名称,方便记忆和识别主机的用途。如果新增工作节点,也可以只在管理节点和待添加的新工作节点配置/etc/hosts文件。推荐的做法还是集群内所有节点都添加相关信息。
二、集群部署前准备
2.1 修改主机名(可选)
登录节点,执行如下命令设置主机名称
bash
# 管理节点
hostnamectl set-hostname k8s-master01
# 工作节点
hostnamectl set-hostname k8s-worker01
登录管理节点和工作节点,编辑/etc/hosts文件,添加配置信息如下:
bash
xx.xx.xx.47 k8s-worker01
xx.xx.xx.71 k8s-master01
注意:请使用实际IP地址替换xx
2.2 配置源(所有节点)
在安装docker之前,首先要配置源。内网环境可以使用华为开源镜像仓来配置,链接地址如下:
https://mirrors.tools.huawei.com/home
配置操作系统镜像源
根据操作系统版本选择对应的源进行配置
在/etc/yum.repos.d/ 目录下,创建文件 openEuler.repo,根据版本及系统架构选择配置内容。
bash
[openEuler-everything]
name=openEuler-everything
baseurl=http://mirrors.tools.huawei.com/openeuler/openEuler-24.03-LTS-SP1/everything/aarch64/
enabled=1
gpgcheck=0
gpgkey=http://mirrors.tools.huawei.com/openeuler/openEuler-24.03-LTS-SP1/everything/aarch64/RPM-GPG-KEY-openEuler
[openEuler-EPOL]
name=openEuler-epol
baseurl=http://mirrors.tools.huawei.com/openeuler/openEuler-24.03-LTS-SP1/EPOL/main/aarch64/
enabled=1
gpgcheck=0
[openEuler-update]
name=openEuler-update
baseurl=http://mirrors.tools.huawei.com/openeuler/openEuler-24.03-LTS-SP1/update/aarch64/
enabled=1
gpgcheck=0
执行yum clean all清除原有 yum 缓存
执行yum makecache生成新的缓存。
注意:还需要关闭证书验证,需要修改/etc/yum.conf,添加sslverify=False或者sslverify=0
配置docker源
推荐使用dnf命令,因为yum后续不在更新,会逐渐被dnf替代。如果使用yum安装,有些软件包会无法安装,比如在安装yum-utils的时候就是提示找不到。
- 卸载原有的docker组件,以免冲突
bash
dnf remove docker docker-common docker-selinux docker-engine
- 安装依赖
bash
dnf install -y dnf-utils device-mapper-persistent-data lvm2
- 获取docker仓库源配置文件
bash
wget -O /etc/yum.repos.d/docker-ce.repo https://mirrors.tools.huawei.com/docker-ce/linux/centos/docker-ce.repo --no-check-certificate
注意:--no-check-certificate参数的作用是未加载证书需要忽略证书验证,不添加这个无法正常下载配置文件。
- 修改docker源的配置文件
OpenEuler 24.03 属于 RH EL9 系列(对应 RHEL 9.4 左右),与 CentOS Stream 9 属于同一级别。
OpenEuler 22.03 相当于 RHEL 9(大约 RHEL 9.0 ~ 9.2 左右),与 CentOS Stream 9 属于同一级别。
所以建议使用docker镜像源中的centos 9的进行替换
首先是替换仓库地址,命令如下
bash
sed -i 's+https://download.docker.com+https://mirrors.tools.huawei.com/docker-ce+' /etc/yum.repos.d/docker-ce.repo
接下来替换配置文件中的$releasever的值为9
bash
sed -i 's+$releasever+9+' /etc/yum.repos.d/docker-ce.repo
- 生成缓存
bash
dnf makecache
2.3 安装docker(所有节点)
在 Kubernetes(k8s)中,Docker 作为容器运行时的支持情况如下:
- 从 Kubernetes 1.20 版本开始,Docker 容器运行时被标记为 已弃用(deprecated)。
- 从 Kubernetes 1.24 版本开始,Docker 容器运行时不再被默认支持,kubelet 中移除了对 Docker 的内置支持(dockershim 被移除)。
因此,最后一个默认支持 Docker 作为容器运行时的 Kubernetes 版本是 1.23。
在 Kubernetes 1.24 及更高版本中,如果需要使用 Docker,需要通过外部的 dockershim 适配器(如 cri-dockerd)来支持。
本次离线部署的k8s版本是1.22.12版本,因此默认是支持docker作为容器运行时的。
如果节点已经安装了docker,可以跳过安装。需要检查一下已经安装的docker版本是否满足要求,k8s 1.22.x版本通常推荐的版本是20.10.x系列docker版本,是当时最稳定和使用最广泛的版本。当然也支持以下版本:19.03.12以上、Docker 20.10.x、Docker 21.06.x、Docker 23.0.x
bash
# 安装 docker-ce
dnf -y install docker-ce-20.10.17 docker-ce-cli-20.10.17
# 安装 containerd(如果需要)
dnf -y install containerd.io
# 安装其他插件(可选)
dnf -y install docker-buildx-plugin docker-compose-plugin
启动docker
bash
# 重新加载守护进程
systemctl daemon-reload
# 启动docker
systemctl start docker
# 设置开机自启动
systemctl enable docker
检查docker
bash
# 检查客户端
docker -v
# 检查服务端
docker info
三、部署k8s集群
本文安装参考来自:
https://3ms.huawei.com/next/groups/index.html#/wiki/detail?groupId=3225441\&wikiId=7342135
上传软件压缩包至服务器任意目录下,例如/opt,服务包中包含以下文件内容:
软件包链接:https://onebox.huawei.com/p/041c2ffd85e4a34fa42ab5bee018947e
bash
k8s1.22.12/
├── kubeadm k8s组件的二进制执行文件
├── kubectl k8s组件的二进制执行文件
├── kubelet k8s组件的二进制执行文件
├── kube-images k8s组件所需的镜像
│ ├── coredns_v1.8.4.tar
│ ├── etcd_3.5.0-0.tar
│ ├── kube-apiserver_v1.22.12.tar
│ ├── kube-controller-manager_v1.22.12.tar
│ ├── kube-proxy_v1.22.12.tar
│ ├── kube-scheduler_v1.22.12.tar
│ └── pause_3.5.tar
├── kubelet-service-config kubelet服务所需的配置
│ ├── 10-kubeadm.conf
│ └── kubelet.service
└── plugin
├── calico 网络插件calico所需的镜像
│ ├── calico-cni-v3.17.6.tar
│ ├── calico-kube-controllers-v3.17.6.tar
│ ├── calico-node-v3.17.6.tar
│ ├── calico-pod2daemon-flexvol-v3.17.6.tar
│ └── calico.yaml
├── cni-plugins-linux-arm64-v1.1.1.tgz CNI插件包
└── crictl-v1.25.0-linux-arm64.tar.gz crictl插件包
将离线安装包上传规划的目录下进行解压即可。
3.1 导入k8s镜像(kube-images目录)
bash
# 切换到k8s镜像所在目录
cd k8s1.22.12/kube-images/
# 执行如下命令导入所有镜像
docker load -i coredns_v1.8.4.tar
docker load -i etcd_3.5.0-0.tar
docker load -i kube-apiserver_v1.22.12.tar
docker load -i kube-controller-manager_v1.22.12.tar
docker load -i kube-proxy_v1.22.12.tar
docker load -i kube-scheduler_v1.22.12.tar
docker load -i pause_3.5.tar
3.2 导入calico镜像(plugin/calico目录)
bash
# 切换到calico镜像目录
cd ../plugin/calico/
# 导入所有镜像
docker load -i calico-cni-v3.17.6.tar
docker load -i calico-kube-controllers-v3.17.6.tar
docker load -i calico-node-v3.17.6.tar
docker load -i calico-pod2daemon-flexvol-v3.17.6.tar
3.3 cni和crictl插件安装
bash
# 创建cni安装目录
mkdir -p /opt/cni/bin
# 解压cni和crictl软件包到相应目录
cd /opt/k8s1.22.12/plugin
tar -zxvf cni-plugins-linux-arm64-v1.1.1.tgz -C /opt/cni/bin/
tar -zxvf crictl-v1.25.0-linux-arm64.tar.gz -C /usr/local/bin/
3.4 安装kubeadm、kubelet、kubectl
bash
# 将kubeadm、kubelet、kubectl二进制放入系统/usr/bin路径
cd /opt/k8s1.22.12/
cp kubeadm kubectl kubelet /usr/bin/
# 添加可执行权限
cd /usr/bin/
chmod +x kubeadm kubectl kubelet
# 创建配置文件目录
mkdir -p /etc/systemd/system/kubelet.service.d/
# 将kubelet服务配置文件复制到相应目录
cd /opt/k8s1.22.12/kubelet-service-config/
cp 10-kubeadm.conf /etc/systemd/system/kubelet.service.d/
cp kubelet.service /etc/systemd/system/
# 设置开机自启
systemctl enable --now kubelet
3.5 检查cgroup driver配置
kubelet需要和docker拥有的相同的cgroup才能正常运行,kubelet默认配置文件中cgroup设置为systemd和docker默认的cgroupfs
由于多数linux发行版中cgroup驱动也为systemd,因此k8s社区推荐配置为与系统一致,检查/etc/docker/daemon.json路径下的配置文件是否配置为systemd,如果没有该文件,创建该文件并配置以下内容
bash
# 编辑daemon.json配置文件
vim /etc/docker/daemon.json
# 添加如下内容
{
"exec-opts": ["native.cgroupdriver=systemd"]
}
# 重新加载守护进程
systemctl daemon-reload
# 重启docker
systemctl restart docker
3.6 关闭swap
临时关闭swap命令如下
bash
swapoff -a
永久关闭swap推荐一下两种方式
bash
# 方式1、注释 /etc/fstab 中的 swap 行
# 方式2、设置 sysctl 参数
# 降低 swappiness(设为 0 表示尽量不使用 swap)
echo "vm.swappiness = 0" >> /etc/sysctl.conf
sysctl -p
3.7 检查并安装依赖
k8s部署依赖的软件检查,如果没有安装可以使用如下命令安装
bash
yum install -y curl wget socat conntrack-tools ebtables ipvsadm ipset
3.8 关闭防火墙 和 SELinux(可选)
本次离线安装没有执行也能正常初始化kubeadm
bash
# 关闭防火墙
systemctl stop firewalld
systemctl disable firewalld
# 关闭 SELinux
# 临时关闭 (重启后失效)
setenforce 0
# 永久关闭
sed -i 's/^SELINUX=enforcing$/SELINUX=permissive/' /etc/selinux/config
3.9 配置内核参数(可选)
本次离线安装没有执行也能正常初始化kubeadm
配置内核参数之前,需要先检查一下需要的内核模块是否已经加载。比如初始化的时候就遇到过缺少br_netfilter的情况。详细请见FAQ中初始化常见报错介绍
bash
立即加载模块:在终端执行以下命令,让当前内核会话加载 br_netfilter 模块。
modprobe br_netfilter
验证模块是否加载成功:执行以下命令,如果看到输出,就说明模块已经成功加载。
lsmod | grep br_netfilter
确保重启后模块自动加载:为了确保服务器重启后模块能自动加载,需要将它加入系统的模块配置文件中。
echo 'br_netfilter' | tee -a /etc/modules-load.d/k8s.conf
bash
# 加载内核模块并设置必要的网络参数。
# 创建 K8s 内核参数配置文件
cat <<EOF | tee /etc/sysctl.d/k8s.conf
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
net.ipv4.ip_forward = 1
EOF
# 应用参数
sysctl --system
四、初始化kubeadm
4.1 初始化
登录管理节点,执行初始化操作。工作节点不需要执行。
初始化命令如下
bash
kubeadm init \
--kubernetes-version=v1.22.12 \
--pod-network-cidr=192.168.0.0/16 \
--apiserver-advertise-address=xx.xx.xx.71
初始化成功后的信息记录
bash
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 7.212.76.71:6443 --token w7pxpt.wxamtph9xgax0p24 \
--discovery-token-ca-cert-hash sha256:63b40a84848f8e77e9a84baac8486ab95edae3c08ad2ff1754dbf4c52ac65fe4
初始化成功后根据提示执行如下命令:
bash
mkdir -p $HOME/.kube
cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
chown $(id -u):$(id -g) $HOME/.kube/config
查看组件的运行状态
bash
[root@k8s-master01 kubelet-service-config]# kubectl get pod -A
NAMESPACE NAME READY STATUS RESTARTS AGE
kube-system coredns-78fcd69978-qk6dk 0/1 Pending 0 5m37s
kube-system coredns-78fcd69978-w8kwc 0/1 Pending 0 5m37s
kube-system etcd-k8s-master01 1/1 Running 0 5m51s
kube-system kube-apiserver-k8s-master01 1/1 Running 0 5m51s
kube-system kube-controller-manager-k8s-master01 1/1 Running 0 5m51s
kube-system kube-proxy-8r6nh 1/1 Running 0 5m37s
kube-system kube-scheduler-k8s-master01 1/1 Running 0 5m51s
此时的coredns的pod还是未就绪的状态,原因是还没有部署网络插件calico。所以可以吧网络插件的部署放在查询组件运行状态之前执行。
4.2 部署网络插件calico
bash
# 切换到网络插件calico的目录
cd /opt/k8s1.22.12/plugin/calico/
# 部署calico应用
kubectl apply -f calico.yaml
bash
[root@k8s-master01 bin]# cd /opt/k8s1.22.12/plugin/calico/
[root@k8s-master01 calico]# kubectl apply -f calico.yaml
configmap/calico-config created
customresourcedefinition.apiextensions.k8s.io/bgpconfigurations.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/bgppeers.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/blockaffinities.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/clusterinformations.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/felixconfigurations.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/globalnetworkpolicies.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/globalnetworksets.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/hostendpoints.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/ipamblocks.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/ipamconfigs.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/ipamhandles.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/ippools.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/kubecontrollersconfigurations.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/networkpolicies.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/networksets.crd.projectcalico.org created
clusterrole.rbac.authorization.k8s.io/calico-kube-controllers created
clusterrolebinding.rbac.authorization.k8s.io/calico-kube-controllers created
clusterrole.rbac.authorization.k8s.io/calico-node created
clusterrolebinding.rbac.authorization.k8s.io/calico-node created
daemonset.apps/calico-node created
serviceaccount/calico-node created
deployment.apps/calico-kube-controllers created
serviceaccount/calico-kube-controllers created
Warning: policy/v1beta1 PodDisruptionBudget is deprecated in v1.21+, unavailable in v1.25+; use policy/v1 PodDisruptionBudget
poddisruptionbudget.policy/calico-kube-controllers created
部署完成后查询组件状态
bash
[root@k8s-master01 calico]# kubectl get pod -A
NAMESPACE NAME READY STATUS RESTARTS AGE
kube-system calico-kube-controllers-567bf7f654-lcwdc 1/1 Running 0 30s
kube-system calico-node-kd79l 1/1 Running 0 30s
kube-system coredns-78fcd69978-qk6dk 1/1 Running 0 15m
kube-system coredns-78fcd69978-w8kwc 1/1 Running 0 15m
kube-system etcd-k8s-master01 1/1 Running 0 16m
kube-system kube-apiserver-k8s-master01 1/1 Running 0 16m
kube-system kube-controller-manager-k8s-master01 1/1 Running 0 16m
kube-system kube-proxy-8r6nh 1/1 Running 0 15m
kube-system kube-scheduler-k8s-master01 1/1 Running 0 16m
[root@k8s-master01 calico]# kubectl get nodes
NAME STATUS ROLES AGE VERSION
k8s-master01 Ready control-plane,master 16m v1.22.12
五、添加工作节点
管理节点初始化完成后,输出的有一条命令就是用来给k8s集群添加工作节点的
bash
Then you can join any number of worker nodes by running the following on each as root:
kubeadm join 7.212.76.71:6443 --token w7pxpt.wxamtph9xgax0p24 \
--discovery-token-ca-cert-hash sha256:63b40a84848f8e77e9a84baac8486ab95edae3c08ad2ff1754dbf4c52ac65fe4
待加入的工作节点,必须完成前面步骤的准备工作,才能执行该命令。
bash
[root@k8s-worker01 kubelet-service-config]# systemctl enable --now kubelet
Created symlink /etc/systemd/system/multi-user.target.wants/kubelet.service → /etc/systemd/system/kubelet.service.
[root@k8s-worker01 kubelet-service-config]# kubeadm join 7.212.76.71:6443 --token w7pxpt.wxamtph9xgax0p24 \
--discovery-token-ca-cert-hash sha256:63b40a84848f8e77e9a84baac8486ab95edae3c08ad2ff1754dbf4c52ac65fe4
[preflight] Running pre-flight checks
[preflight] Reading configuration from the cluster...
[preflight] FYI: You can look at this config file with 'kubectl -n kube-system get cm kubeadm-config -o yaml'
[kubelet-start] Writing kubelet configuration to file "/var/lib/kubelet/config.yaml"
[kubelet-start] Writing kubelet environment file with flags to file "/var/lib/kubelet/kubeadm-flags.env"
[kubelet-start] Starting the kubelet
[kubelet-start] Waiting for the kubelet to perform the TLS Bootstrap...
This node has joined the cluster:
* Certificate signing request was sent to apiserver and a response was received.
* The Kubelet was informed of the new secure connection details.
Run 'kubectl get nodes' on the control-plane to see this node join the cluster.
[root@k8s-worker01 kubelet-service-config]#
执行完成后,可以到管理节点查询状态
bash
[root@k8s-master01 calico]# kubectl get nodes
NAME STATUS ROLES AGE VERSION
k8s-master01 Ready control-plane,master 27m v1.22.12
k8s-worker01 Ready <none> 32s v1.22.12