首页
/
行业洞察
/
正文
INDUSTRY INSIGHT · 深度
Kubernetes入门:Ubuntu环境下k8s集群搭建实操与避坑指南
📅 2026/10/20 22:20:42
✍️ 爱科研究院
👁 阅读 3,247
有朋友让我聊聊 k8s 到底是个啥顺便给一套能在 Ubuntu 上把环境跑起来的实操流程。这话题我前前后后折腾了不少次从最早只会跑 docker 容器到后来维护几个节点的集群中间踩的坑不算少。这篇就结合我自己的实操经验从“是什么”讲到“怎么搭”再聊几个新手最容易掉进去的深坑。照着一步步来通常能把一套能用的环境搭起来。1. 先弄清楚 k8s 是什么以及它到底解决了什么问题k8s 是 Kubernetes 的简称名字太长大家习惯叫 k8s中间 8 个字母省了。它本质上是一套容器编排系统解决的是“容器多了以后怎么管理”的问题。举个生活化的类比你要是自己在家做饭一个锅一个灶自己盯着就行不需要什么管理系统。但如果是开一个后厨几十个灶同时开工有切菜的、有炒菜的、有装盘的你就需要一个“后厨调度总管”负责安排谁先做、哪个灶空闲、食材够不够、出菜顺序怎么排。k8s 就是这个总管只不过它管的不是菜而是容器。它管的事情包括部署告诉系统“我要跑 3 个 Nginx 容器”它会自动帮你拉起 3 个并且分布在不同机器上。自动重启某个容器挂了它会自动重新拉起一个保证对外服务的数量不减少。服务发现与负载均衡容器跑起来后 IP 会变k8s 提供稳定的访问入口并把请求分发到健康的容器上。扩缩容流量大了可以手动或者自动增加容器数量流量小了再缩回去。滚动更新发布新版本时逐步替换旧容器期间服务不中断。在没有 k8s 的年代我们要管理十几台服务器上的容器基本靠脚本和人工发布一次版本需要半夜起来操作。有了 k8s 之后很多事情变成了声明式的你告诉它“最终状态是什么样”它自己去想办法达成。再说得直白一点很多时候你看到公司招聘要求里写着“熟悉 k8s”实际意思是你能不能在 k8s 上部署应用、排查问题、调优资源。它已经成了现代后端基础设施的事实标准和当年“会不会 Linux”差不多是一个地位。2. 理解 k8s 的整体架构才知道搭建时每个组件是干嘛的说完是什么得说说它由哪些部分组成。很多人搭建环境时一股脑照着文档敲命令结果出了问题完全不知道哪一环坏了就是因为对架构没有整体概念。2.1 控制平面Control Plane控制平面是整个集群的“大脑”负责决策和调度。通常由以下几个组件组成API Server所有操作的入口kubectl 命令实际上都是发给它的。其他组件之间不直接通信都通过它中转。etcd集群的数据库保存所有配置信息和状态。可以理解成“账本”——集群里发生了什么、现在应该是什么样、实际是什么样全部记录在这里。生产环境里 etcd 挂了整个集群基本就瘫痪了。Scheduler调度器决定一个新的 Pod 应该放在哪台机器上运行。它会综合考虑资源够不够、有没有特殊要求等因素。Controller Manager控制器管理器负责维持集群的实际状态。比如你声明“要 3 个副本”它发现现在只有 2 个就会触发创建第 3 个。可以理解成纠偏员。2.2 工作节点Node真正跑应用的地方每台工作节点上都有kubelet每个节点上的代理负责接收控制平面的指令管理本机上的容器并把状态汇报上去。kube-proxy负责网络规则实现 Service 的负载均衡和转发。不同节点上的 Pod 要互通、外部要访问服务都靠它维护规则。容器运行时真正运行容器的地方常见的是 containerd也可以理解成 docker 的替代品。k8s 本身不直接运行容器它通过容器运行时接口CRI和 containerd 打交道。2.3 核心对象Pod、Deployment、Service你实际使用 k8s 时打交道最多的是这几个对象。Pod是 k8s 的最小调度单元一个 Pod 里可以有一个或几个容器这些容器共享网络和存储。通常会有一个业务容器加一两个辅助容器。Deployment是管理无状态应用的对象。你写一个 YAML 描述“镜像是什么、副本数多少、更新策略怎么定”Deployment 就会帮你管好这一切。Service是稳定的访问入口。Pod 会随时被销毁重建IP 不稳定Service 提供固定的虚拟 IP 和 DNS 名字。你可以用 Service 名直接访问后端服务不需要关心具体是哪个 Pod 在处理。理解这几个对象之后搭建环境时就不会晕了kubeadm 初始化后系统组件本身就是以 Pod 的方式跑在集群里的比如 kube-apiserver、etcd 都作为静态 Pod 运行在控制节点上。3. 搭建前的准备工作和环境规划这一节重点说实操。我这里的操作环境是 Ubuntu 22.04 LTS用的 k8s 版本是 1.28 系列。版本选择上提一句如果不是特殊原因尽量用官方还在支持维护的版本别用太老的也没必要追最新1.28 属于比较稳定成熟的版本。3.1 硬件和系统要求先说硬件控制节点2 核 CPU、2GB 内存以上推荐 4GB 以上。如果内存不够 2GB初始化大概率会失败。工作节点同样建议至少 2 核 2GB。磁盘每个节点 20GB 以上可用空间镜像多的话再放大些。系统要求Ubuntu 22.04 或 20.04 都行内核版本别太旧。所有节点之间网络互通主机名不能重复。确保能访问外网至少能访问到拉取镜像的仓库。3.2 修改主机名和 hosts搭建之前先把主机名设置好方便后面识别节点。比如控制节点叫 master-01工作节点叫 worker-01。修改主机名后建议把节点 IP 加到 /etc/hosts 里避免后续互相解析出问题。# 控制节点 sudo hostnamectl set-hostname master-01 # 工作节点 sudo hostnamectl set-hostname worker-013.3 关闭交换分区这一步是硬性要求。k8s 默认不允许在开启了 swap 的节点上运行kubelet 会直接报错不启动。原因涉及到内存管理swap 会导致内存资源统计不准确影响 Pod 的 QoS 判断。sudo swapoff -a注意这只是临时关闭重启后 swap 会恢复。要永久关闭需要注释掉 /etc/fstab 里 swap 那一行。3.4 加载内核模块和调整系统参数k8s 网络组件需要一些内核模块支持主要是 overlay 和 br_netfilter。cat EOF | sudo tee /etc/modules-load.d/k8s.conf overlay br_netfilter EOF sudo modprobe overlay sudo modprobe br_netfilter然后调整网络参数让 iptables 能正确处理桥接流量cat EOF | sudo tee /etc/sysctl.d/k8s.conf net.bridge.bridge-nf-call-iptables 1 net.bridge.bridge-nf-call-ip6tables 1 net.ipv4.ip_forward 1 EOF sudo sysctl --system这套参数是让集群网络正常工作的重要前置条件。之前我遇到过 Pod 之间网络不通的问题最后排查下来就是网桥流量没放行导致的。4. 安装容器运行时 containerd 并完成基础配置k8s 1.24 版本之后已经移除了对 Docker 的直接支持转而使用 containerd 作为默认容器运行时。当然 Docker 仍然可以作为一个独立的容器工具使用但 k8s 运行容器时不再直接依赖它了。4.1 安装 containerdsudo apt update sudo apt install -y containerd安装完成后先别急着用containerd 的默认配置需要调整。4.2 生成默认配置并修改关键两项sudo mkdir -p /etc/containerd containerd config default | sudo tee /etc/containerd/config.toml生成配置文件之后有两个地方必须改第一处SystemdCgroup 改为 true找到[plugins.io.containerd.grpc.v1.cri.containerd.runtimes.runc.options]这一段把SystemdCgroup false改成SystemdCgroup true。为什么要改因为 Ubuntu 系统默认的 init 系统是 systemd容器如果不用 systemd cgroup 驱动会和 kubelet 的 cgroup 配置不一致导致节点状态一直 NotReady。这个坑我踩过不止一次初始化成功了但节点就是不 Ready排查半天就是这里的问题。可以用 sed 直接替换sudo sed -i s/SystemdCgroup false/SystemdCgroup true/ /etc/containerd/config.toml第二处配置镜像加速因为网络环境原因默认的沙箱镜像地址经常拉取超时而且拉取公共镜像速度慢建议配置镜像仓库加速地址。找到[plugins.io.containerd.grpc.v1.cri.registry]这一段修改config_path或者直接加[plugins.io.containerd.grpc.v1.cri.registry.mirrors]。如果你拿到了可用的镜像加速地址常见的有 docker 官方源、国内各大云厂商提供的加速服务具体以自己可用为准可以配置成[plugins.io.containerd.grpc.v1.cri.registry.mirrors] [plugins.io.containerd.grpc.v1.cri.registry.mirrors.docker.io] endpoint [https://你的加速地址]我自己实操时还改过 sandbox_image 的地址这一步也是为了解决镜像拉取问题。改完配置后重启 containerdsudo systemctl restart containerd sudo systemctl enable containerd5. 安装 kubeadm、kubelet、kubectl这三个工具的分工是kubeadm负责初始化集群和添加节点相当于一个引导工具。kubelet节点上的核心代理组件以 systemd 服务方式运行。kubectl命令行工具用来和 API Server 交互发布应用、查看状态全靠它。5.1 添加 k8s 的 apt 源这里有一个版本差异要提醒k8s 1.28 及更早版本官方源在apt.kubernetes.io1.29 开始迁移到了pkgs.k8s.io。我用的是 1.28所以按旧源来配sudo apt update sudo apt install -y apt-transport-https ca-certificates curl gpg curl -fsSL https://mirrors.aliyun.com/kubernetes/apt/doc/apt-key.gpg | sudo gpg --dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring.gpg echo deb [signed-by/etc/apt/keyrings/kubernetes-apt-keyring.gpg] https://mirrors.aliyun.com/kubernetes/apt kubernetes-xenial main | sudo tee /etc/apt/sources.list.d/kubernetes.list提示这里的源地址我用的是国内可访问的镜像源因为官方源在某些网络环境下面非常慢。如果你所在网络访问官方源没问题直接用官方文档里的地址就行。5.2 安装指定版本sudo apt update sudo apt install -y kubelet kubeadm kubectl如果不指定版本号默认安装的是当前最新版本。为了稳定起见建议指定版本sudo apt install -y kubelet1.28.2-00 kubeadm1.28.2-00 kubectl1.28.2-00安装完成后设置版本锁定防止 apt 升级时把组件版本改了导致集群不一致sudo apt-mark hold kubelet kubeadm kubectl6. 初始化控制平面节点到这里准备工作就全部完成了。下一步是初始化集群的控制节点。6.1 拉取组件镜像初始化前可以先手动拉取需要的镜像避免初始化时因为网络问题卡在拉镜像步骤sudo kubeadm config images pull --image-repositoryregistry.aliyuncs.com/google_containers--image-repository参数很关键如果直接使用默认的registry.k8s.io在国内环境大概率会卡住。6.2 执行 kubeadm init初始化命令如下sudo kubeadm init \ --apiserver-advertise-address192.168.1.100 \ --image-repositoryregistry.aliyuncs.com/google_containers \ --kubernetes-versionv1.28.2 \ --pod-network-cidr10.244.0.0/16 \ --service-cidr10.96.0.0/12参数说明--apiserver-advertise-address控制节点的内网 IP写上你的实际 IP。--image-repository镜像源换成可访问的仓库地址。--kubernetes-version指定版本要和安装的 kubeadm 版本对应。--pod-network-cidrPod 网段这里用 10.244.0.0/16 是为后续网络插件准备的。比如后面用 Flannel这个网段就是它的默认网段用 Calico 的话通常默认是 192.168.0.0/16两者别混。--service-cidrService 网段一般用默认值就行不要和 Pod 网段、物理网络网段重叠。初始化过程大约需要两到三分钟期间主要在做的事是拉镜像、生成证书、配置 etcd、启动 API Server 等系统组件。看到类似下面的输出就说明成功了Your Kubernetes control-plane has been 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初始化成功后 kubeadm 会打印一条加入集群的命令类似kubeadm join 192.168.1.100:6443 --token xxx --discovery-token-ca-cert-hash sha256:xxx这条命令要保存好工作节点加入集群时需要用到。如果丢了也没关系后面可以重新生成。6.3 配置 kubectl按初始化输出的提示配置 kubectl 的访问权限mkdir -p $HOME/.kube sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config sudo chown $(id -u):$(id -g) $HOME/.kube/config配置完成后验证一下kubectl get nodes此时能看控制节点但状态是 NotReady因为还没有装网络插件。6.4 安装 CNI 网络插件这一步不行跳过否则节点永远无法变成 Ready。我这边选的是 Calico功能更完整支持网络策略。在网络插件选择上我多说两句Flannel 更轻量配置简单Calico 功能更多性能也不错但配置复杂一些。单机测试或者学习环境用 Flannel 完全够真想在生产上跑建议认真评估 Calico。Calico 的安装方式通常是直接应用官方提供的 YAMLkubectl apply -f https://raw.githubusercontent.com/projectcalico/calico/v3.27.0/manifests/calico.yaml如果你网络无法访问 GitHub 源可以先把 YAML 文件下载到本地再 apply或者找可访问的镜像地址。应用完之后等待 Pod 启动kubectl get pods -n kube-system -w等所有 Pod 都变成 Running节点状态也会变成 Readykubectl get nodes我这里选用 Calico 时需要确认 Pod 网段和 Calico 默认网段一致。如果你初始化时用的--pod-network-cidr10.244.0.0/16而 Calico 默认使用的是 192.168.0.0/16就需要去改 Calico 的 ConfigMap。这一点网上很多教程没提实际操作中容易踩坑。7. 工作节点加入集群控制节点 Ready 之后工作节点加入集群。7.1 在工作节点上重复系统配置所有工作节点也要做前面第 3、4、5 节的操作关闭 swap、加载内核模块、设置系统参数、安装 containerd、安装 kubeadm 和 kubelet。工作节点上不用装 kubectl装了也暂时用不上但装了也没坏处。7.2 执行 join 命令在控制节点上重新生成 token 和 join 命令因为之前那条不一定还在有效期。默认 token 有效期是 24 小时sudo kubeadm token create --print-join-command输出的命令拿到工作节点上执行sudo kubeadm join 192.168.1.100:6443 --token xxx --discovery-token-ca-cert-hash sha256:xxx如果控制节点的 CA 证书哈希值不记得了可以用下面的命令获取openssl x509 -pubkey -in /etc/kubernetes/pki/ca.crt | openssl rsa -pubin -outform der 2/dev/null | openssl dgst -sha256 -hex | sed s/^.* //回到控制节点验证kubectl get nodes看到新节点状态变成 Ready 就完成了。8. 部署第一个应用验证环境集群搭好了不实际跑一个应用验证一下总觉得不放心。我用 Nginx 来做个冒烟测试。8.1 创建 Deploymentkubectl create deployment nginx-test --imagenginx:latest查看状态kubectl get podsPod 状态变成 Running说明部署成功。8.2 暴露 Servicekubectl expose deployment nginx-test --typeNodePort --port80 --target-port80查看 Servicekubectl get svc会看到类似这样的输出NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE nginx-test NodePort 10.98.74.122 none 80:31234/TCP 10s然后用任意节点的 IP 加端口访问curl http://192.168.1.100:31234看到 Nginx 的欢迎页说明整套环境已经通了。8.3 配置 kubectl 命令自动补全这里补充一个提高效率的小技巧。kubectl 命令比较长配置自动补全之后用起来会舒服很多echo source (kubectl completion bash) ~/.bashrc source ~/.bashrc9. 常见问题与排查技巧实录实践过程中总会遇到各种问题这里把最常见的几个列出来并分享我的排查思路。9.1 节点一直 NotReadykubelet 起不来最常见的两个原因cgroup 驱动不一致确认 containerd 配置里SystemdCgroup true这是最常见的。镜像拉不下来查看 kubelet 日志。排查方法sudo journalctl -u kubelet -f用 systemd 的 journal 直接看 kubelet 日志这是排查 k8s 节点问题最常用的手段。9.2 Pod 一直 Pending 或 ContainerCreatingPending 通常意味着没有节点能满足调度条件常见的是资源不足。我之前遇到过一次控制节点只有 1GB 内存初始化的系统组件就占掉了大半普通 Pod 根本没有资源分配。ContainerCreating 大概率是镜像拉取慢或者镜像源有问题kubectl describe pod pod-name看 Events 部分能看到拉取镜像的具体报错。9.3 token 过期或者 join 报错如果之前 join 命令失败重新生成 token 时--print-join-command会直接给出新命令。也可以加上--ttl0让 token 永不过期测试环境可以用生产环境不建议。还有一种情况是 CA 证书 hash 不匹配需要重新获取正确值。9.4 Service 无法访问先确认 Pod 是否正常运行再确认 Service 的后端是否有 Endpointskubectl get endpoints nginx-test如果 Endpoints 为空通常是 Service 的 selector 和 Pod 的 label 对不上。查看 Service 的 selector 和 Deployment 的 label 对不对得上。9.5 Pod 之间网络不通网络插件安装有问题是最常见的原因。先确认网络插件 Pod 是否正常运行kubectl get pods -n kube-system -o wide再用kubectl exec进入容器实际测试连通性比如从业务 Pod ping Service 的 ClusterIP。9.6 containerd 拉取镜像超时这个问题在部分网络环境下非常突出。我的做法是配置镜像加速地址。把 sandbox_image 地址也改掉。适当调大timeout参数在 /etc/containerd/config.toml 里能找到相关配置。10. 写在最后的几点体会环境搭好只是第一步。我在实际用下来最大的感受是k8s 的概念和使用习惯和传统运维思路有很大不同。传统方式是你命令机器“给我跑一个 Nginx”k8s 是你告诉它“我要确保集群里始终有 3 个 Nginx 副本”至于怎么达成它自己想办法。思路转换过来之后再看什么 Deployment、ReplicaSet、StatefulSet 就不会觉得绕了。学习路径上我个人的建议是先搞清楚 Pod、Deployment、Service 这三个核心对象把应用发布和访问跑通然后逐步去接触 ConfigMap、Secret、Ingress、持久化存储这些更深入的内容。不要一开始就照着大而全的文档啃容易越看越晕。还有一点多describe少猜。k8s 的问题排查入口基本都是kubectl describe xxx xxx它会把事件、调度记录、镜像拉取状态等信息都展示出来。大多数问题看 Events 就能定位到原因。这套流程跑通之后你已经在用和很多生产环境相同的技术栈了。下一步可以试试在上面部署一个有价值的应用而不是停留在跑个 Nginx 冒烟测试。比如搭个简单的 Web 服务配合 ConfigMap 管理配置给自己立个小目标——把某个应用完整地用 k8s 管理起来。那才是真正开始体会到 k8s 的好处。
📌 标签:
工业官网
设计趋势
AI 建站
SEO
获取完整报告 →
RELATED ARTICLES
推荐阅读
2026/10/20 22:15:39
大模型与特征工程在A股量化策略中的落地实践
2026/10/20 22:15:39
国产AI算力地基:拓扑调度、确定性内存与微架构桥接
2026/10/20 22:15:39
HarmonyOS 6人脸识别实时渲染:基于XComponent的绘制链路设计与实践
2026/10/21 2:47:45
WinForms DataGridViewComboBox输入自动匹配实战指南
2026/10/21 2:47:45
HyperDbg内核调试器:Ring0实时调试与EPT内存监控实战指南
2026/10/21 2:47:45
学生信息管理系统:SSM架构下的数据一致性与工程落地实践
2026/10/21 2:47:45
WinForm登录状态机设计:事件解耦与DPAPI安全存储实战
2026/10/21 2:47:45
Quartz动态设置并发数量
2026/10/21 2:42:44
教培机构如何用GEO+RAG优化截获AI搜索流量
2026/10/21 0:01:44
ClickHouse实战:从列式存储到亿级数据秒级查询
2026/10/21 0:01:44
高效筛选arXiv机器学习论文:四步法实战指南
2026/10/21 0:01:44
Python爬取百度迁徙数据:接口签名、反爬与SQLite存储实战
2026/10/20 16:07:12
OpenResearch实战:Claude Code、Codex、OpenCode、Cursor 工作流搭建与故障排查
2026/10/20 7:57:25
知识管理核弹:用Obsidian构建第二大脑的工程化方案(TaoToken 统一 Key 接入版)
2026/10/20 16:49:38
金融AI落地指南:从调研报告到技术选型与工程实践
2026/10/20 2:24:03
我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频
2026/10/20 2:23:57
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证
2026/10/20 2:23:53
2026 大模型集体涨价:用 Python 做企业 Token 成本测算与选型避坑(附配置)