k3d入门指南:在Docker中运行轻量级K3s集群
k3d这个工具圈子里其实不算新了但每次跟人聊到本地跑K8s总还有人一脸懵地问k3d和k3s到底啥关系为啥不直接用Docker Desktop自带的K8s。这问题我在各种场合被问过不下几十次。今天打算用一篇完整的入门指南把k3d怎么在Docker里跑K3s这事彻底讲明白从原理到实操再到我踩过的一些坑一次性说清楚。我最初接触k3d是因为某次需要在本地快速复现一个客户端连不上集群的问题。当时嫌minikube太重kind又觉得节点启动得太慢折腾了一圈之后发现k3d恰好卡在一个非常舒服的位置轻量、快、配置灵活。如果你也跟我一样需要在本地或者CI环境里频繁创建和销毁K8s集群那这篇指南应该能帮你省下不少时间。1. 内容整体设计与思路拆解1.1 K3s和k3d到底是什么关系先把概念理清楚。K3s是一个轻量级Kubernetes发行版官方给它的定位是面向边缘计算和资源受限场景。它把K8s控制平面组件压缩进单个二进制默认使用SQLite替代etcd作为存储去掉了很多云服务商相关的控制器整体内存占用可以压到几百兆。k3d做的事情更简单粗暴它把K3s直接装进Docker容器里跑这个容器既是控制平面节点也可以作为工作节点多个容器组合在一起就构成一个完整的K8s集群。打个比方K3s好比一个精简版的操作系统镜像k3d则是帮你把这个镜像跑在一台虚拟机里。Docker容器就是那台虚拟机只不过它比传统虚拟机轻得多启动一个K3s节点通常只需要十几秒到三十秒。k3d通过Docker网络让各个节点容器互联互通再通过Server负载均衡器把集群的API Server和Service端口暴露给宿主机。1.2 为什么选择k3d而不是minikube或者kind选型这事没有绝对的对错关键看使用场景。我把k3d和几个常见的本地K8s方案放在一起对比过工具核心原理启动速度内存占用适用场景minikube单节点虚拟机或容器中1-2分钟较高完整K8s功能验证、教学kindDocker容器模拟K8s节点中1分钟左右中等与真实K8s一致性高的CI测试k3dDocker容器运行K3s快10-30秒很低轻量开发、快速原型、CI集成kind是使用Kubernetes官方组件在容器里搭建完整节点所以它与真实集群的一致性很高适合做需要复现线上环境的测试。但这也意味着它启动慢、占资源。k3d基于K3sK3s本身对K8s做了大量裁减和优化所以启动速度和内存占用都有明显优势。我个人的经验是如果只是在本地跑个Demo、验证一下Helm Chart、或者需要快速测试多集群交互k3d是首选。如果是做非常贴近生产的集成测试尤其是要验证etcd、kube-proxy这些底层组件的行为用kind更合适。两者不冲突像我平时就同时装了k3d和kind按需使用。1.3 k3d在本地开发工作流中的定位把k3d放在一个更大的开发流程里看它的优势会更明显。本地开发时你通常会经历这几个阶段编写代码、构建镜像、部署到K8s、观察日志、调试。如果你用的是云上的开发集群每次构建镜像都要push到远程仓库然后拉取整个循环可能要好几分钟。用k3d你可以把集群直接跑在本地镜像构建完直接导入集群里整个迭代循环压缩到几十秒。更关键的是k3d支持创建多集群。比如我在做某些微服务联调时会同时起两个集群一个模拟生产环境版本一个跑最新的开发分支通过端口映射让它们互访。这在minikube上是很难做到的但k3d只需两条命令就能搞定。后面我会详细讲这个操作。2. 核心原理与配置解析2.1 k3d的工作原理与架构细节k3d的核心机制就是利用Docker容器来模拟K8s节点。一个k3d集群通常由三类容器组成Server节点容器承载K3s server进程也就是K8s控制平面。默认情况下这个容器还会运行一个名为traefik的Ingress Controller用来处理集群内的七层负载均衡。在单Server模式下工作负载也会调度到这个节点上。Agent节点容器相当于K8s的工作节点只运行kubelet和容器运行时接收来自控制平面的调度。可创建多个Agent容器来扩展集群容量。Loadbalancer容器这不是K3s自己的一部分而是k3d额外创建的。它运行着一个轻量级的负载均衡器基于HAProxy作用是把宿主机上的端口流量转发到集群内对应的Service端口上。你通过-p 8080:80loadbalancer这样的参数宿主机端口映射到集群时实际就是经过这个容器完成的。这些容器之间通过一个预先创建的Docker网络互联。k3d的镜像里预置了K3s二进制以及对应的启动脚本容器启动时执行这些脚本初始化节点并注册到集群中。值得留意的是k3d并不是完全环境无关的。它依赖Docker的网络和存储能力所以你不能在一台没有Docker的机器上用k3d。同时k3d中的K3s版本是由k3d镜像版本决定的默认使用的镜像标签是rancher/k3s:latest但你也可以用--image myregistry/k3s:custom指定任意包含K3s的镜像。2.2 集群创建时的关键配置参数k3d的配置方式很灵活既可以写命令行参数也可以用YAML配置文件。这里梳理几个日常使用频率最高的参数我会把每个参数的用途和应用场景都展开说明。控制平面与工作节点数量创建集群时最基础的两个参数是--servers和--agents它们决定了控制平面节点和工作节点的数量。k3d cluster create mycluster --servers 1 --agents 2单Server模式下K3s默认使用SQLite存储状态适合开发测试。如果你需要高可用控制平面可以指定--servers 3此时K3s会用内置的etcd模式运行三个Server节点之间自动形成共识。不过要注意etcd模式对磁盘I/O和内存的要求更高资源紧张的机器可能会有点吃力。以我自己的笔记本为例16GB内存的机器上一个Server节点加两个Agent节点每个节点的内存限制在1GB以内整个集群加起来大概占用2.5GB到3GB的内存这个开销对本地开发来说完全可接受。端口映射语法详解k3d端口映射的语法看起来有点别扭但拆开看其实不难k3d cluster create mycluster -p 8080:80loadbalancer冒号前面的8080是宿主机端口冒号后面的80是集群内的端口loadbalancer表示这个映射挂到负载均衡器上。你访问宿主机localhost:8080时流量会经过Loadbalancer容器再转发到集群内Service暴露的80端口。这里有一个点很容易搞混80并不是指某个Pod的端口而是指集群内Service的端口。也就是说你创建的Service类型如果是ClusterIP端口为80那通过-p 8080:80loadbalancer就能直接访问到它。如果Service端口是30080那就得写成-p 8080:30080loadbalancer。如果不想用Loadbalancer也可以把端口映射挂到具体的Server或Agent节点上比如-p 8080:30080server:0这样流量会直接进到第一个Server节点的对应端口。这种做法偶尔会用到比如调试Ingress或者NodePort类型的Service时。存储卷挂载与镜像导入本地开发经常需要把代码目录挂载进集群让Pod直接读最新代码避免每次改动都重新构建镜像。k3d通过--volume参数支持这个能力k3d cluster create dev-cluster --volume /Users/me/code:/codeallall表示挂载到所有节点。对于依赖本地文件做热加载的开发场景这一步非常关键。不过要注意K8s本质上是分布式系统Pod可能被调度到任意节点所以这种方法更适合单节点的开发环境。多节点环境下还是应该用镜像或ConfigMap来管理代码和数据。另外k3d提供了k3d image import命令可以把本地构建好的镜像直接导入集群k3d image import myimage:latest -c dev-cluster这条命令会把镜像推送到集群内的所有节点上省去了push到远程仓库再pull下来的环节本地开发效率提升非常明显。私有镜像仓库k3d还支持直接创建一个内置的私有镜像仓库免去你先跑一个registry容器再配置的麻烦k3d registry create myregistry --port 5000 k3d cluster create dev-cluster --registry-use myregistry:5000创建完集群后你就可以直接往localhost:5000推送镜像然后在这些镜像上部署应用。这个功能在做微服务联调时很实用多个人共享一套仓库和集群互相之间不用再拷贝镜像文件。2.3 配置解析表格速查为了方便查阅我整理了一张参数速查表覆盖平时最常用的k3d配置参数示例作用--servers--servers 3设置控制平面节点数量--agents--agents 2设置工作节点数量-p-p 8080:80loadbalancer端口映射到loadbalancer--volume--volume /tmp/data:/dataall挂载存储卷到所有节点--k3s-arg--k3s-arg --disabletraefik传递额外参数给K3s--registry-use--registry-use myregistry:5000使用已有私有仓库--network--network my-net指定Docker网络--agents-memory--agents-memory 512m限制Agent节点内存--image--image custom/k3s:test自定义K3s镜像--kubeconfig-merge-default无合并Kubeconfig到默认配置3. 实操过程与核心环节实现3.1 环境准备与安装步骤在开始之前先确认你的机器满足两个硬性条件Docker可以正常运行且版本不能太老。k3d依赖Docker API的大部分现代特性建议Docker版本在20.10以上。检查Docker是否正常docker version --format {{.Server.Version}}能正常输出版本号就说明Docker可用。接下来安装k3d。我用的方式是通过官方安装脚本curl -s https://raw.githubusercontent.com/k3d-io/k3d/main/install.sh | bash如果你用的是macOS也可以直接用Homebrewbrew install k3dLinux用户还可以用包管理器安装Debian或Ubuntu用户可以使用apt源。安装完成后验证一下k3d version能正常输出版本信息就说明安装成功。k3d CLI会与K3s镜像解耦所以即使k3d本身版本较新你依然可以在创建集群时指定使用旧版K3s镜像这个灵活性在实际项目里真的救过我一次。提示安装完k3d之后别忘了确认kubectl也可以使用。k3d本身不依赖kubectl但集群创建后你需要它来管理资源。3.2 创建集群的完整演示范例创建一个最基础的集群一行命令搞定k3d cluster create demo这个命令会创建一个名为demo的集群默认包含一个Server节点。执行过程中k3d会拉取K3s镜像创建Docker网络启动容器整个流程通常在几十秒内完成。看到输出中出现Cluster demo created successfully就说明成功了。查看当前所有集群k3d cluster list你会看到类似这样的输出能直观看到集群的状态信息NAME SERVERS AGENTS LOADBALANCER demo 1/1 0/0 true接着把Kubeconfig合并到本地默认配置让kubectl能直接连上这个集群k3d kubeconfig merge demo --kubeconfig-merge-default然后验证连通性kubectl cluster-info如果一切正常会输出集群的API Server地址和CoreDNS信息。到这里一个K3s集群已经在Docker里跑起来了。创建带有Agent节点的集群也很简单k3d cluster create demo \ --servers 1 \ --agents 2 \ -p 8080:80loadbalancer \ --volume /tmp/k3d-demo:/dataall这条命令创建的集群有两个工作节点把宿主机8080端口映射到集群的80端口并且把/tmp/k3d-demo目录挂载到所有节点。在这个集群里你可以体验多节点调度、跨节点通信这些更接近生产的特性。3.3 部署一个真实应用走通全流程集群跑起来之后光看状态没意思得实际部署点东西才有感觉。我先用一个最简单的Nginx来演示端口映射和Ingress的工作方式。先创建一个Nginx Deploymentkubectl create deployment nginx --imagenginx:alpine kubectl scale deployment nginx --replicas2创建一个Service暴露端口kubectl expose deployment nginx --port80 --target-port80再创建一个Ingress让访问nginx.localhost时能进到Nginxcat EOF | kubectl apply -f - apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: nginx spec: rules: - host: nginx.localhost http: paths: - path: / pathType: Prefix backend: service: name: nginx port: number: 80 EOF等一下Ingress Controller生效然后访问测试curl -v http://nginx.localhost如果返回了Nginx的默认页面说明整条链路已经通了。你看到K8s自带的Traefik作为Ingress Controller自动监听了新创建的Ingress资源并通过Host头路由到对应的Service。本地开发时这种*.localhost域名的方式非常方便不用配置本地DNS都能访问。3.4 镜像导入与本地开发循环在这个阶段我想分享一个真正的高频操作基于本地镜像的开发循环。绝大多数K8s开发者的痛点在于每次改代码都要走完整的构建-推送-拉取循环。k3d可以通过k3d image import直接把镜像塞进集群里。假设你的本地构建了一个叫myapp:dev的镜像docker build -t myapp:dev . k3d image import myapp:dev -c demo导入完成后直接在Deployment里使用这个镜像K3s会自动从本地Docker存储中取用kubectl create deployment myapp --imagemyapp:dev之后每次修改代码只需重复执行构建和导入两条命令再重启一下Deploymentkubectl rollout restart deployment/myapp这样一轮迭代大概能控制在几十秒内比推到远程仓库再拉下来快了不是一点点。3.5 创建多集群进行隔离测试使用k3d进行多集群操作时每个集群都有独立的集群名称。它们的配置互不影响。我在做两个版本对比测试时通常会同时创建两个集群k3d cluster create v1 --servers 1 --agents 1 k3d cluster create v2 --servers 1 --agents 1然后分别操作对应的Kubeconfig上下文kubectl config get-contexts kubectl config use-context k3d-v1 kubectl config use-context k3d-v2两个集群互不干扰可以同时跑不同的应用版本做对比测试。等测试完直接删除对应集群即可k3d cluster delete v1这种多集群模式还特别适合测试多集群ServiceMesh、跨集群通信等场景。在我做过的一次模拟中两个集群通过--volume挂载共享数据目录再配合--network让它们处于同一个Docker网络内实现了跨集群的网络互通测试效果非常理想。3.6 删除集群与资源清理开发完不用的集群就应该果断删除别让它一直占着内存。删除单个集群k3d cluster delete demo执行完后检查是否还有残留docker ps -a | grep k3d正常情况下列表应该是空的。如果发现有残留容器手动清理docker rm $(docker ps -a | grep k3d | awk {print $1})k3d的容器在删除集群时默认会同步删除但Docker网络有时会残留需要手动确认一下docker network ls | grep k3d如果还有残留同样手动删除docker network rm k3d-demo4. 常见问题与排查技巧实录4.1 集群创建失败的排查思路k3d在创建集群时挂掉的场景不算少见但绝大多数问题都出在几个固定环节。我把实际遇到过的问题整理成了一张速查表现象可能原因排查命令解决办法创建超时卡在拉取镜像网络不稳定或镜像仓库连接慢docker pull rancher/k3s配置镜像加速或手动pull镜像后再create端口被占用宿主机8080等端口被其他进程占用lsof -i :8080更换映射端口如-p 8081:80loadbalancer容器创建失败资源不足Docker没有足够的内存或存储docker system df清理不用的容器和镜像或扩大Docker资源配额节点启动失败日志报错K3s镜像与k3d版本不兼容k3d version与镜像标签对比指定兼容的镜像版本集群命令正常但kubectl连不上Kubeconfig未合并或上下文不对k3d kubeconfig get demo重新合并或手动指定--kubeconfig其中镜像拉取问题是最常见的。如果你所在环境的网络访问Docker Hub比较慢建议在创建集群前手动拉取镜像一次docker pull rancher/k3s:latest这样避免了k3d在创建过程中因为拉取超时而中断。如果网络长期不稳定也可以修改Docker的镜像加速配置把Docker Hub的镜像拉取加速。4.2 Kubeconfig相关的典型问题K3s集群创建成功但kubectl执行任何命令都报connection refused这个问题的排查思路其实非常固定。先检查上下文kubectl config current-context然后检查k3d里的集群状态k3d cluster list如果集群是健康的但kubectl连不上那多半是Kubeconfig文件里的集群地址不对。k3d集群的API Server默认绑定在0.0.0.0:6443但你在容器外部访问时需要通过映射端口或者使用宿主机地址。解决办法是重新合并k3d kubeconfig merge demo --kubeconfig-merge-default -f-f的意思是强制覆盖之前的配置。然后验证kubectl cluster-info正常情况下输出里会有Kubernetes control plane is running at这样就说明连接正常。4.3 端口映射不生效的排查端口映射不生效也是高频问题之一。有时候集群正常、服务正常、Ingress也建了但访问localhost:8080就是没有任何响应。排查顺序是这样三步第一步确认宿主机端口确实被Docker的端口转发监听了lsof -i :8080如果输出空说明k3d的Loadbalancer容器没有正确绑定端口。查看Loadbalancer容器状态docker ps --filter namek3d-demo-serverlb正常状态应该是Up。如果容器反复重启基本可以断定负载均衡器启动失败原因多半是端口冲突或者配置问题。第二步检查集群内的Service是否正常kubectl get svc kubectl get endpoints如果Endpoints为空说明Pod没有正常运行或者标签选择器不对Service没有可用的后端。第三步检查Ingress规则是否指对了Service名和端口。这里有个经常踩的坑Service的端口名称和Ingress里写的端口号不匹配导致路由失败。4.4 使用私有镜像仓库如果团队内部有私有镜像仓库或者你需要使用自建的Registry来管理镜像k3d也内置了支持。最推荐的方式是创建集群时直接指定Registryk3d registry create myregistry --port 5000 k3d cluster create demo --registry-use myregistry:5000然后配置Docker客户端允许不安全的HTTP Registry{ insecure-registries: [localhost:5000] }修改完Docker配置后重启Docker服务就可以直接往这个registry里推送镜像了docker push localhost:5000/myapp:v1K3s集群内的节点能够拉取到这个Registry中的镜像是因为k3d在创建集群时自动在所有节点上配置了对应的镜像仓库地址。这块配置通常不需要手动处理但如果你的Registry配置了认证信息就需要在k3d的配置文件中进行更详细的定义。4.5 性能调优与资源控制技巧k3d虽然轻量但如果不注意资源控制多个集群叠在一起还是可能把本地机器拖垮。下面几个做法在实际项目里很有用。限制每个节点可用的内存和CPU。k3d的--agents-memory和--agents-cpu可以分别限制Agent节点的资源用量k3d cluster create demo \ --agents 2 \ --agents-memory 1g \ --agents-cpu 2对于Server节点可以传递K3s参数来减少资源占用k3d cluster create demo \ --k3s-arg --disablemetrics-serverserver:* \ --k3s-arg --disabletraefikserver:*server:*是k3d的一个特性语法表示该参数只作用于所有Server节点。禁用Metrics Server和Traefik后集群内存占用能再降一截。不过要注意禁用Traefik之后Ingress功能不可用你需要自己安装其他Ingress Controller或改用NodePort方式暴露服务。另外一个容易被忽略的点是K3s默认会在集群里启用一些额外的控制器和特性但不是每个开发场景都需要它们。在资源紧张的机器上可以考虑禁用掉不需要的组件让系统资源集中在真正要测试的负载上。4.6 k3d与CI环境的集成聊完本地开发k3d在CI环境里的价值同样值得单独说一下。在CI流水线中你经常需要一套干净的K8s环境来跑集成测试。k3d因为启动快、不需要嵌套虚拟化、只依赖Docker所以非常适合作为GitHub Actions等CI平台里的测试集群。在CI里使用k3d的基本套路是这样- name: Start k3s cluster run: | k3d cluster create ci-cluster \ --servers 1 \ --no-lb--no-lb会跳过Loadbalancer容器的创建因为CI里通常不需要端口映射这样可以再省一点资源。测试完成后直接删掉集群保证CI环境是干净的- name: Clean up run: k3d cluster delete ci-cluster在这个模式中有几个CI特有的坑值得提前预防。比如一些CI环境默认没有安装Docker CLI或者Docker daemon用户权限不同需要先在CI脚本里安装或确认Docker环境。再比如CI环境中K3s需要系统权限来创建iptables规则如果agent运行在非特权模式可能会失败。这些在初始化流水线时都要考虑到。5. 进阶使用技巧与扩展场景5.1 通过K3s参数定制集群行为k3d一个很强大的地方是可以把任意K3s参数透传进去。这意味着你可以非常细致地定制集群的行为。比如关闭Traefik改用自己熟悉的Ingress Controllerk3d cluster create demo --k3s-arg --disabletraefikserver:0比如配置K3s的日志级别和存储路径k3d cluster create demo \ --k3s-arg --log-leveldebugserver:* \ --k3s-arg --data-dir/var/lib/k3sserver:*再比如开启K3s的Docker容器运行时模式而不是默认的containerdk3d cluster create demo --k3s-arg --dockerserver:*这个模式在调试本地镜像时非常有用因为Docker运行时可以直接访问宿主的Docker守护进程使用本地缓存的镜像省去了镜像导入的步骤。不过这个模式只建议在单节点开发环境中使用多节点集群下的行为可能会与预期不一致。5.2 多集群配置与集群切换前面提到过可以用多个集群做隔离测试这里再把集群切换的细节讲透。k3d创建的每个集群都会有一套对应的Kubeconfig上下文命名格式通常是k3d-集群名。使用k3d kubeconfig merge可以把多个集群的配置都合并到一个Kubeconfig文件中然后通过标准的kubectl上下文切换来管理k3d cluster create alpha k3d cluster create beta k3d kubeconfig merge alpha --kubeconfig-merge-default k3d kubeconfig merge beta --kubeconfig-merge-default kubectl config get-contexts kubectl config use-context k3d-alpha切换上下文之后你的kubectl操作就作用于对应的集群了。如果经常要在多个集群间切换建议结合一些shell别名来减少输入成本比如在~/.zshrc里加alias k3d-alphakubectl config use-context k3d-alpha alias k3d-betakubectl config use-context k3d-beta5.3 模拟高可用控制平面k3d也支持模拟高可用控制平面。方法很简单直接指定多个Server节点k3d cluster create ha-demo --servers 3 --agents 2当--servers等于3时k3d会启用K3s的内置etcd模式三个Server节点组成一个etcd集群任意一个节点宕机集群仍能正常工作。这种模式适合验证高可用相关的行为比如控制平面节点故障时Pod如何调度、Leader选举是否正常等。需要提醒的是3个Server节点加2个Agent节点的集群内存开销会显著增加建议在资源充足的机器上运行。我在8GB内存的笔记本上跑过一个这样的集群明显能感觉到系统有压力不推荐在低配置机器上长期运行。5.4 与Helm和Kustomize的结合集群跑起来之后部署应用通常不会只用kubectl apply而是会用到Helm或Kustomize。k3d对这些工具没有任何限制因为它们都是直接通过Kubeconfig与API Server交互的。使用Helm部署应用只需要确保kubectl当前上下文指向k3d集群helm install myapp ./chart --kube-context k3d-demo使用Kustomize也很常见kubectl apply -k ./overlays/dev这样一个完整的开发闭环就非常清晰了代码改动 - 构建镜像 - 导入集群 - helm upgrade - 验证 - 销毁集群。整个循环几乎全部在本地完成没有网络延迟没有配额限制开发体验非常顺畅。5.5 k3d配置文件方式的进阶用法命令行参数适合简单场景但如果你需要一组固定的集群配置供团队复用k3d的配置文件方式会更加方便。k3d官方支持YAML格式的配置。一个典型的配置文件示例apiVersion: k3d.io/v1alpha5 kind: Simple metadata: name: dev-cluster servers: 1 agents: 2 ports: - port: 8080:80 nodeFilters: - loadbalancer volumes: - volume: /tmp/data:/data nodeFilters: - all options: k3s: extraServerArgs: - --disabletraefik保存为k3d-config.yaml然后创建k3d cluster create --config k3d-config.yaml配置文件的好处是可重复、可版本控制。团队新成员加入时不再需要手工敲一堆命令拉取仓库一条命令就能得到一套完整且一致的K3s环境。这种标准化方式在团队协作中特别有价值。5.6 k3d在边缘计算模拟中的角色最后再聊一个容易被忽视的使用场景边缘计算模拟。K3s本身主打边缘所以k3d天然适合在本地模拟多节点边缘部署。你可以为每个边缘站点分配一个k3d集群再通过--volume挂载不同的配置文件来模拟不同的站点状态。比如模拟一个边缘站点的资源受限环境k3d cluster create edge-sim \ --servers 1 \ --agents 1 \ --agents-memory 512m \ --agents-cpu 1 \ --volume /tmp/edge-config:/configall这种方式对测试边缘场景下的应用行为非常有帮助特别是验证资源限制、断网重连、数据同步这些场景。因为每个k3d集群都是独立的Docker网络你甚至可以通过切断某个集群的网络来模拟边缘节点离线观察应用的整体表现。写在最后的几点经验我在实际使用k3d的过程中踩过几次坑也积累了一些心得。最想说的一点是k3d虽好但别忘了它本质上是为开发环境设计的。它的目标不是模拟生产环境的所有细节而是让你在本地快速获得一个可用的K8s集群用来验证代码、跑通流程、调试问题。如果你需要验证的是生产环境的复杂网络策略、存储插件、或者大规模的调度行为那还是应该老老实实用kind或者云上的托管集群。另外k3d的官方文档更新速度很快新的参数和特性经常在版本迭代中出现。如果你在一个旧版本上遇到了莫名的问题不妨先检查一下k3d和K3s镜像的版本是否匹配在升级k3d之后把之前创建的集群删除并重新创建一遍很多奇怪的问题都会自愈。如果你之前一直是在远程集群上做开发我强烈建议你花一天时间把本地k3d环境搭起来。那种改完代码二十秒就能在K8s里看到变化的体验真的会改变你的开发习惯。