适用环境CentOS 7.9 / Rocky Linux 7.9 |容器运行时Containerd |网络插件Calico架构1 Master 2 Node |模式全离线Air-Gap目录 一、 什么是 Kubernetes (K8s)1. 基础定义2. 它有什么用 前言️ 第一阶段所有节点通用系统初始化Master Node1 Node21. 设置主机名与 Hosts 解析2. 关闭防火墙与 SELinux3. 关闭 Swap4. 加载内核模块与网络参数5. 时间同步与时区设置 第二阶段所有节点部署 Containerd**(Master Node1 Node2)**1. 解压离线包并安装 Containerd2. 配置 Containerd3. 启动并验证服务4. 导入离线镜像核心步骤5.确认containerd健康⚙️ 第三阶段所有节点安装 K8s 核心组件1. 导入安装 kubeadm, kubelet, kubectl2. 版本一致性校验 第四阶段仅在 Master 节点初始化集群1. 清理旧环境如果是重装2. 执行 kubeadm init3. 配置 kubectl 凭证4. 验证控制平面5. 移除 Master 污点 (可选方便单节点测试)6. 部署 Calico 网络插件7. 验证 Master 节点状态➕ 第五阶段Worker 节点加入集群1. 在 Master 生成 Token2. 在 Node 节点执行 Join 命令 第六阶段集群验证与测试1. 查看节点状态2. 检查系统 Pod3. 创建测试 Pod 验证网络⚠️ 避坑指南小白必看 总结 一、 什么是 Kubernetes (K8s)在开始部署之前我们需要先搞清楚K8s 到底是什么它能干什么1. 基础定义Kubernetes简称 K8sK 和 s 之间有 8 个字母是一个开源的容器编排引擎。如果把 Docker 比作“集装箱卡车”负责运行应用那么 Kubernetes 就是“港口调度系统”负责管理成千上万辆卡车。2. 它有什么用在微服务时代应用被拆分成无数个小容器。如果没有 K8s你需要手动去每台服务器启动、停止、重启容器。K8s 的核心价值在于自动化部署与回滚一键发布新版本出问题自动回退。服务发现与负载均衡自动分配 IP 和 DNS 名称流量自动分摊。自我修复某个容器挂了K8s 会自动拉起一个新的保证服务不中断。弹性伸缩流量大了自动增加容器数量流量小了自动减少节省资源。 前言在生产环境中服务器往往无法直接访问互联网。本文档记录了从零开始在完全离线的环境下部署一套高可用、稳定的 Kubernetes v1.24.17 集群的全过程。集群规划IP 地址主机名角色192.168.30.153k8s-masterMaster 节点192.168.30.154k8s-node1Worker 节点192.168.30.155k8s-node2Worker 节点**准备工作**请提前下载好离线包k8s-offline-full.tar.gz并上传至三台服务器的/root目录。️ 第一阶段所有节点通用系统初始化Master Node1 Node2注意以下命令需要在三台机器上分别执行。1. 设置主机名与 Hosts 解析**设置主机名**根据规划分别设置每台机器的主机名。# 在 192.168.30.153 上执行 hostnamectl set-hostname k8s-master # 在 192.168.30.154 上执行 hostnamectl set-hostname k8s-node1 # 在 192.168.30.155 上执行 hostnamectl set-hostname k8s-node2**配置 Hosts 文件**在三台机器上执行相同的命令确保节点间可以通过主机名互相访问。cat /etc/hosts EOF 192.168.30.153 k8s-master 192.168.30.154 k8s-node1 192.168.30.155 k8s-node2 EOF**验证解析**执行以下脚本确保输出结果中所有项均为✓ 成功。for node in k8s-master k8s-node1 k8s-node2; do echo 测试节点: $node echo -n 主机名解析: if ping -c 1 -W 1 $node /dev/null 21; then echo ✓ 成功; else echo ✗ 失败; fi ip$(grep $node /etc/hosts | awk {print $1}) echo 对应 IP: $ip echo -n IP 连通性: if ping -c 1 -W 1 $ip /dev/null 21; then echo ✓ 成功; else echo ✗ 失败; fi echo -n hosts 记录: grep $node /etc/hosts || echo 未找到 echo done #额外验证反向测试 for ip in 192.168.30.153 192.168.30.154 192.168.30.155; do echo -n 连接到 $ip: if ping -c 1 -W 1 $ip /dev/null 21; then echo ✓ 可达 else echo ✗ 不可达 fi done #检验主机名唯一性 for node in k8s-master k8s-node1 k8s-node2; do printf %-15s %-20s $node $(grep $node /etc/hosts | awk {print $1}) if ping -c 1 -W 1 $node /dev/null 21; then echo ✓ 连通正常 else echo ✗ 无法连通 fi done echo hosts 文件配置验证: cat /etc/hosts | grep -E k8s-master|k8s-node1|k8s-node22. 关闭防火墙与 SELinux为了避免网络拦截和权限问题我们需要关闭防火墙和 SELinux。# 关闭防火墙 systemctl stop firewalld systemctl disable firewalld # 临时关闭 SELinux setenforce 0 # 永久关闭 SELinux重启生效 sed -i s/^SELINUXenforcing$/SELINUXdisabled/ /etc/selinux/config3. 关闭 SwapKubernetes 官方强烈建议关闭 Swap 分区以获得更好的性能。# 临时关闭 swapoff -a # 永久关闭注释掉 fstab 中的 swap 行 sed -i / swap / s/^\(.*\)$/#\1/g /etc/fstab4. 加载内核模块与网络参数配置网络桥接和流量转发这是 K8s 网络工作的基础。# 加载模块 modprobe br_netfilter modprobe overlay # 写入永久配置 cat /etc/sysctl.d/k8s.conf EOF net.bridge.bridge-nf-call-iptables 1 net.bridge.bridge-nf-call-ip6tables 1 net.ipv4.ip_forward 1 EOF # 使配置立即生效 sysctl --system5. 时间同步与时区设置集群内时间必须一致误差不能超过几秒。# 启动并设置开机自启 chronyd 服务 systemctl start chronyd systemctl enable chronyd # 设置时区为上海 timedatectl set-timezone Asia/Shanghai # 查看状态关键指标 NTP synchronized: yes timedatectl status /#方法一使用 chronyc 检查推荐 # 1. 查看时间同步源 chronyc sources -v # 2. 查看时间同步状态核心指标 chronyc tracking /#方法二使用 timedatectl 检查 #这个命令可以一眼看出系统时钟是否已同步。 timedatectl status #验证要点必须全部满足 #NTP enabled: yes #NTP synchronized: yes #这是最关键的指标表示已成功同步 #System clock synchronized: yes #Time zone: Asia/Shanghai #RTC in local TZ: no #建议设为 no避免双系统时间错乱**集群时间一致性校验**在 Master 节点执行确保所有节点时间一致/# 方法三集群内多节点一致性校验For 循环 for node in k8s-master k8s-node1 k8s-node2; do echo -n $node 时间: ssh $node date %Y-%m-%d %H:%M:%S done 第二阶段所有节点部署 Containerd**(Master Node1 Node2)**注意以下命令需要在三台机器上分别执行。1. 解压离线包并安装 Containerdcd /root tar -xvzf k8s-offline-full.tar.gz cd /root/k8s-offline/rpms/ # 使用 yum localinstall 解决依赖关系 yum localinstall -y containerd.io-1.6.21-3.1.el7.x86_64.rpm container-selinux-2.119.2-1.911c772.el7_8.noarch.rpm # 验证版本 rpm -qa | grep containerd containerd --version2. 配置 Containerd这是离线部署最容易出错的地方请务必仔细核对。# 生成默认配置文件 mkdir -p /etc/containerd containerd config default /etc/containerd/config.toml # 关键修改1: 将 cgroup 驱动改为 systemdK8s 推荐 sed -i s/SystemdCgroup false/SystemdCgroup true/g /etc/containerd/config.toml # 关键修改2: 指定本地 pause 镜像注意版本号必须与离线包内的 pause 镜像一致 sed -i s#sandbox_image .*#sandbox_image registry.k8s.io/pause:3.7#g /etc/containerd/config.toml # 验证修改是否生效 grep -E SystemdCgroup|sandbox_image /etc/containerd/config.toml3. 启动并验证服务systemctl daemon-reload systemctl restart containerd systemctl enable containerd # 检查状态 grep -E SystemdCgroup|sandbox_image /etc/containerd/config.toml # 应看到 SystemdCgroup true 和 sandbox_image registry.k8s.io/pause:3.74. 导入离线镜像核心步骤注意K8s 使用的是k8s.io命名空间不是默认的default。# 导入基础镜像包含 pause, kube-proxy 等 ctr -n k8s.io images import /root/k8s-offline/k8s-base-images.tar # 导入 Calico 网络插件镜像 ctr -n k8s.io images import /root/k8s-offline/calico-images.tar # 验证镜像列表 ctr -n k8s.io images list5.确认containerd健康确认 containerd 健康状态在所有节点Master 和 Node上完成 containerd 部署后首先需要验证其运行状态。**检查服务状态 **执行以下命令确认服务处于active (running)状态。systemctl status containerd**检查版本信息 **执行以下命令确认能正常显示客户端client和服务端server的版本信息。ctr version # 能看到 client 和 server 版本所有节点做完后下一步做什么当你所有 master node 都完成了 containerd 的部署并且 systemctl statuscontainerd 都是 running 状态后Master 节点执行 kubeadm init … 初始化集群Node 节点拿到 master 输出的 kubeadm join … 命令后执行加入集群在 master 上 kubectl get nodes 能看到 node 状态变成 Ready给小白的几个避坑提醒⚙️ 第三阶段所有节点安装 K8s 核心组件注意以下命令需要在三台机器上分别执行。1. 导入安装 kubeadm, kubelet, kubectlcd /root/k8s-offline/rpms yum localinstall -y \ kubernetes-cni-1.1.1-0.x86_64.rpm \ cri-tools-1.24.0-0.x86_64.rpm \ *kubelet-1.24.17*.rpm \ *kubeadm-1.24.17*.rpm \ *kubectl-1.24.17*.rpm # 设置 kubelet 开机自启注意此时 kubelet 尚未启动等待 init/join 后才会真正运行 systemctl enable kubelet2. 版本一致性校验确保三台机器的版本完全一致避免诡异问题。kubelet --version kubeadm version kubectl version --client预期输出所有版本均为v1.24.17。 第四阶段仅在 Master 节点初始化集群注意以下命令仅在k8s-master(192.168.30.153) 上执行。1. 清理旧环境如果是重装如果是第一次安装跳过此步如果是重装必须执行。kubeadm reset -f iptables -F iptables -t nat -F iptables -t mangle -F iptables -X ipvsadm -C rm -rfv /etc/kubernetes /var/lib/etcd /var/lib/kubelet $HOME/.kube2. 执行 kubeadm initkubeadm init \ --kubernetes-versionv1.24.17 \ --apiserver-advertise-address192.168.30.153 \ --image-repositoryregistry.aliyuncs.com/google_containers \ --pod-network-cidr10.244.0.0/16 \ --service-cidr10.96.0.0/12 \ --node-namek8s-master \ --cri-socketunix:///run/containerd/containerd.sock3. 配置 kubectl 凭证初始化成功后按照终端提示执行以下命令mkdir -p $HOME/.kube cp -i /etc/kubernetes/admin.conf $HOME/.kube/config chown $(id -u):$(id -g) $HOME/.kube/config4. 验证控制平面kubectl get pods -n kube-system预期输出etcd、kube-apiserver、kube-controller-manager、kube-scheduler均为Running。5.移除 Master 污点 (可选方便单节点测试)kubectl taint nodes k8s-master node-role.kubernetes.io/master-6. 部署 Calico 网络插件由于是离线环境我们已经有了calico.yaml文件。# 应用 Calico 配置 kubectl apply -f /root/k8s-offline/calico.yaml #如果出错 rm -f /root/k8s-offline/calico.yaml wget https://docs.projectcalico.org/v3.25/manifests/calico.yaml -O /root/k8s-offline/calico.yaml # 监控 Pod 启动状态等待几分钟 kubectl get pods -n kube-system -w直到calico-node-xxx和calico-kube-controllers-xxx全部变为Running。7. 验证 Master 节点状态kubectl get nodes预期输出k8s-master状态变为Ready。➕ 第五阶段Worker 节点加入集群注意以下命令在Node1 和 Node2上执行。1. 在 Master 生成 Token如果刚才 Master 初始化时的命令丢了可以在 Master 上重新生成kubeadm token create --print-join-command2. 在 Node 节点执行 Join 命令重点必须指定--cri-socket参数指向 containerd。kubeadm join 192.168.30.153:6443 \ --token xxxxxx.xxxxxxxxxxxxxxxx \ --discovery-token-ca-cert-hash sha256:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx \ --cri-socketunix:///run/containerd/containerd.sock 第六阶段集群验证与测试注意以下命令在Master上执行。1. 查看节点状态等待几分钟直到所有节点状态为Ready。# Master 验证节点加入(两台 Worker 节点会自动调度 calico-node Pod随后依次变为 Ready。) kubectl get nodes -w kubectl get nodes -o wide2. 检查系统 Pod确保所有系统组件运行正常。kubectl get pods -n kube-system3. 创建测试 Pod 验证网络# 创建一个 Nginx Pod kubectl run test-nginx --imagenginx # 查看 Pod 是否运行及 IP 分配情况 kubectl get pods -o wide # 进入 Pod 测试网络可选 kubectl exec -it test-nginx -- curl k8s-master:6443⚠️ 避坑指南小白必看Pause 镜像版本不一致config.toml里的sandbox_image版本必须与k8s-base-images.tar里的 pause 镜像版本严格一致例如都是3.7否则 Node 节点会一直NotReady。镜像命名空间错误 导入镜像时必须加-n k8s.io。如果导入到了defaultK8s 是找不到镜像的会导致ImagePullBackOff。忘记指定 CRI Socket 在kubeadm init和kubeadm join时如果不指定--cri-socket新版本 K8s 可能会尝试连接 Docker导致报错。Swap 未关闭 虽然可以通过参数忽略但强烈建议物理关闭 Swap否则可能引发 kubelet 异常。K8s 核心学术名词解析在 K8s 的学习和面试中以下名词是必须掌握的“黑话”1. 架构组件类Master Node (控制平面)集群的大脑。包含 API Server唯一入口、Scheduler调度器、Controller Manager管家、etcd数据库。Worker Node (工作节点)干活的苦力。包含 Kubelet接收指令、Kube-proxy网络代理、Container Runtime容器运行时。PodK8s 的最小调度单位。一个 Pod 可以包含一个或多个容器通常是 1 个它们共享网络和存储。CNI (Container Network Interface)容器网络接口标准。Calico、Flannel 都是 CNI 插件的实现负责给 Pod 分配 IP 并打通网络。2. 控制器与工作负载类Deployment最常用的控制器用于管理无状态应用如 Nginx。它保证指定数量的 Pod 副本一直运行。DaemonSet守护进程集。保证每个或特定节点上都运行一个 Pod 副本。常用于日志收集、监控代理、网络插件如 Calico。Service服务发现。Pod 是 ephemeral短暂的IP 会变Service 提供一个固定的 VIP虚拟 IP来访问一组 Pod。3. 状态与策略类Ready表示 Pod 已经准备好接收流量。CrashLoopBackOff容器启动后立刻挂掉K8s 正在尝试指数退避重启。通常是应用配置错误。ImagePullBackOff拉取镜像失败。通常是镜像名写错、仓库没权限或离线环境没导入镜像。Taints Tolerations (污点与容忍)污点节点说“我不喜欢这类 Pod别往我这调度”。容忍Pod 说“我不介意那个污点我就要去那个节点”。实战应用Master 节点默认有污点不允许运行业务 Pod除非你执行kubectl taint nodes ...去除它。 总结至此一个基于 Containerd、版本为 v1.24.17 的 Kubernetes 三节点集群已全部搭建完成。你可以开始在上面部署你的微服务应用了如果觉得这篇文章对你有帮助请点赞收藏支持一下如有问题欢迎在评论区留言讨论。