安装Kubernetes,容器为containerd
背景介绍
Kubernetes(简称K8s)是一个开源的、用于自动化容器化应用程序部署、扩展和管理的系统。随着技术的不断发展,Kubernetes的版本也在不断更新,但网上大部分的Kubernetes安装教程仍然停留在较旧的版本上。这些教程中,容器运行时通常是以Docker为例,镜像源则多使用已经关闭的阿里云等国内镜像地址,且ServiceAccount的Secret通常是自动生成的。
然而,在最新的Kubernetes版本中,这些方面都发生了显著的变化。首先,从Kubernetes 1.20版本开始,官方已经逐步放弃对Docker的支持,默认容器运行时已经改为了containerd。这一变化旨在提高性能和安全性,因为containerd更轻量级,并且与Kubernetes集成更紧密。其次,由于各种原因,国内的一些镜像地址,包括阿里云、腾讯云以及各大高校提供的镜像源,已经全部关闭,这给国内用户在使用Kubernetes时带来了一定的不便。最后,在Kubernetes v1.24.0更新之后,创建ServiceAccount时不会自动生成Secret,需要手动创建,这一变更也需要注意。
因此,本文将详细介绍如何在最新的Kubernetes版本中,从零开始部署一个Kubernetes集群,并特别注意上述变化点。
准备开始
- 一台兼容的 Linux 主机。Kubernetes 项目为基于 Debian 和 Red Hat 的 Linux 发行版以及一些不提供包管理器的发行版提供通用的指令。
- 每台机器 2 GB 或更多的 RAM(如果少于这个数字将会影响你应用的运行内存)。
- 控制平面机器需要 CPU 2 核心或更多。
- 集群中的所有机器的网络彼此均能相互连接(公网和内网都可以)。
- 节点之中不可以有重复的主机名、MAC 地址或 product_uuid。请参见这里了解更多详细信息。
- 开启机器上的某些端口。请参见这里了解更多详细信息。
- 交换分区的配置。kubelet 的默认行为是在节点上检测到交换内存时无法启动。 更多细节参阅交换内存管理。
- 如果 kubelet 未被正确配置使用交换分区,则你必须禁用交换分区。 例如,
sudo swapoff -a
将暂时禁用交换分区。要使此更改在重启后保持不变,请确保在如/etc/fstab
、systemd.swap
等配置文件中禁用交换分区,具体取决于你的系统如何配置。
- 如果 kubelet 未被正确配置使用交换分区,则你必须禁用交换分区。 例如,
步骤详解
步骤1: 设置主机名和hosts文件
#查看本机hostname
hostname
若有重复的主机名使用下面命令进行修改
假设我们有以下三台机器:
- k8s-master: 172.16.196.23
- k8s-node1: 172.16.196.24
- k8s-node2: 172.16.196.25
在每台机器上修改主机名,并更新/etc/hosts
文件,使各节点可以相互通信。
# 在k8s-master上执行
hostnamectl set-hostname k8s-master
# 在k8s-node1上执行
hostnamectl set-hostname k8s-node1
# 在k8s-node2上执行
hostnamectl set-hostname k8s-node2
步骤2: 关闭swap分区
Kubernetes不支持开启swap分区的系统。关闭swap并注释掉/etc/fstab
中的swap条目以防止重启后swap重新启用。
swapoff -a # 临时禁用
sed -ri 's/.*swap.*/#&/' /etc/fstab # 永久禁用
步骤3: 添加Kubernetes仓库
创建一个名为 kubernetes.repo
的文件在 /etc/yum.repos.d/
目录下,并添加官方的Kubernetes YUM仓库。
cat <<EOF | sudo tee /etc/yum.repos.d/kubernetes.repo
[kubernetes]
name=Kubernetes
baseurl=https://mirrors.aliyun.com/kubernetes-new/core/stable/v1.30/rpm/
enabled=1
gpgcheck=1
gpgkey=https://mirrors.aliyun.com/kubernetes-new/core/stable/v1.30/rpm/repodata/repomd.xml.key
EOF
步骤4: 安装Kubernetes三大件:kubeadm、kubelet 和 kubectl
在每台机器上安装以下的软件包:
sudo yum install -y kubelet kubeadm kubectl --disableexcludes=kubernetes
sudo systemctl enable --now kubelet
如果要安装以前的版本,可以直接指定版本号,例如
sudo yum install -y kubelet-1.20.9 kubeadm-1.20.9 kubectl-1.20.9 --disableexcludes=kubernetes
kubeadm
:用来初始化集群的指令。kubelet
:在集群中的每个节点上用来启动 Pod 和容器等。kubectl
:用来与集群通信的命令行工具。
kubeadm 不能帮你安装或者管理 kubelet
或 kubectl
, 所以你需要确保它们与通过 kubeadm 安装的控制平面的版本相匹配。 如果不这样做,则存在发生版本偏差的风险,可能会导致一些预料之外的错误和问题。 然而,控制平面与 kubelet 之间可以存在一个次要版本的偏差,但 kubelet 的版本不可以超过 API 服务器的版本。 例如,1.7.0 版本的 kubelet 可以完全兼容 1.8.0 版本的 API 服务器,反之则不可以。
有关安装 kubectl
的信息,请参阅安装和设置 kubectl 文档。
kubeadm 中 kubelet 的版本偏差
与 Kubernetes 版本类似,kubeadm 可以使用与 kubeadm 相同版本的 kubelet, 或者比 kubeadm 老三个版本的 kubelet。
例子:
- kubeadm 的版本为 1.32。
- 主机上的 kubelet 必须为 1.32、1.31、 1.30 或 1.29。
kubeadm 支持的 kubeadm 的版本偏差
kubeadm 命令在现有节点或由 kubeadm 管理的整个集群上的操作有一定限制。
如果新的节点加入到集群中,用于 kubeadm join
的 kubeadm 二进制文件必须与用 kubeadm init
创建集群或用 kubeadm upgrade
升级同一节点时所用的 kubeadm 版本一致。 类似的规则适用于除了 kubeadm upgrade
以外的其他 kubeadm 命令。
kubeadm join
的例子:
- 使用
kubeadm init
创建集群时使用版本为 1.32 的 kubeadm。 - 添加节点所用的 kubeadm 可执行文件为版本 。
对于正在升级的节点,所使用的的 kubeadm 必须与管理该节点的 kubeadm 具有相同的 MINOR 版本或比后者新一个 MINOR 版本。
kubeadm upgrade
的例子:
- 用于创建或升级节点的 kubeadm 版本为 1.31。
- 用于升级节点的 kubeadm 版本必须为 1.31 或 1.32。
要了解更多关于不同 Kubernetes 组件之间的版本偏差, 请参见版本偏差策略。
查看kubeadm、kubelet 和 kubectl版本的命令
kubeadm version
kubelet --version
kubectl version
初始化控制平面节点准备
控制平面节点是运行控制平面组件的机器, 包括 etcd(集群数据库) 和 API 服务器 (命令行工具 kubectl 与之通信)。
- (推荐)如果计划将单个控制平面 kubeadm 集群升级成高可用, 你应该指定
-control-plane-endpoint
为所有控制平面节点设置共享端点。 端点可以是负载均衡器的 DNS 名称或 IP 地址。 - 选择一个 Pod 网络插件,并验证是否需要为
kubeadm init
传递参数。 根据你选择的第三方网络插件,你可能需要设置-pod-network-cidr
的值。 请参阅安装 Pod 网络附加组件。 - (可选)
kubeadm
试图通过使用已知的端点列表来检测容器运行时。 使用不同的容器运行时或在预配置的节点上安装了多个容器运行时,请为kubeadm init
指定-cri-socket
参数。 请参阅安装运行时。
要初始化控制平面节点,请运行:
# 以下是示例,无须执行
`kubeadm init <args>`
关于 apiserver-advertise-address 和 ControlPlaneEndpoint 的注意事项
-apiserver-advertise-address
可用于为控制平面节点的 API 服务器设置广播地址,-control-plane-endpoint
可用于为所有控制平面节点设置共享端点。-control-plane-endpoint
允许 IP 地址和可以映射到 IP 地址的 DNS 名称。 请与你的网络管理员联系,以评估有关此类映射的可能解决方案。
这是一个示例映射:
192.168.0.102 cluster-endpoint
其中 192.168.0.102
是此节点的 IP 地址,cluster-endpoint
是映射到该 IP 的自定义 DNS 名称。 这将允许你将 --control-plane-endpoint=cluster-endpoint
传递给 kubeadm init
, 并将相同的 DNS 名称传递给 kubeadm join
。稍后你可以修改 cluster-endpoint
以指向高可用性方案中的负载均衡器的地址。
kubeadm 不支持将没有 --control-plane-endpoint
参数的单个控制平面集群转换为高可用性集群。
步骤5: 添加master域名映射
#查看master节点ip地址
ifconfig
#所有机器添加master域名映射
echo "10.211.55.5 cluster-endpoint" >> /etc/hosts
测试通信
# 执行看是否能联通
ping cluster-endpoint
步骤6: 启用 IPv4 数据包转发
默认情况下,Linux 内核不允许 IPv4 数据包在接口之间路由。 大多数 Kubernetes 集群网络实现都会更改此设置(如果需要),但有些人可能希望管理员为他们执行此操作。 (有些人可能还期望设置其他 sysctl 参数、加载内核模块等;请参阅你的特定网络实施的文档。)
手动启用 IPv4 数据包转发:
# 设置所需的 sysctl 参数,参数在重新启动后保持不变
cat <<EOF | sudo tee /etc/sysctl.d/k8s.conf
net.ipv4.ip_forward = 1
EOF
# 应用 sysctl 参数而不重新启动
sudo sysctl --system
使用以下命令验证 net.ipv4.ip_forward
是否设置为 1:
sysctl net.ipv4.ip_forward
步骤7: 安装containerd
-
添加 containerd 的官方仓库
首先,确保你有一个稳定的软件包源。你可以使用阿里云的镜像源来加快下载速度:wget -O /etc/yum.repos.d/docker-ce.repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
#查看yum源中containerd软件 yum list | grep containerd
-
安装 containerd
使用 yum 安装 containerd:sudo yum install -y containerd.io
-
启用并启动 containerd 服务
安装完成后,启用并启动 containerd 服务:sudo systemctl enable --now containerd
-
检查 containerd 状态
确认 containerd 已成功启动并正在运行:sudo systemctl status containerd
5. 配置 containerd
重新生成一个默认配置,修改下面4处:
# sudo mkdir -p /etc/containerd
sudo containerd config default | sudo tee /etc/containerd/config.toml
# sudo mkdir -p /etc/containerd
vim /etc/containerd/config.toml
SystemdCgroup
:此配置改为 SystemdCgroup = truedisabled_plugins
:此配置不能存在cri
,如果用此配置,需要删除。sandbox_image
改为 "registry.aliyuncs.com/google_containers/pause:3.6plugins."io.containerd.grpc.v1.cri".registry.mirrors
: 添加镜像加速地址,国内的一些镜像地址,包括阿里云、腾讯云以及各大高校提供的镜像源,已经全部关闭。可用镜像地址需要自行搜索,找到两篇文章:2025年1月国内可用Docker镜像源汇总、DockerHub 国内加速镜像列表,里面镜像地址是否可用自行测试!
[plugins."io.containerd.grpc.v1.cri".registry.mirrors]
[plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"]
endpoint = ["https://1ms.run"]
[plugins."io.containerd.grpc.v1.cri".registry.mirrors."registry.k8s.io"]
endpoint = ["https://1ms.run"]
修改完成,重启containerd
sudo systemctl restart containerd
步骤7: 初始化主节点
在主节点上执行以下命令初始化集群:
kubeadm init --kubernetes-version v1.30.8 --apiserver-advertise-address=10.211.55.5 --control-plane-endpoint=cluster-endpoint --pod-network-cidr=192.168.0.0/16 --service-cidr=10.1.0.0/16 --image-repository registry.aliyuncs.com/google_containers --v=5
这条命令是用于初始化一个 Kubernetes (K8s) 集群的 kubeadm init
命令,其中包含了一系列参数来配置集群的特定设置。下面是对这个命令中各个参数的解释:
kubeadm init
: 这是 Kubernetes 提供的用于初始化新集群的命令。它会安装必要的 Kubernetes 控制平面组件,并配置一个本地的 kubeadm-kubelet 客户端。-apiserver-advertise-address=10.211.55.5
: 这个参数设置了 Kubernetes API 服务器的监听地址,这个地址用于集群内部通信。你应该将其设置为你希望 API 服务器监听的 IP 地址,是主节点master的ip地址
。--control-plane-endpoint
:此参数用于指定Kubernetes控制平面的访问端点。在集群环境中,控制平面负责处理集群的API请求、调度Pod等核心任务。通过该参数,可以设定一个统一的访问地址,使得集群内外的客户端都能方便地访问到控制平面。这个地址通常是一个负载均衡器的DNS名称或IP地址,用于将请求分发到集群中的各个控制平面节点。此处设置上面hosts设置的master域名映射的域名
。-pod-network-cidr=192.168.0.0/16
: 这个参数指定了 Pod 网络的 CIDR(无类别域间路由)范围。这是集群内 Pod IP 地址的分配范围。选择一个不与你的其他网络重叠的范围是很重要的。-service-cidr=10.1.0.0/16
: 这个参数设置了 Service 的 CIDR 范围。Service 是 Kubernetes 中的一个抽象层,它定义了一个逻辑集合和访问它们的策略。这个范围用于分配 Service 的 ClusterIP 地址。-image-repository registry.aliyuncs.com/google_containers
: 这个参数用于指定 Kubernetes 镜像的仓库地址。在这个例子中,它使用阿里云的镜像仓库来代替默认的 Google 镜像仓库。这通常用于在中国大陆部署 Kubernetes 集群,因为直接访问 Google 镜像仓库可能会受到网络限制。
apiserver-advertise-address、service-cidr、pod-network-cidr 三者的IP网段确保不能重叠,pod-network-cidr、service-cidr可以直接使用示例中的,这两个网段是留给内网的
运行这个命令后,如果一切配置正确,你将看到一个成功消息,包括如何配置你的 kubectl(Kubernetes 命令行工具)以便与你的新集群通信的指令。此外,你可能还需要安装一个网络插件(如 Flannel、Calico 等),以完成 Pod 网络的配置。
[addons] Applied essential addon: kube-proxy
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/
You can now join any number of control-plane nodes by copying certificate authorities
and service account keys on each node and then running the following as root:
kubeadm join cluster-endpoint:6443 --token emo01i.1k9co48bf6o5end8 \
--discovery-token-ca-cert-hash sha256:dbad3d1197b173b2c94ebd6e2f39f38cdbe3fd9fe61f0be8c81256df0768e567 \
--control-plane
Then you can join any number of worker nodes by running the following on each as root:
kubeadm join cluster-endpoint:6443 --token emo01i.1k9co48bf6o5end8 \
--discovery-token-ca-cert-hash sha256:dbad3d1197b173b2c94ebd6e2f39f38cdbe3fd9fe61f0be8c81256df0768e567
根据提示执行:
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
查看node和pod
kubectl get nodes -A
kubectl get pods -A
至此,主节点已经搭建完成并成功启动,如果需要加入其他主节点,需要在其他主节点的机器上运行上面那条join命令,如果要加入从节点,需要执行下面那条join。如果token过期,可以使用下面命令重新生成:
kubeadm token create --print-join-command
下一篇将介绍配置集群访问和部署 Pod 网络