Kubernetes实战指南:从集群搭建到微服务迁移与高并发压测 📅 发布时间:2026/9/19 2:18:43 👁 浏览次数: 开始接触 Kubernetes 的人十个里有八个是先在 Docker 里把服务跑通了然后被“容器编排”这四个字卡住的。这篇文章我想用一套真实的若依RuoYi微服务环境作为主线把 k8s 从安装部署、常用命令、与 Docker 的区别到单节点集群搭建、Prometheus 监控、微服务容器化编排再到准不停服迁移到阿里云 ECS以及最后用 JMeter 做高并发压测验证承载能力整个链路完完整整走一遍。这套流程不是我纸上谈兵而是从实际项目里一步步踩出来的。前后遇到过的坑不少比如单节点上 Pod 调度不平衡、镜像推送太慢导致迁移窗口拉长、压测时 NodePort 变单点、迁移过程中 Redis 数据不一致等等。下面这些内容既有操作步骤也有我自己的取舍逻辑希望能帮你少走弯路。如果你是刚入门 k8s 的运维或后端开发或者正准备把自建微服务迁到云上这篇文章应该能直接拿来当参考。说实话k8s 这东西难的不是概念而是概念落地时的那一长串细节。1. K8s 与 Docker先理清核心概念和区别1.1 容器、Docker 与 K8s 的层级关系很多人一开始对“k8s 和 docker 区别”这个问题特别困惑是因为他们下意识把 Docker 和 k8s 放到了同一个赛道里对比。实际上这两者的定位完全不同。Docker 解决的是“怎么把应用打包成镜像然后以一个隔离的容器跑起来”而 k8s 解决的是“怎么管理成百上千个这样的容器让它们自动部署、自动伸缩、自动恢复”。打个比方Docker 像是一个标准化集装箱它规定了货物怎么装、怎么运k8s 则是整个港口的管理系统它负责调度哪些船停哪个泊位、什么时候卸货、集装箱坏了怎么替换、流量来了怎么多开几个吊臂。没有 Dockerk8s 就没有可调度的对象没有 k8sDocker 容器只能靠手工一台台去管。在 k8s 架构里真正运行容器的最小单元是 Pod。Pod 可以包含一个或多个容器这些容器共享网络命名空间和存储卷。通常一个 Pod 里只放一个主容器需要的时候再塞一个 sidecar 容器做日志采集、流量代理之类的辅助。Docker 容器被 k8s 调度时会被封装进 Pod 里统一管理所以从用户视角看操作对象不再是单个容器而是 Pod。1.2 K8s 核心对象Pod、Deployment、Service、Ingress理解 k8s第一关就是搞清这几个对象之间的关系。Pod 是最小调度单元前面说了。Deployment 则是用来声明“我要跑几个副本、用什么镜像、怎么更新”的控制器。你写一个 Deployment告诉它“nginx 镜像跑 3 个副本”k8s 的 controller-manager 就会通过 ReplicaSet 维护这 3 个 Pod 的期望状态。某个 Pod 挂了它会自动再拉起一个保证永远有 3 个在跑。Service 解决的是服务发现和负载均衡。Pod 的 IP 是动态的随时可能因重启或调度而改变你不能让其他服务去记 Pod IP。Service 提供一组稳定的虚拟 IP把流量转发到后面匹配 label 的 Pod 上。ClusterIP 是集群内访问NodePort 是暴露到宿主机端口LoadBalancer 则对接云厂商的负载均衡服务。Ingress 是七层入口负责把外部 HTTP/HTTPS 请求按域名和路径路由到不同 Service。有了 Ingress 就不需要为每个服务都申请一个 NodePort 或 LoadBalancer域名、TLS、路径转发都能在这一层统一处理。这四个对象搞明白k8s 的核心使用逻辑就通了Deployment 管 PodService 管流量分发Ingress 管外部入口。1.3 K8s 与 Docker 在实际使用中的本质区别如果只看单机场景Docker Compose 其实够用。它用 YAML 文件定义一组服务一条 docker-compose up 全部拉起来开发环境非常方便。但一旦到了生产问题就出来了某台宿主机宕机了Compose 不会自动把容器迁移到别的机器流量涨了也不会自动扩容发布版本时做不到滚动更新不中断服务。这些恰恰是 k8s 的核心能力。k8s 里有 etcd 保存集群状态controller-manager 负责让实际状态无限贴近期望状态scheduler 决定 Pod 跑在哪台节点上kubelet 管理节点上的容器生命周期。整个控制循环设计确保系统一直朝“期望状态”收敛。比如你的 Deployment 声明 5 个副本某节点宕机导致 2 个 Pod 消失k8s 会自动在其他健康节点上重建 2 个。所以在选型时我的建议是单机开发、本地调试用 Docker Compose 就挺好一旦涉及多台服务器、需要高可用、滚动发布、弹性伸缩直接上 k8s。这个界限非常清晰。2. k8s 安装部署与集群搭建从单节点开始上手2.1 安装方式选型kubeadm、k3s、minikube、云托管服务真正上手 k8s第一个问题就是“怎么装”。大多数人一开始不是要搭一个十几台的大集群而是先在自己的机器或者一台 ECS 上把环境跑起来。这里我按适用场景给你排一个顺序minikube适合本地开发一条命令起一个单节点环境用完就删。资源占用可控但别指望它模拟生产。kubeadm官方推荐的安装工具适合从零搭建真实的单节点或多节点集群也是运维上手应该掌握的方式。k3s轻量级发行版把很多内置组件做成了外部进程占用内存小适合边缘节点或配置较低的机器。单台 2G 内存的服务器跑微服务用 k3s 会舒服很多。云厂商托管版比如阿里云 ACK、腾讯云 TKE控制台点几下就给你一个生产可用的集群自动帮你维护 Master 组件。适合不想折腾基础设施、专注业务的团队。如果你是想学习 k8s 本身强烈建议用 kubeadm 亲手装一遍。这个过程会让你对组件分工有非常直观的理解。2.2 单节点 k8s 集群搭建实操记录下面是我在一台 CentOS 7.9 单机4 核 8G上使用 kubeadm 搭建单节点集群的完整过程。先做基础环境配置# 关闭 swapkubelet 默认要求必须关闭 swapoff -a sed -i / swap / s/^/#/ /etc/fstab # 加载内核模块 modprobe br_netfilter # 写入内核参数 cat EOF /etc/sysctl.d/k8s.conf net.bridge.bridge-nf-call-iptables 1 net.ipv4.ip_forward 1 vm.swappiness 0 EOF sysctl --system然后安装 Docker 和 kubeadm 相关组件# 安装 Docker这里省略 Docker 安装步骤装好之后设置 cgroup 驱动为 systemd # 配置 kubeadm 源 cat EOF /etc/yum.repos.d/kubernetes.repo [kubernetes] nameKubernetes baseurlhttps://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64/ enabled1 gpgcheck0 EOF yum install -y kubelet-1.23.17 kubeadm-1.23.17 kubectl-1.23.17 systemctl enable kubelet systemctl start kubelet初始化主节点kubeadm init \ --apiserver-advertise-address192.168.1.10 \ --image-repository registry.aliyuncs.com/google_containers \ --kubernetes-version v1.23.17 \ --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因为我是在单节点上跑Master 默认有 taint污点Pod 不会被调度到 Master 节点上。我选择直接去掉这个污点让微服务 Pod 可以运行在这台节点上kubectl taint nodes --all node-role.kubernetes.io/master-接着安装 Flannel 网络插件kubectl apply -f https://raw.githubusercontent.com/flannel-io/flannel/master/Documentation/kube-flannel.yml装完检查节点状态kubectl get nodes直到 STATUS 变成 Ready单节点集群就搭好了。整个过程如果参考阿里云的镜像源大概 20 分钟能搞定。这里有个关键点kubeadm init 的参数中 --apiserver-advertise-address 必须填节点能稳定访问的 IP不要填 127.0.0.1否则后面 kubectl 远程管理、Ingress 转发都会出问题。2.3 k8s 原生管理页面Dashboard 部署与访问集群搭好了命令行能用但很多人还是想有一个可视化页面。k8s 原生管理页面是 Kubernetes Dashboard它本身也是跑在集群里的一组 Pod。我建议在单节点学习环境直接通过 NodePort 方式暴露kubectl apply -f https://raw.githubusercontent.com/kubernetes/dashboard/v2.7.0/aio/deploy/recommended.yaml # 修改 Service 类型为 NodePort kubectl -n kubernetes-dashboard patch svc kubernetes-dashboard -p {spec:{type:NodePort}} # 查看暴露出来的端口 kubectl -n kubernetes-dashboard get svc登录 Dashboard 需要 token先创建管理员账号cat EOF | kubectl apply -f - apiVersion: v1 kind: ServiceAccount metadata: name: admin-user namespace: kubernetes-dashboard --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: admin-user roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: cluster-admin subjects: - kind: ServiceAccount name: admin-user namespace: kubernetes-dashboard EOF kubectl -n kubernetes-dashboard create token admin-user拿到这串 token再去浏览器访问 https://节点IP:NodePort选择 token 方式登录即可。页面里能看到节点状态、Pod 列表、日志、事件管理单个环境足够用了。2.4 k8s 集群搭建 Prometheus 监控体系集群装完第一件事不是急着上业务而是先把监控做起来不然后面迁移和压测就是瞎跑。单节点上搭 Prometheus 监控我推荐 kube-prometheus-stack它一次性把 Prometheus、Alertmanager、Grafana、Node Exporter、kube-state-metrics 都打包好了。在单节点环境里直接用 Helm 安装# 添加仓库 helm repo add prometheus-community https://prometheus-community.github.io/helm-charts helm repo update # 安装 helm install monitoring prometheus-community/kube-prometheus-stack \ --namespace monitoring \ --create-namespace \ --set grafana.service.typeNodePort \ --set grafana.service.nodePort30300装完之后重点看两个指标节点 CPU/内存使用率、Pod 的 CPU/内存使用率。压测的时候如果监控曲线显示 CPU 已经打满说明瓶颈在计算资源而不是应用本身。这里有一个经验单节点集群里Prometheus 本身也会吃资源如果机器只有 2G 内存先把 Prometheus 的 storage.tsdb.retention.time 调小或者用轻量级的 VictoriaMetrics 替代。别让监控系统成为第一个被压垮的服务。2.5 k8s 与 GPU 安装教程让调度器认识 GPU 资源现在很多团队在 k8s 上跑 AI 推理任务GPU 节点的安装就绕不开。这里需要引入 device plugin 机制让 kubelet 能把 GPU 作为可调度资源上报给 API Server。NVIDIA 官方提供了一组现成的 DaemonSetkubectl apply -f https://raw.githubusercontent.com/NVIDIA/k8s-device-plugin/main/nvidia-device-plugin.yml部署前要求节点上已经安装好 NVIDIA 驱动和 nvidia-container-runtime。装完检查kubectl get nodes -o json | jq .items[].status.capacity如果输出里能看到 nvidia.com/gpu: 1说明 GPU 已经被正确识别。之后在 Pod 描述里声明资源resources: limits: nvidia.com/gpu: 1调度器就会把任务调度到有 GPU 的那台节点上。这里我踩过最大的坑是驱动版本和 CUDA 版本不匹配导致 Pod 一直报错。建议先手动在宿主机跑 nvidia-smi确认驱动正常再部署 device plugin。3. 微服务容器化部署与编排以若依微服务整套环境为例3.1 若依微服务体系拆解先说说若依微服务版本RuoYi-Cloud这套东西。它并非单个应用而是一整套微服务架构Nacos 做注册中心和配置中心Gateway 做统一入口认证中心负责登录鉴权然后按业务域拆分出 system 模块、job 定时任务模块以及基于 seata 的分布式事务处理。数据层通常涉及 MySQL、Redis文件存储还可能用到 MinIO。整套环境直接扔进 k8s 里如果没理清依赖关系会陷入“服务起不来、不知道先起哪个”的泥潭里。正确的部署顺序应该是基础设施先行也就是 MySQL、Redis、Nacos 这些等注册中心就绪后再启动 Gateway 和各个业务微服务。3.2 编写 Deployment 和 Service核心步骤拆解下面用一个标准微服务如 system 模块的 YAML 示例来演示。apiVersion: apps/v1 kind: Deployment metadata: name: ruoyi-system namespace: ruoyi labels: app: ruoyi-system spec: replicas: 2 selector: matchLabels: app: ruoyi-system template: metadata: labels: app: ruoyi-system spec: containers: - name: ruoyi-system image: registry.cn-hangzhou.aliyuncs.com/my-demo/ruoyi-system:1.0.0 imagePullPolicy: IfNotPresent ports: - containerPort: 9201 env: - name: NACOS_ADDR value: nacos:8848 - name: JVM_OPTS value: -Xms512m -Xmx512m resources: requests: cpu: 250m memory: 512Mi limits: cpu: 1 memory: 1Gi readinessProbe: httpGet: path: /actuator/health port: 9201 initialDelaySeconds: 30 periodSeconds: 10 --- apiVersion: v1 kind: Service metadata: name: ruoyi-system namespace: ruoyi spec: selector: app: ruoyi-system ports: - port: 9201 targetPort: 9201 --- apiVersion: v1 kind: ConfigMap metadata: name: ruoyi-system-config namespace: ruoyi data: application.yml: | spring: cloud: nacos: server-addr: nacos:8848写这个 YAML 时有几个细节值得重点解释一下。第一为什么要配 readinessProbe 探活。微服务启动通常需要几十秒如果 k8s 在端口没完全就绪时就把流量打过来请求会超时。readinessProbe 通过健康检查确认服务可接受流量后k8s 才会把 Service 的端点加进去。我配的是 /actuator/health因为若依基于 Spring CloudSpring Boot Actuator 默认会暴露这个路径。initialDelaySeconds 给 30 秒是考虑到 JVM 启动和 Nacos 注册需要时间。第二环境变量和 ConfigMap 怎么用。Nacos 地址最好不要写死在镜像里通过 ConfigMap 或者环境变量注入这样同一条镜像发到不同环境都不用重新构建。这里我用环境变量 NACOS_ADDR 注入 Nacos 地址实际项目里更推荐整套配置都放 Nacos 配置中心统一管理。第三resources 的命名空间为什么用 250m 这种写法。在 k8s 里1 个 CPU 核心可以划分成 1000m250m 就是 0.25 个核心。requests 是调度时的最低保障limits 是运行时不可超过的上限。如果 Pod 使用量超过 limits会被 k8s 杀掉或限制。我给 system 模块设置 512Mi 的 request 和 1Gi 的 limit是考虑到 JVM 堆 512M 加上各种 Metaspace、线程栈之后整体约需要 700M 左右留出一点余量。3.3 微服务整体编排顺序与命名规范整套若依环境我建议放在一个独立的 namespace 下避免和其他环境资源互相干扰kubectl create ns ruoyi部署顺序就按依赖关系走。先部署 MySQL、Redis、MinIO再部署 Nacos。注意 Nacos 本身需要 MySQL 做持久化存储所以 MySQL 必须先可用。接着部署 auth 认证服务、system 模块、job 模块最后部署 Gateway。Gateway 是所有请求的入口需要依赖所有业务服务注册到 Nacos。有读者可能会问像“若依微服务整套环境”这种项目一个 Deployment 该取什么中文名字技术上 k8s 对象名称只支持小写字母、数字和中划线中文名并不能直接用于 metadata.name。但可以在 Deployment 上打一个中文描述性的 Label比如metadata: labels: app: ruoyi-system description: 若依系统模块这样在管理平台或 Dashboard 里能更直观辨认又不违反 k8s 命名规范。3.4 Service Mesh 方向Dubbo Mesh 与 k8s Service Mesh 的关系聊到微服务编排很多人会问到 Dubbo Mesh、Service Mesh 这类话题。在若依微服务这种规模的项目里Nacos 注册中心 直接调用已经足够不需要立刻引入 Istio 等 Service Mesh 框架。但如果服务规模膨胀到几十上百个链路追踪、流量治理、灰度发布成为刚需Service Mesh 的价值才会凸显。Service Mesh 的核心思路是把服务间通信能力从业务代码中抽离出来下沉到 Sidecar 代理。业务容器只关注业务逻辑网络策略、熔断、超时、重试这些由 Sidecar 统一处理。这个方向适合团队有足够人力维护控制平面的场景初期不建议新手一上来就上 Istio。4. 准不停服、不丢数据地把若依整套环境迁移到阿里云 ECS4.1 迁移目标与方案选型为什么选镜像迁移 数据同步现在到了整篇最实战的部分。我们要把一套已经在自建机房单节点 k8s 上跑得好好的若依微服务环境迁移到阿里云 ECS前提是“准不停服、不丢数据”。准不停服不是完全不停而是把丢失的请求控制在极少数量比如几秒内。为什么是“准不停服”而不是完全不断流因为迁移涉及数据一致性。虽然 MySQL 有主从同步、Redis 有持久化但应用层保持连接的状态比如用户登录 token 缓存在 Redis切换瞬间可能失效。我的目标是让整个切换窗口控制在 1 到 2 分钟以内业务只在这段窗口接受少量失败重试整体影响可接受。方案我分三条线并行镜像层把本地的 Docker 镜像推送到阿里云容器镜像服务 ACR云上的 k8s 集群直接拉取。数据层MySQL 用 mysqldump 做全量备份再通过 binlog 增量同步最后在切换前只做一次短暂停写Redis 用 RDB 快照迁移并在切换前做最后同步。应用层云上面先起一套新集群等数据追平之后通过改 Ingress 或负载均衡入口流量完成切换。4.2 镜像迁移从自建仓库到 ACR本地单节点 k8s 上镜像已经存在各节点本地要迁移到阿里云最保险的做法是把镜像列表导出来推送到 ACR。# 列出当前 namespace 下所有 Deployment 使用的镜像 kubectl get deployment -n ruoyi -o jsonpath{.items[*].spec.template.spec.containers[*].image} | tr \n | sort -u拿到镜像列表后先登录到 ACR然后本地重新打 tag再推送docker login --username你的账号 registry.cn-hangzhou.aliyuncs.com docker tag ruoyi-system:1.0.0 registry.cn-hangzhou.aliyuncs.com/my-demo/ruoyi-system:1.0.0 docker push registry.cn-hangzhou.aliyuncs.com/my-demo/ruoyi-system:1.0.0如果镜像数量多建议写个脚本循环处理。这里我有个教训如果本地服务器带宽上行受限推送时间会远超预期直接用 docker save 打包再通过 OSS 中转会更稳。就是把所有镜像 docker save 成一个 tar 包传到阿里云 OSS再用 ECS 从 OSS 下载后 docker load最后统一推送到 ACR。别忽略这一步因为镜像推不上去迁移窗口就会无限拉长。4.3 数据迁移MySQL 与 Redis 不丢数据的同步方案数据迁移是这个方案里最需要小心的部分。若依微服务的数据主要在 MySQL系统配置、用户、业务表和 Redis缓存、token。MySQL 我用的策略是“全量 增量”。先做主库只读锁做一次全量备份然后开启 binlog 并将目的实例设置为源实例的从库追平后解除只读锁。# 源库全量备份 mysqldump -uroot -p --single-transaction --routines --triggers --all-databases ruoyi_mysql.sql # 导入到目的实例 mysql -h 目的ECSIP -uroot -p ruoyi_mysql.sql之后配置增量同步可以用 DTS数据传输服务也可以自己搭主从复制。我自己项目里直接用 DTS因为它可以不停服做增量同步并且有监控告警。等 lag 降到 0 且稳定十几分钟之后数据就算追平了。Redis 的迁移我用了 RDB 持久化文件拷贝方式。在源 Redis 上执行 BGSAVE拿到 dump.rdb拷贝到 ECS 上再启动 Redis 时自动加载。如果业务量大这个文件会比较大建议在业务低峰期操作。切换前再确认一下 key 的有效性和数量避免漏迁移。注意不要指望 Redis 迁移过程中完全不丢 key。如果必须做到毫秒级一致就得引入 Redis 版本的双写或使用阿里云 Redis 的迁移功能。对于若依微服务绝大多数缓存都是 session、验证码、配置类数据短暂丢失影响可控。4.4 应用层切换Ingress 流量迁移与验证数据追平之后接下来是应用层的切换。云上的 k8s 集群里我已经提前部署好了和本地完全一致的 namespace、Deployment、Service镜像从 ACR 拉取。最后一步是切流量。我在实际项目里用的是一个四层负载均衡 SLB 作为统一入口后端指向新集群 Master 节点上的 Ingress NodePort。切换前先在本地 ECS 上用 curl 直接访问云上 Ingress 地址验证 Gateway 路由正常。确认无误后在 DNS 供应商后台把域名解析到一个新的负载均衡公网 IP。这里要注意 TTL 的问题。DNS 切换不是实时的老的解析记录可能还会有缓存为了平滑过渡我在切换前先把 TTL 改成 60 秒生效后再改解析。整体切换窗口大约在 1 分钟以内。切换完成后立刻做下面几项检查Ingress 日志里是否出现新节点 IP 的请求。各微服务的注册数量是否和本地一致。MySQL 和 Redis 的连接数是否在预期范围内。压测前先手工跑通登录、查询、提交流程确认业务正常。5. 高并发压测用 JMeter 脚本验证云上承载能力5.1 JMeter 压测前的准备与脚本适配迁移完成只是第一步能不能扛住线上流量得靠压测数据说话。按原要求压测人员会使用配套的 JMeter 脚本做高并发测试。这里我把脚本准备的核心几点说一下。JMeter 压测脚本通常包含线程组、HTTP 请求默认值、HTTP Header 管理器、断言、监听器。因为若依的前后端是分离的压测要覆盖几个核心接口获取验证码、登录、查询用户列表、提交表单等。有一个很关键的准备工作压测会引入大量验证码和 session 数据如果压测脚本每次都走“登录 - 获取 token - 请求业务”的完整流程对 Redis 会造成额外压力。最好让压测脚本直接复用同一个 token或者把获取 token 的请求用 Once Only Controller 包裹起来避免压测结果被登录接口干扰定位不到真实瓶颈。JMeter 线程数设置也要讲究。不要一上来就 1000 并发那只会让你的压测机自己先吃不消。我的习惯是先 100 并发跑 5 分钟观察响应时间再逐步提升到 300、500。每一步都留几分钟观察曲线。5.2 压测执行与关键监控指标解读压测过程中我一边看 JMeter 的聚合报告一边盯 Grafana 面板。聚合报告里重点关注三个指标吞吐量Throughput、平均响应时间Average、错误率Error%。如果吞吐量随着并发上升而增长响应时间保持稳定说明系统还在健康区间一旦吞吐量停止增长而响应时间直线上升说明已经达到瓶颈拐点。同时看 k8s 侧的资源使用kubectl top node kubectl top pod -n ruoyi这时候经常会出现一个有意思的现象在某些并发点Pod CPU 已经打满但节点 CPU 使用率还不高。因为单副本的 limits 把 Pod 限制住了它没法使用节点更多空闲资源。这时需要扩容副本数。另外我压测时会在应用侧打开 GC 日志观察 Full GC 频率。如果 Full GC 频繁且耗时长说明堆内存偏小需要调大 JVM。我在一次压测中遇到过 system 模块请求耗时剧烈抖动排查后是老年代不断增长Full GC 每次耗时超过 2 秒。解决方案是把 -Xmx 从 512M 调到 1G并把默认的 CMS 换成 G1抖动立刻缓解。5.3 压测暴露的问题单节点瓶颈与扩容思路单节点集群压测最容易暴露的就是“一个人干所有活”的问题。Ingress Controller、Pod、监控全部挤在一台机器上高并发时节点 CPU 率先被 ing-nginx 打满甚至业务 Pod 还没发挥实力入口已经堵死了。这时候选择很明确要么把 Ingress Controller 独占到一个节点并打污点隔离要么直接使用云上的 SLB 接入让 SLB 直接转发到 Service 的 NodePort。生产建议直接用云负载均衡少一层 Ingress 转发就少一层延迟。如果是多节点集群还可以通过节点亲和性把不同微服务调度到不同规格的节点上。比如 Gateway 对 CPU 敏感调度到高主频节点system 模块吃内存调度到大内存节点。压测之后根据资源曲线调整节点池的规格比盲目堆副本更经济。5.4 容量评估从压测结果推算承载能力压测的真正产出不是一份好看的报告而是一个“这环境到底能扛多少并发”的结论。根据 JMeter 聚合报告和监控数据我们可以做容量评估。假设压测结果显示300 并发时登录接口吞吐量 1500 req/s平均响应时间 80ms错误率 0.1%节点 CPU 使用率 70%。那么单节点这套环境承载 300 并发是稳妥的。如果业务真实峰值大约 200 并发就还有约 30% 的余量可以接受。如果压到 500 并发时响应时间超过 2 秒且错误率升高就要给出扩容建议比如将 system 模块从 2 副本扩到 4 副本或者升级 ECS 实例规格。这套评估方法适用于大多数场景。云上环境的好处是扩容路径很清晰ECS 不够就升规格Pod 不够就加副本SLB 带宽不够就升带宽。有压测数据撑着这些决策做起来就有底气。6. 常用命令与 k8s 管理工具速查6.1 我日常用得最多的 k8s 命令这里整理一份我在实际工作中反复用的命令特别是排查和迁移场景。# 查看节点和 Pod 状态 kubectl get nodes -o wide kubectl get pods -n ruoyi -o wide # 查看 Pod 详细信息排查事件 kubectl describe pod pod-name -n ruoyi # 查看容器日志加 -f 持续跟踪 kubectl logs -f pod-name -n ruoyi # 进入容器调试 kubectl exec -it pod-name -n ruoyi -- /bin/bash # 查看 Service 和 Endpoint 是否正确 kubectl get svc,ep -n ruoyi # 查看 Ingress 规则 kubectl get ingress -n ruoyi # 对 Deployment 滚动重启更新镜像后 kubectl rollout restart deployment/ruoyi-system -n ruoyi # 查看滚动状态 kubectl rollout status deployment/ruoyi-system -n ruoyi # 临时扩容 kubectl scale deployment/ruoyi-system -n ruoyi --replicas5有一段时间我排查“服务间调用不通”时总喜欢先看 Pod但真正的问题往往出在 Service 的 label selector 没有匹配上。这里建议多练一个组合拳kubectl get pod --show-labels和kubectl get svc -o yaml把 selector 和 Pod labels 对一遍十次有八次能找到答案。6.2 常用的 k8s 管理工具推荐命令行适合日常操作但如果环境复杂有个可视化工具效率会高很多。Kubernetes Dashboard前面提过k8s 原生管理页面适合学习和轻量管理。Lens桌面客户端跨 namespace 管理很方便监控和日志入口做得很完善。k9s终端下的 TUI 工具用键盘就能切 namespace、看日志、进容器是运维效率神器。kubectl 插件比如 krew可以扩展出很多实用插件比如查看镜像版本、批量清理 Evicted Pod。工具不在多顺手就好。我自己现在是 k9s 为主kubectl 为辅Dashboard 偶尔给同事远程看现场用。6.3 k8s 面试高频考点从原理到排查思路顺便把 k8s 面试里常被问到的几个点简单列一下因为这些知识点也确实是日常使用绕不开的。Deployment 滚动更新是怎么实现的它通过 ReplicaSet 做新旧版本替换先起一个新 ReplicaSet副本数逐步增加同时旧 ReplicaSet 副本数逐步减少直到全部替换完成。更新过程可以通过 maxSurge 和 maxUnavailable 控制前者允许超出期望副本数的最大 Pod 数后者允许不可用的最大 Pod 数。Pod 分配到哪个节点是 scheduler 决定的它会根据 request、亲和性、污点容忍做筛选和打分。这也是为什么要合理设置 resources不设置的话所有 Pod 都有机会挤到一个节点上资源分配很容易失衡。还有其他常被追问的kubelet 和 kube-proxy 的作用分别是什么etcd 保存了什么Service 的 ClusterIP 是如何实现负载均衡的这些如果工作中都亲手处理过回答起来并不难。真正难的是把一套系统从零搭起来再迁移出去这个过程远比背面试题有价值。尾声我在这套项目里体会最深的三件事这套从单节点 k8s 到云上迁移再到压测的流程我前后做了不止一次每次都有新的体会。第一件事k8s 最大的价值不是什么高深技术而是“声明式管理”这个思维。你把期望状态告诉它它自己负责收敛。这种思维一旦建立你再回头看手工运维会明显感觉到差距。第二件事迁移方案里最容易被低估的是数据同步我头一回做 MySQL 增量同步时只考虑了全量备份结果业务一写库就乱了。之后再小的项目我也会把 binlog 增量同步和切换预案写清楚。第三件事压测不是做完就结束它是一次容量体检报告里的每个数字都能转化为扩缩容的决策依据。最后再分享一个小技巧迁移和压测前把 kubectl get pod、kubectl top node、JMeter 聚合报告三个结果统一保留一份截图存档。出了问题回看时间线定位速度会快很多。真实生产场景不怕出问题怕的是没有参照物不知道什么时候开始变的。希望这份实战指南能让你在 k8s 这条路上少踩几个坑也欢迎大家把自己迁移和压测中遇到的典型问题拿出来交流。