k8s集群搭建与部署详解

2025-05-12T21:18:28+08:00 | 9分钟阅读

bestzy
k8s集群搭建与部署详解

本文详细描述了部署K8s集群的步骤

前期准备

本文使用K8s的1.28版本。注意,在早期,Docker 是 Kubernetes 主要支持的运行时,Kubernetes 使用了一个叫做 dockershim 的内置组件来连接到 Docker Engine 的 API。但从 Kubernetes 1.24 版本开始,dockershim 被移除了。 这意味着 Kubelet 不再内置与 Docker API 直接通信的能力。本文不使用docker容器运行时,而使用contained。

服务器配置

主机名称IPOSCPU内存磁盘
bestzy-master192.168.154.100Ubuntu-22.04-live-server2核2G30GB
bestzy-node1192.168.154.101Ubuntu-22.04-live-server2核2G30GB
bestzy-node2192.168.154.102Ubuntu-22.04-live-server2核2G30GB

更换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 三件套需要安装公共签名密钥

特性kubeadmkubectlkubelet
主要角色集群引导/安装工具集群命令行客户端/管理工具节点代理/执行者
做什么搭建集群骨架,安装配置核心组件/节点与 API Server 交互,管理应用和集群资源运行在节点上,根据 API Server 指令管理容器
在哪里运行在需要安装/加入集群的服务器上手动执行在用户的本地机器或管理服务器上执行集群的每个节点上 作为一个服务持续运行
谁使用集群管理员/搭建者所有与集群交互的用户(开发者、运维、管理员)Kubernetes 系统本身(内部组件)
与谁交互系统服务、容器运行时、生成配置/证书等Kubernetes API ServerAPI Server 和 容器运行时
生命周期执行命令时运行执行命令时运行节点运行期间持续运行为一个服务
目的集群 Setup集群 Operation/Management节点 Pod/Container Execution
  1. 安装必要的包

先更新包版本,安装一些必须的包——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
  1. 添加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
  1. 添加镜像源

将 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
  1. 安装三件套
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。

  1. 安装必要的包

lsb-release显示关于 Linux Standard Base (LSB) 和 Linux 发行版的信息。

sudo apt install lsb-release
  1. 添加GPG签名
curl -fsSL http://mirrors.aliyun.com/docker-ce/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker-apt-keyring.gpg
  1. 添加镜像仓库

使用 $(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
  1. 安装
sudo apt-get update && sudo apt-get install -y containerd.io

查看运行状态

sudo systemctl enable containerd
sudo systemctl start containerd
sudo systemctl status containerd
  1. 修改配置

先生成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 aifconfig 查看。在输出中找到你连接内网的那个网络接口(比如 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-node1bestzy-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节点后会显示如下文字。

img

部署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 被调度到了哪个节点上。

参考链接

© 2025 Bestzy's Blog

🌱 Powered by Hugo with theme Dream.

About Me

👋 Hi, This is Zheng Yi.