恒美微站
首页
关于我们
建站服务
主题模板
案例展示
资讯中心
联系我们
一台服务器搞定K8s:k3s、minikube、kubeadm单节点部署指南
首页
资讯中心
/
一台服务器搞定K8s:k3s、minikube、kubeadm单节点部署指南
一台服务器搞定K8s:k3s、minikube、kubeadm单节点部署指南
发布时间:2026/10/15 13:01:08
这段时间我把Kubernetes的单机部署翻来覆去折腾了几遍从最开始连Pod都调度不上去到后来能在2C4G的一台服务器上稳定跑起完整集群踩了不少坑也摸清了不少门道。这篇东西不是官方文档翻译是我自己“如何只使用一台服务器配置kubernetes”的学习总结。文章会把三条主流路线都讲清楚k3s、minikube、kubeadm单节点各自适用什么场景、关键参数怎么设置、部署完怎么自测、遇到报错怎么查。适合手里只有一台服务器但又想认真学容器编排的运维新人、后端开发以及准备面试前突击K8s实操的学生。1. 先想清楚单机K8s到底在学什么1.1 为什么非要一台服务器很多人学Kubernetes第一反应是凑三台机器觉得少了不像集群。但真实情况是多节点集群的日常管理成本很高而学习K8s核心概念其实单机就能覆盖80%的内容。一台服务器能让你把Pod、Deployment、Service、Ingress、ConfigMap、PV/PVC这些核心对象全部跑一遍甚至能模拟出Pod调度、重启策略、滚动更新这些调度行为。区别只在于单机环境没有任何高可用可言etcd和kubelet都在同一台机器上宕机就是全挂。所以单机部署的核心价值是“学习”和“轻量验证”不是“替代生产”。你得带着这个预期去选方案才不会出现“为什么我只有一台机器学不了K8s”的错觉。另外很多人在本机用虚拟机或者Docker Desktop折腾总感觉卡顿严重其实换成一台独立的Linux服务器同样配置下的体验会好非常多因为资源隔离更干净网络模型也更接近真实环境。1.2 四条技术路线对比k3s、minikube、kind、kubeadm单机部署Kubernetes不是只有一种方法。对于“只有一台服务器”这个约束条件常见的方案有四条k3s、minikube、kind、kubeadm单节点。我用了一段时间后把它们放在同一个表格里对比方案内存占用启动速度接近生产程度推荐场景k3s约500MB-700MB极快中高边缘计算、临时环境、入门学习、低配机器minikube约1.5GB-2GB较快中等系统学习K8s原生API、快速开发验证kind约1GB-2GB中等较低CI流水线、镜像构建验证、快速销毁重建kubeadm约1.5GB-2.5GB较慢高模拟生产部署方式、准备向多节点扩展从内存占用就能看出来如果你的服务器只有2G内存基本不用犹豫直接选k3s。4G内存的话minikube和kubeadm都能跑起来但会比较紧张。8G及以上三者随便选体验都好。这里顺便说一个很多教程不会提的细节调整方案之前先确认服务器内存是不是真正可用很多特价云主机标注2G内存实际可用只有1.5G左右因为系统本身吃掉了不少。2. 部署前的底线准备系统初始化与运行时选型2.1 服务器的最低配置要求按照我的实测不同方案对应不同的最低配置。k3s最低1核1G能跑起来但属于“能启动不代表能用”的程度连个像样的应用进去CPU就满了。minikube最低建议2核2G官方文档写的是2核2G起步实际跑起来至少需要2G可分配内存。kubeadm单节点最低建议2核4G因为etcd本身比较吃内存加上kubelet、apiserver这些进程内存不足时etcd容器会反复重启这是一个非常典型的失败表现。磁盘方面单机集群至少留出20G给K8s相关组件和镜像。如果你想拉一些带有GPU依赖或者大体积的镜像做实验30G-50G会更从容。系统方面Ubuntu 20.04/22.04、Debian 11/12、CentOS 7.9/Stream 9我都试过CentOS系列会遇到一些内核模块和防火墙规则的额外问题Ubuntu和Debian是体验最顺的。2.2 无论选哪条路线都要做的系统初始化这部分操作三条路线通用绝对不是白做的。第一件事关闭swap。Kubernetes在1.8版本之后要求节点必须关闭swap否则kubelet会拒绝启动或者直接报错。命令是swapoff -a但这只是临时关闭重启后会恢复。要把/etc/fstab里带swap关键字的那行注释掉才能保证重启后不再启用。第二件事加载必要内核模块并设置内核参数cat EOF | tee /etc/modules-load.d/k8s.conf overlay br_netfilter EOF modprobe overlay modprobe br_netfilter cat EOF | 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 sysctl --system很多部署失败都出现在网络层比如Pod跨节点通信不正常、CoreDNS解析超时根源往往是内核参数没打开。net.ipv4.ip_forward这个参数尤其重要它决定iptables规则能否正确转发数据包。第三件事确保系统时间同步。Kubernetes集群内部很多组件依赖证书证书有一个有效期窗口系统时间如果偏差过大会出现x509证书校验失败。安装chrony并启动即可。2.3 容器运行时containerd优先单机部署K8s容器运行时推荐直接选containerd。原因很简单Docker在K8s里的地位已经变成了一个兼容层Docker本身默认使用的也是containerd。如果你通过Docker来启动K8s组件等于多绕了一层。用containerd作为运行时镜像路径、日志格式、资源占用都更简洁。不过containerd有一个容易被忽略的配置点SystemdCgroup。如果节点使用的是systemd作为init系统而containerd的SystemdCgroup没有切换成truekubelet运行起来之后会报cgroup相关错误或者Pod经常处于Pending状态。修改方法是编辑/etc/containerd/config.toml找到SystemdCgroup参数改成true然后重启containerd。3. 最省心的路径k3s单机部署全流程3.1 k3s到底做了什么k3s是一个轻量级Kubernetes发行版它把控制面组件kube-apiserver、kube-controller-manager、kube-scheduler全部打包进一个二进制文件里内置了containerd、CoreDNS、flannel等组件。你装完k3s之后机器上不需要预先安装Docker、containerd或者kubectl它全帮你解决了。安装完成后k3s自带的kubectl命令是k3s kubectl与原生kubectl使用方式一致。这个方案非常适合只有一台服务器的情况。装完之后整个集群的组件数量比完整版K8s要少很多资源占用低启动也快。官方提供了极其简单的安装命令curl -sfL https://get.k3s.io | sh -如果你下载脚本比较慢可以先把脚本下载到本地再执行不要纠结于必须一条命令完成。3.2 安装后的关键操作与权限处理安装完成后首先检查状态systemctl status k3s k3s kubectl get node k3s kubectl get pods -A正常情况下节点状态是Readykube-system命名空间里的Pod都是Running。k3s的kubeconfig文件默认放在/etc/rancher/k3s/k3s.yaml默认权限是600只有root能读。如果你使用普通用户执行kubectl需要先把配置文件复制出来并修改权限mkdir -p $HOME/.kube sudo cp /etc/rancher/k3s/k3s.yaml $HOME/.kube/config sudo chown $(id -u):$(id -g) $HOME/.kube/config另外k3s.yaml里的server地址默认是https://127.0.0.1:6443只能本机访问。如果你想从自己电脑上远程操作这台服务器上的集群我个人的建议是在服务器上用SSH端口转发而不是直接把kubeconfig里的地址改成公网IP因为6443端口暴露到公网的安全隐患很大而且还要处理证书SAN的问题学习阶段没有必要踩这个坑。3.3 部署一个应用验证集群单机K8s环境跑通了之后第一个验证用例很有讲究。我的习惯是部署一个nginx Deployment然后用NodePort方式暴露服务。因为这种方式能同时验证调度、容器运行、网络代理三个核心环节kubectl create deployment nginx --imagenginx kubectl scale deployment nginx --replicas2 kubectl expose deployment nginx --port80 --target-port80 --typeNodePort kubectl get svc看到Service的ClusterIP和NodePort之后在当前服务器上直接访问验证curl http://127.0.0.1:30080如果能正常返回nginx页面说明整个链路已经通了。这时候你还可以顺手验证一下滚动更新和副本调度先把副本数改成3再修改镜像tag观察Pod逐个重建的过程。3.4 k3s的升级与卸载k3s升级非常简单官方安装脚本本身支持重复执行。升级的命令同样是curl -sfL https://get.k3s.io | sh -脚本检测到已存在的版本会自动更新。卸载的时候k3s会生成一个卸载脚本执行/usr/local/bin/k3s-uninstall.sh即可这个脚本会把所有相关文件、服务、数据目录清理干净。这里要提醒一下卸载前确认没有需要保留的PVC数据因为卸载脚本会把/var/lib/rancher/k3s下面的数据一起删掉。4. 更接近原汁原味的K8sminikube单机部署全流程4.1 minikube能解决什么问题minikube是官方长期维护的本地Kubernetes环境它的定位就是“在单机上跑一个完整的K8s集群”。和k3s不同minikube不会帮你把组件打包成一个二进制文件它背后还是标准的K8s组件只是通过缓存和预下载把安装过程简化了。如果你打算系统学习K8s原生对象、看kube-system里各个组件是怎么部署的minikube的体验更接近真实环境。之前我推荐过用Docker作为驱动这也是在Linux服务器上最推荐的运行方式。安装minikube二进制文件之后用下面命令启动集群minikube start --driverdocker --cpus2 --memory4096 --container-runtimecontainerd参数含义很简单cpus和memory决定分配给K8s集群的资源上限container-runtime选择containerd。这里建议显式指定memory因为如果不指定minikube可能只用默认内存导致集群启动后kube-system组件频繁因内存不足被杀掉。4.2 minikube日常使用与Dashboardminikube最实用的地方是自带了一套本地开发体验。启动集群之后可以用minikube dashboard命令打开K8s控制面板这个功能对可视化观察资源状态和Pod日志非常有用。在无图形界面的服务器上你仍然可以访问Dashboard因为它本质上是代理到本地的Web服务。minikube还内置了很多addons可以随时启用比如minikube addons enable ingress minikube addons enable metrics-server启用ingress之后集群里就有了标准的Ingress Controller可以做基于域名的路由转发实验这是k3s和kind都容易折腾的地方。minikube对kubectl的整合也做得很好。如果你的系统上没有独立安装kubectl可以用minikube kubectl -- get pods来调用内置的kubectl。如果想要在任意终端直接使用kubectl可以配置alias但更推荐直接安装独立kubectl然后把kubeconfig指向minikube生成的文件。minikube的kubeconfig在~/.kube/config里自动追加了minikube的context使用minikube start之后默认的context就是minikube。4.3 minikube的常见坑第一个坑是卡在SSH连接阶段。如果你在云服务器上使用Docker驱动偶尔会卡在waiting for SSH主要原因通常是镜像拉取超时或者Docker镜像缓存损坏。处理方式是把minikube重新初始化minikube delete后重新minikube start或者删除~/.minikube目录后重试。第二个坑是镜像拉取慢。minikube启动时要从公共镜像仓库拉取一组K8s组件镜像如果网络不稳定整个启动流程会变得很慢。解决办法是给Docker配置镜像加速在/etc/docker/daemon.json里配置registry-mirrors选项这个配置不仅影响Docker也会影响minikube通过Docker拉取镜像的速度。第三个坑是不要在服务器上使用none驱动。minikube的none驱动是直接把K8s组件以系统服务方式运行在宿主机上。表面上省了一层虚拟化开销但后续删除集群时会把宿主机上的K8s相关文件清理得很不干净而且在系统服务层面留下不少残留。Docker驱动虽然多占一点内存但隔离性更好删除也彻底。5. 模拟生产部署方式kubeadm单节点部署全流程5.1 为什么已经有了k3s和minikube还要用kubeadm如果你将来打算进公司维护真实K8s集群你会发现生产环境普遍是用kubeadm、二进制或者发行版自带的安装器搭起来的。kubeadm是构建Kubernetes集群的标准工具它把apiserver、controller-manager、scheduler、etcd都封装成静态Pod通过kubelet拉起。用kubeadm在单机上走一遍你才能真正看到每个控制面组件是怎么以Pod形式存在的。单节点的意义在于除了没有第二个工作节点其它流程和生产几乎完全一致。初始化控制面、安装CNI插件、移除控制面污点这套流程最接近生产。而且之后如果你有了第二台服务器只需要在另一台机器上执行kubeadm join就能把单节点扩成多节点这是k3s和minikube都不太容易做到的升级路径。5.2 初始化控制面的完整命令使用kubeadm之前先准备好容器运行时。这里以containerd为例。安装好containerd之后直接初始化控制面kubeadm init --pod-network-cidr10.244.0.0/16然后按照初始化完成后的提示设置kubectl的配置文件mkdir -p $HOME/.kube cp -i /etc/kubernetes/admin.conf $HOME/.kube/config chown $(id -u):$(id -g) $HOME/.kube/config初始化完成后集群处于NotReady状态原因是没有安装网络插件。这里推荐安装Calico作为CNI插件kubectl apply -f https://raw.githubusercontent.com/projectcalico/calico/master/manifests/calico.yaml安装完成后重点检查calico-system命名空间下的Pod是否全部Running。在网络插件就绪之前CoreDNS也会一直处于Pending状态这是正常现象不要急着去查CoreDNS的问题。5.3 单节点集群的污点处理初始化完成的单节点集群有一个很经典的坑控制面节点默认带有污点Pods无法调度上去。所以当你尝试部署一个普通应用时Pod会一直Pending。解决办法是移除控制面节点的污点kubectl taint nodes --all node-role.kubernetes.io/control-plane-执行之后Pod才能调度到这个节点上。这一步非常重要很多初次使用kubeadm单节点的朋友都会在这里卡住。需要注意的是生产环境的多节点集群里控制面节点通常不会移除污点让它只跑系统组件单机实验环境才需要这样做。5.4 kubeadm单节点的其他坑位kubeadm单节点对资源的要求是三条路线里最高的。最容易出现的失败是etcd容器反复重启表现是kubectl get pods -n kube-system中etcd处于CrashLoopBackOff。根本原因多半是内存不足因为etcd会在启动时锁定一定量的内存页资源不够时直接被OOM杀掉。这种情况没有捷径要么扩大内存要么换用k3s。另一个常见问题是系统时间不对。Kubernetes证书有效期是动态计算的系统时间偏差超过几分钟apiserver和kubelet之间的通信就会出现证书校验失败。排错时先date看一下当前时间这个操作花费五秒钟却经常能解决看起来像网络故障的问题。6. 三种方案对比之后我留下的真实结论6.1 对应用途的选型清单如果你问我现在有一台2C4G服务器到底选哪个我的回答是看阶段。只想快速搭建一个K8s环境跑几个实验尽量少跟系统配置打交道选k3s。安装一条命令装完即可用自带containerd和网络插件占用资源最少。想认真把K8s的核心对象学明白愿意接受镜像拉取和初始化过程选minikube。Dashboard体验好附加组件丰富kubectl和K8s API版本都是原生的学习曲线更顺。后续计划扩到多节点想提前模拟生产部署方式选kubeadm。单节点初始化流程和生产完全一致扩节点时执行kubeadm join即可。如果只是写自动化脚本或者做CI环境选kind。kind的所有K8s节点都是Docker容器启动销毁都非常迅速。三条主线我个人都完整走过一遍现在的习惯是遇到复杂实验想快速验证用k3s需要研究K8s本身行为时用minikube模拟生产部署就kubeadm。三者不冲突学习阶段都用一用反而收获更大。6.2 资源占用与可维护性实测这是我多次部署后记录的一组真实数据。k3s安装完成后空闲状态下内存常驻约600MB-800MBPod数量非常少。minikube使用Docker驱动时占用在1.5GB-2GB之间如果再加上Dashboard和附加组件会接近2.5GB。kubeadm单节点最重etcd、apiserver、controller-manager、scheduler加上kubelet空闲状态约2GB左右跑上业务Pod之后容易突破2.5GB。磁盘占用也有明显差异。k3s因为很多组件合并进二进制镜像层更少整体占用约3GB-4GB。minikube因为有本地镜像缓存和集群数据占用约5GB-6GB。kubeadm单节点如果加上Calico、CoreDNS等镜像也在5GB以上。可维护性方面k3s的优点是升级卸载全自动脚本缺点是它封装了不少细节以后想排查底层问题时难以直接观察。minikube的启动参数最直观但集群生命周期依赖minikube这个工具本身。kubeadm最接近原生但手工升级和排错负担最重。7. 部署完成后的自测清单与高频报错速查7.1 单机部署成功的硬性指标不要只看节点Ready就认为大功告成我整理了一份单机部署完成后的自测清单建议全部过一遍节点状态确认kubectl get nodes输出Ready。系统组件全部Runningkubectl get pods -A里没有Pending或CrashLoopBackOff。核心DNS解析可用创建一个临时Pod执行nslookup kubernetes.default能返回ClusterIP说明CoreDNS正常。应用能正常调度部署一个nginx Deployment观察Pod状态为Running。应用能通过Service访问部署成功后创建NodePort类型的Service从外部访问节点IP加端口能通。持久化能力创建一个PVC确认能绑定到PV。整套清单跑下来才说明你的单机K8s环境是真正可用的而不只是“看起来装好了”。7.2 十个常见报错的排查思路下面这张表格基本都是我在单机环境里踩过的真实报错整理成了速查表典型报错含义处理思路The connection to the server localhost:8080 was refusedkubectl读不到有效kubeconfig设置KUBECONFIG环境变量或拷贝admin.conf到~/.kube/confignode NotReady网络插件没安装或未就绪检查CNI插件Pod状态确认内核模块br_netfilter已加载CoreDNS Pending一般因为网络插件未运行先装好Calico或flannelCoreDNS会自动调度ImagePullBackOff镜像拉取失败检查镜像名称、标签、网络源给容器运行时配置镜像加速CrashLoopBackOff容器启动后自行退出kubectl logs查看退出原因多半是配置错误或资源不足etcd处于CrashLoopBackOffetcd启动失败大概率是内存不足或磁盘IO异常查看etcd日志确认Kubelet服务启动失败kubelet报cgroup或swap错误检查swap是否关闭cgroup驱动是否和运行时一致Pod一直Pending调度失败查看describe输出是否有taint或资源不足TCP healthz probe failedapiserver健康检查失败检查系统时间和证书尝试重启apiserver静态Podexec format errorCPU架构和镜像架构不匹配换用对应架构的镜像arm机器不要拉amd64镜像如果你遇到了表中没有的报错我的排查习惯是先看事件描述kubectl describe pod 名称这里能看到Pod的完整事件链绝大多数问题在事件里就能定位。再不行就看容器日志kubectl logs 名称 --previous可以看到容器上一次退出时的日志。这两个命令基本覆盖90%的问题。8. 这条学习路我个人建议怎么走如果让我重新走一遍单机K8s的学习路径我会按下面的顺序来先用k3s把集群跑起来花一天时间熟悉常用kubectl命令知道如何看Pod、Service、Deployment这些基础对象。然后删掉k3s换minikube开Dashboard把PVC、Ingress、ConfigMap这些对象逐个实验这个阶段是建立抽象概念的关键时期。最后再用kubeadm按生产方式搭一遍自己装网络插件、自己处理污点感受一下真实的部署复杂度。在学习过程中一定不要贪多没必要一上来就叠加Istio、Prometheus这类生态组件。先把一个nginx跑通再把多副本和滚动更新跑通最后再碰存储和网络。单机K8s学到的调度逻辑和对象模型是通用的换到多节点集群只是多了一些网络通信细节核心概念完全一样。我个人在实际操作中体会最深的两个点一是资源规划远比命令重要很多人失败在内存不足却不自知频繁报错却找不到根因二是学会看现象和日志比背命令重要任何一次部署失败的过程都是最好的学习素材。把这三条路线都亲手搭一遍你会发现自己对Kubernetes的理解会扎实很多。这篇记录既是备忘也希望能给你一台服务器配置Kubernetes的实践之路省下几步弯路。