
本文详细描述了部署K8s集群的步骤
前期准备
本文使用K8s的1.28版本。注意,在早期,Docker 是 Kubernetes 主要支持的运行时,Kubernetes 使用了一个叫做 dockershim 的内置组件来连接到 Docker Engine 的 API。但从 Kubernetes 1.24 版本开始,dockershim 被移除了。 这意味着 Kubelet 不再内置与 Docker API 直接通信的能力。本文不使用docker容器运行时,而使用contained。
服务器配置
| 主机名称 | IP | OS | CPU | 内存 | 磁盘 |
|---|---|---|---|---|---|
| bestzy-master | 192.168.154.100 | Ubuntu-22.04-live-server | 2核 | 2G | 30GB |
| bestzy-node1 | 192.168.154.101 | Ubuntu-22.04-live-server | 2核 | 2G | 30GB |
| bestzy-node2 | 192.168.154.102 | Ubuntu-22.04-live-server | 2核 | 2G | 30GB |
更换apt镜像源
如果镜像源是国外的,建议更换为国内的阿里云。
apt镜像源文件一般是/etc/apt/sources.list,建议修改之前先备份该文件。
cp /etc/apt/sources.list /etc/apt/sources.list.bak
然后将用以下内容替换掉/etc/apt/sources.list中的内容。
deb http://mirrors.aliyun.com/ubuntu/ focal main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ focal main restricted universe multiverse
deb http://mirrors.aliyun.com/ubuntu/ focal-security main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ focal-security main restricted universe multiverse
deb http://mirrors.aliyun.com/ubuntu/ focal-updates main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ focal-updates main restricted universe multiverse
deb http://mirrors.aliyun.com/ubuntu/ focal-proposed main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ focal-proposed main restricted universe multiverse
deb http://mirrors.aliyun.com/ubuntu/ focal-backports main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ focal-backports main restricted universe multiverse
固定IP
Netplan 这是 Ubuntu 18.04 LTS 及以后版本使用的默认网络管理工具。它使用 YAML 文件进行配置。
进入/etc/netplan,找到目录下的*.yaml文件,建议先将文件备份。

修改addresses,如下图所示。

修改了/etc/netplan/*.yaml文件后,先执行:
sudo netplan try
这个命令会测试你的 YAML 配置文件的语法是否正确,并尝试应用配置。如果新的配置导致网络中断,它会在指定的时间后自动回滚到之前的配置。这是一个非常有用的安全措施,以防你不小心把自己锁在服务器外面。如果测试成功,它会提示你 “Configuration accepted.” 并让你按 Enter 确认。
然后再执行即可。
sudo netplan apply
这个命令会检查你的 YAML 配置文件的语法,将其翻译成后端(systemd-networkd 或 NetworkManager)可以理解的配置,然后指示后端去应用这些配置。
不过,注释警告说,如果你直接修改这个文件,你的修改可能在系统重启后失效,因为 cloud-init 可能会重新生成或覆盖它。
如果你希望这个静态 IP 配置在重启后依然生效,并且你确定不需要 cloud-init 来管理网络(或者你想通过 cloud-init 的方式去指定这个静态 IP,但这超出了基础的网络文件配置范畴),你需要按照注释中的建议,创建一个文件(例如 /etc/cloud/cloud.cfg.d/99-disable-network-config.cfg)并写入 network: {config: disabled} 来禁用 cloud-init 的网络配置功能。
禁用swap分区
在/etc/fstab文件中注视掉交换内存

将桥接的IPv4流量传递到iptables的链
# 确保 br_netfilter 模块已加载
sudo modprobe br_netfilter
# 创建或编辑 sysctl 配置文件
echo "net.bridge.bridge-nf-call-iptables = 1" | sudo tee /etc/sysctl.d/k8s.conf
echo "net.bridge.bridge-nf-call-ip6tables = 1" | sudo tee -a /etc/sysctl.d/k8s.conf # -a 参数表示追加而非覆盖
# 应用 sysctl 配置
sudo sysctl --system
- br_netfilter 模块: 这个内核模块是实现网络桥接流量与 netfilter(iptables) 框架集成的关键。加载这个模块后,Linux 内核就具备了让桥接流量通过 iptables 的能力。
- net.bridge.bridge-nf-call-iptables = 1: 这个内核参数(通过 sysctl 设置)是告诉内核,当 br_netfilter 模块加载时,对于桥接流量,是否要将它们传递给 iptables 的链进行处理。设置为 1 表示“是,将桥接流量也发送给 iptables 处理”。
当一个 Pod 尝试访问同一节点上的另一个 Pod 通过其 Service IP 时,流量可能会通过本地的网络桥接。Linux 内核的 iptables/netfilter 框架非常强大,可以检查和修改网络数据包。然而,默认情况下,流经网络桥接的流量可能 不会经过标准的 iptables 链。它们可能在网络桥接内部就被直接转发了。
如果 bridge-nf-call-iptables 没有启用 (=0),那么这个流量在经过桥接时,很可能就不会被 kube-proxy 设置的那些将 Service IP 转发到 Pod IP 的 iptables 规则所捕获和处理。结果就是,访问 Service IP 的请求无法正确地转发到后端的 Pod,导致网络不通或服务访问失败。
启用 bridge-nf-call-iptables=1 确保了即使是流经网络桥接的数据包,也会被 iptables 规则检查到,这样 kube-proxy 设置的 Service 转发规则才能正确应用,保证集群内部 Service 的可达性。
安装
Kube三件套
kubectl kubelet kubeadm 三件套需要安装公共签名密钥
| 特性 | kubeadm | kubectl | kubelet |
|---|---|---|---|
| 主要角色 | 集群引导/安装工具 | 集群命令行客户端/管理工具 | 节点代理/执行者 |
| 做什么 | 搭建集群骨架,安装配置核心组件/节点 | 与 API Server 交互,管理应用和集群资源 | 运行在节点上,根据 API Server 指令管理容器 |
| 在哪里运行 | 在需要安装/加入集群的服务器上手动执行 | 在用户的本地机器或管理服务器上执行 | 集群的每个节点上 作为一个服务持续运行 |
| 谁使用 | 集群管理员/搭建者 | 所有与集群交互的用户(开发者、运维、管理员) | Kubernetes 系统本身(内部组件) |
| 与谁交互 | 系统服务、容器运行时、生成配置/证书等 | Kubernetes API Server | API Server 和 容器运行时 |
| 生命周期 | 执行命令时运行 | 执行命令时运行 | 节点运行期间持续运行为一个服务 |
| 目的 | 集群 Setup | 集群 Operation/Management | 节点 Pod/Container Execution |
- 安装必要的包
先更新包版本,安装一些必须的包——apt-transport-https、ca-certificates、curl、gpg,
- apt-transport-https: 如果需要的话,安装这个包以支持 HTTPS 协议的软件源。
- 一般较新的apt通常已经内置了 HTTPS 支持,所以这个包有时是虚拟的或不必要的。如果是的话,我们可以跳过这个包。
- ca-certificates: 安装包含公共证书颁发机构证书的软件包。这让你的系统能够验证通过 SSL/TLS 连接(如 HTTPS)下载的数据的来源是否可信。
- curl: 安装一个强大的命令行工具,用于通过各种协议(包括 HTTPS)传输数据。这里用于下载 Kubernetes 软件源的 GPG 密钥。
- gpg: 安装 GNU Privacy Guard 工具,用于处理加密签名。这里用于处理下载的 GPG 密钥,以便 apt 能够验证软件包的真实性。
sudo apt-get update && sudo apt-get install -y apt-transport-https ca-certificates curl gpg
- 添加GPG签名密钥
从阿里云下载用于验证其软件包的公钥,并将其安全地存储到 APT 的密钥环目录中,以便 apt 在下载和安装 Kubernetes 软件包时可以验证其签名。
注意: 这里的 URL ( /v1.28/ ) 指定了是针对 v1.28 版本的密钥,这表明你后续安装的软件包将是 v1.28 或兼容版本。
sudo curl -fsSL https://mirrors.aliyun.com/kubernetes-new/core/stable/v1.28/deb/Release.key | sudo gpg --dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring.gpg
- 添加镜像源
将 Kubernetes 软件包源的配置信息(指向阿里云镜像站的 v1.28 版本源,并指定用于验证签名的 GPG 密钥文件)写入到 /etc/apt/sources.list.d/ 目录下的 kubernetes.list 文件中。
echo "deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.gpg] https://mirrors.aliyun.com/kubernetes-new/core/stable/v1.28/deb/ /" | sudo tee /etc/apt/sources.list.d/kubernetes.list
- 安装三件套
sudo apt-get update && sudo apt-get install -y kubelet kubeadm kubectl
安装完成后运行kubelet
sudo systemctl enable kubelet
sudo systemctl start kubelet
安装Containerd
安装containerd与安装docker流程基本一致,差别在于不需要安装docker-ce。
- 安装必要的包
lsb-release显示关于 Linux Standard Base (LSB) 和 Linux 发行版的信息。
sudo apt install lsb-release
- 添加GPG签名
curl -fsSL http://mirrors.aliyun.com/docker-ce/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker-apt-keyring.gpg
- 添加镜像仓库
使用 $(lsb_release -cs) 可以确保 APT 仓库的配置指向适用于你当前 Ubuntu 版本的 Docker 软件包目录,避免安装了不兼容的软件包。
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker-apt-keyring.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list
- 安装
sudo apt-get update && sudo apt-get install -y containerd.io
查看运行状态
sudo systemctl enable containerd
sudo systemctl start containerd
sudo systemctl status containerd
- 修改配置
先生成containerd的默认配置
sudo containerd config default | sudo tee /etc/containerd/config.toml
再修改CgroupDriver为systemd,k8s官方推荐使用systemd类型的CgroupDriver
[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc]
...
[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc.options]
SystemdCgroup = true
接下来修改镜像源,找到registry.mirrors所在位置,添加如下所示配置。
docker.io是 Docker Hub 的官方地址,绝大多数公共镜像都来源于此,配置docker.io的加速器是最常见的需求。- 对于 Kubernetes 自己的核心镜像 (如 kube-apiserver, kube-controller-manager 等),在 Kubernetes 1.25 之前它们主要托管在
k8s.gcr.io,1.25 及之后迁移到了registry.k8s.io。我们将registry.k8s.io加速。
[plugins."io.containerd.grpc.v1.cri".registry]
config_path = ""
[plugins."io.containerd.grpc.v1.cri".registry.auths]
[plugins."io.containerd.grpc.v1.cri".registry.configs]
[plugins."io.containerd.grpc.v1.cri".registry.headers]
[plugins."io.containerd.grpc.v1.cri".registry.mirrors]
[plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"]
endpoint=["https://docker.m.daocloud.io"]
[plugins."io.containerd.grpc.v1.cri".registry.mirrors."registry.k8s.io"]
endpoint=["https://k8s.m.daocloud.io"]
最后,重启containerd
sudo systemctl restart containerd
可以执行以下命令查看是否将镜像修改成功。
sudo crictl info
如下图所示,表示成功了。

部署
Master节点初始化
在bestzy-master主机上,执行以下代码。
sudo kubeadm init \
--apiserver-advertise-address=192.168.154.100 \
--image-repository registry.aliyuncs.com/google_containers \
--kubernetes-version v1.28.15 \
--service-cidr=10.96.0.0/12 \
--pod-network-cidr=10.244.0.0/16
- –apiserver-advertise-address : 填控制平面节点本机的、其他节点可以访问到的 IP 地址。
- 用
ip a或ifconfig查看。在输出中找到你连接内网的那个网络接口(比如 eth0 或 ens33 等),找到它对应的 inet 地址。这个地址就是你可以填写的--apiserver-advertise-address。
- 用
- –image-repository :使用这个参数指定其他的镜像仓库,例如阿里云的
registry.aliyuncs.com/google_containers。这样 kubeadm 就会从这里拉取控制平面组件的镜像。 - –kubernetes-version : 指定要安装的 Kubernetes 版本,例如 v1.28.15。如果不指定,会使用当前安装的 kubeadm 适配的默认版本。
- –pod-network-cidr : 填一个为 Pod 准备的、未被占用的、不与你的宿主机网络和 Service 网络冲突 的 IP 地址段。这个参数通常取决于你选择的 CNI 插件,例如 Flannel 的 10.244.0.0/16 或 Calico 的 192.168.0.0/16。
- –service-cidr : 填一个为 Service 准备的、未被占用的、不与你的宿主机网络和 Pod 网络冲突 的 IP 地址段。常见的选择是 10.96.0.0/12。
显示 successfully 表示初始化成功

修改目录权限
要想使相关的组件可以正常使用,我们还需要按提示将目录、权限设置成功。
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
添加Node节点
如提示所示,我们需要在bestzy-node1、bestzy-node2主机上,分别执行以下命令。
kubeadm join 192.168.154.100:6443 --token h1wtmw.rr8v9m4ym61wsd6d \
--discovery-token-ca-cert-hash sha256:5b4156b9e5849143330015a8e5912ec7ae345d3783a783a3872aa152a85df0c4
但默认的token有效期为24小时,当过期之后,该token就不能用了,这时可以使用如下的命令创建token:
kubeadm token create --print-join-command
成功添加Node节点后会显示如下文字。
部署CNI网络插件
根据提示,在Master节点使用kubectl工具查看节点状态:
kubectl get nodes

kubeadm init 命令负责初始化 Kubernetes 控制平面。它会下载并启动控制平面所需的组件:kube-apiserver, kube-controller-manager, kube-scheduler, etcd 等。
但kubeadm init并没有部署一个实际的 Pod 网络 来满足上面提到的 Pod 之间直接通信的要求。它设置了网络环境的基础,但它没有提供一个具体的网络实现方案来分配 Pod IP 并处理跨节点的数据包转发。
总而言之,kubeadm init 只搭建了骨架,如果没有部署 CNI 插件,那么 kubelet 在尝试启动 Pod 时,会发现没有组件可以为其配置网络接口和 IP 地址(这是 Pod 启动流程中的关键一步)。
此处,我们选择https://github.com/flannel-io/flannel,进行快速部署
注意,该命令不能使用sudo,当你使用 sudo 执行 kubectl 命令时,命令是以 root 用户的身份运行的。 kubectl 在查找其配置(kubeconfig 文件,通常是 ~/.kube/config)时,会去 root 用户的home目录,也就是 /root/.kube/config。而我们之前配置 kubectl 的步骤(将 /etc/kubernetes/admin.conf 复制到 ~/.kube/config 并修改权限)这些命令是为当前登录用户配置的。
kubectl apply -f https://github.com/flannel-io/flannel/releases/latest/download/kube-flannel.yml

去除污点
污点(Taint)是标记节点的一种方式,用来阻止某些 Pod 调度到该节点上。
初始情况下,master是污点节点,我们可以选择性的为它去除污点。
kubectl describe node bestzy-master | grep -i taint
命令将输出:

执行以下命令(注意末尾的-)将移除污点。
kubectl taint node bestzy-master node-role.kubernetes.io/control-plane:NoSchedule-
测试
部署nginx
尝试部署一个简单的应用程序,验证 Pod 是否可以被调度到节点上并成功运行。
kubectl create deployment nginx --image=nginx
预期输出: 会创建名为 nginx 的 Deployment。
检查状态
检查 nginx Deployment 的状态,以及它创建的 Pod 的状态。
kubectl get deployments
kubectl get pods
Pod 的状态应该最终变为 Running。
kubectl get pods -o wide 可以看到 Pod 被调度到了哪个节点上。
