news 2026/6/14 22:06:53

Pod 重启 IP 就变——Nacos 上 k8s 的三个致命问题与完整解决方案

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Pod 重启 IP 就变——Nacos 上 k8s 的三个致命问题与完整解决方案

Pod 重启 IP 就变——Nacos 上 k8s 的三个致命问题与完整解决方案


Deployment 部署 Nacos,重启后集群全员失联

团队决定把 Nacos 迁移到 k8s。我想着"三个 Deployment 不就完了"——结果踩了一串连环坑。

第一版配置:

apiVersion:apps/v1kind:Deploymentmetadata:name:nacosspec:replicas:3

三个 Pod 跑起来,控制台能看到所有节点。一切正常。直到有一天——Pod-0 被 k8s 调度器驱逐重启,新 Pod 拿到了新 IP。

cluster.conf 里还写着旧 IP。三个节点互相找不到对方,集群裂了。

后来发现三个问题:

  1. Pod IP 会变,重启后 cluster.conf 里存的是旧地址。
  2. 不能用 Deployment,需要稳定的 Pod 标识来维护集群拓扑。
  3. 自发现机制和 Readiness Probe 会打架——启动中就被 Service 路由了流量。

下面把 k8s 部署 Nacos 的正确姿势完整拆开。


第一个问题:Pod IP 不稳定

cluster.confnacos-pod-2(IP: 10.244.1.25)nacos-pod-1(IP: 10.244.1.24)nacos-pod-0(IP: 10.244.1.23)k8s Schedulercluster.confnacos-pod-2(IP: 10.244.1.25)nacos-pod-1(IP: 10.244.1.24)nacos-pod-0(IP: 10.244.1.23)k8s Scheduler集群正常运行nacos-pod-0 拿到新 IP新 IP: 10.244.1.58不通!纳维斯自杀式连接集群裂→只剩两个节点内部通信→一切仍看似正常驱逐 Pod-0重建 Pod-0读 cluster.conf → 10.244.1.23尝试连接 10.244.1.23(旧 IP)发现 Pod-0 失联发现 Pod-0 失联

Pod 重启后 IP 变化,cluster.conf 里的旧 IP 失效。如果两个以上节点同时受此影响——集群完全崩溃。

解决:StatefulSet + Headless Service

StatefulSet 给每个 Pod 分配固定网络标识

nacos-0.nacos-headless.nacos.svc.cluster.local nacos-1.nacos-headless.nacos.svc.cluster.local nacos-2.nacos-headless.nacos.svc.cluster.local

Pod 重启后域名不变,即使 IP 变了。

# headless-service.yamlapiVersion:v1kind:Servicemetadata:name:nacos-headlessnamespace:nacosspec:clusterIP:None# Headless Service:不分配 ClusterIPselector:app:nacosports:-name:httpport:8848targetPort:8848-name:grpc-clientport:9848targetPort:9848-name:grpc-clusterport:9849targetPort:9849

坑1:不能用普通 Service,必须 Headless。普通 Service 有 ClusterIP,所有流量经过它代理,Pod 不知道自己的域名。Headless Service(clusterIP: None)让每个 Pod 获得独立 DNS 记录。


第二个问题:Deployment 不适合有状态集群

Deployment 管的是"无状态副本"——Pod 从哪个节点启动无所谓,名称随机,IP 随机。但集群模式需要:

  • 启动顺序可控(先启动的当 Leader)
  • 每个节点有固定身份标识
  • 滚动更新时知道"现在重启的是哪个"

StatefulSet 完美匹配这三个需求:

StatefulSet 保障

固定 Pod 名称
nacos-0 / nacos-1 / nacos-2

有序启动
nacos-0 → nacos-1 → nacos-2

有序终止
nacos-2 → nacos-1 → nacos-0

独立 PVC
每个 Pod 绑定专属存储

cluster.conf 用 DNS 名
重启后不丢节点

避免脑裂:第一个 Pod
先成为 Leader

优雅下线:从集群
中正常退出

StatefulSet 四大保障:固定名称、有序启动、逆序终止、独立存储。每一项都命中集群部署的痛点。

完整 StatefulSet 配置

# statefulset.yamlapiVersion:apps/v1kind:StatefulSetmetadata:name:nacosnamespace:nacosspec:serviceName:nacos-headless# 绑定 Headless Servicereplicas:3podManagementPolicy:Parallel# 并行启动(非严格有序,但第一个先启)selector:matchLabels:app:nacostemplate:metadata:labels:app:nacosspec:# 反亲和:三个 Pod 尽量分布在不同节点上affinity:podAntiAffinity:requiredDuringSchedulingIgnoredDuringExecution:-labelSelector:matchLabels:app:nacostopologyKey:kubernetes.io/hostnamecontainers:-name:nacosimage:nacos/nacos-server:v2.3.2env:-name:MODEvalue:"cluster"-name:PREFER_HOST_MODEvalue:"hostname"-name:NACOS_SERVERSvalue:"nacos-0.nacos-headless.nacos.svc.cluster.local:9849 nacos-1.nacos-headless.nacos.svc.cluster.local:9849 nacos-2.nacos-headless.nacos.svc.cluster.local:9849"-name:SPRING_DATASOURCE_PLATFORMvalue:"mysql"-name:MYSQL_SERVICE_HOSTvalue:"mysql.nacos.svc.cluster.local"-name:MYSQL_SERVICE_PORTvalue:"3306"-name:MYSQL_SERVICE_DB_NAMEvalue:"nacos_config"-name:MYSQL_SERVICE_USERvalueFrom:secretKeyRef:name:nacos-mysql-secretkey:username-name:MYSQL_SERVICE_PASSWORDvalueFrom:secretKeyRef:name:nacos-mysql-secretkey:passwordports:-containerPort:8848name:http-containerPort:9848name:grpc-client-containerPort:9849name:grpc-clusterreadinessProbe:httpGet:path:/nacos/v1/console/health/readinessport:8848initialDelaySeconds:30periodSeconds:10failureThreshold:5livenessProbe:httpGet:path:/nacos/v1/console/health/livenessport:8848initialDelaySeconds:60periodSeconds:20failureThreshold:3

第三个问题:Readiness Probe 与启动时间打架

坑2:Readiness Probe 太早探活。Nacos 集群启动需要 30~60 秒(初始化数据库 + 选举)。如果initialDelaySeconds设太短,Pod 还没准备好就被打入 Service 后端,请求直接超时。

# 推荐值(生产环境)readinessProbe:httpGet:path:/nacos/v1/console/health/readinessport:8848initialDelaySeconds:60# 给足启动时间periodSeconds:10failureThreshold:5# 容忍偶尔超时livenessProbe:httpGet:path:/nacos/v1/console/health/livenessport:8848initialDelaySeconds:120# 比 readiness 更晚periodSeconds:20failureThreshold:3

Nacos 内部有两个健康端点:

端点含义探活类型
/nacos/v1/console/health/readiness服务是否准备好接收请求Readiness Probe
/nacos/v1/console/health/liveness进程是否存活Liveness Probe

如果 Liveness Probe 失败,k8s 会杀死 Pod 重建。Readiness 失败只是暂时不路由流量。

坑3:Liveness Probe 设置太激进。选举期间 Nacos 可能短暂不响应,不要因为一两次失败就 kill 容器。


对外暴露:集群内外双通道

k8s 集群外

k8s 集群内

直连

通过 NodePort/LoadBalancer

业务 Pod

Nacos Headless Service
域名:nacos-headless.nacos

nacos-0

nacos-1

nacos-2

集群外客户端

Nacos 对公 Service

# service-for-external.yaml# 给集群外客户端和控制台访问apiVersion:v1kind:Servicemetadata:name:nacos-externalnamespace:nacosspec:type:NodePort# 或 LoadBalancerselector:app:nacosports:-name:httpport:8848targetPort:8848nodePort:30848# 对外暴露的端口

两套 Service:Headless 给集群内 Pod 直连(固定 DNS),NodePort/LoadBalancer 给集群外客户端和控制台访问。


ConfigMap 统一管理配置

# configmap.yamlapiVersion:v1kind:ConfigMapmetadata:name:nacos-confignamespace:nacosdata:application.properties:|spring.sql.init.platform=mysqldb.num=1 db.url.0=jdbc:mysql://mysql.nacos.svc.cluster.local:3306/nacos_config?useSSL=false&serverTimezone=Asia/Shanghainacos.core.auth.enabled=true nacos.core.auth.server.identity.key=nacos nacos.core.auth.server.identity.value=nacos

通过volumeMounts挂入 Pod:

volumeMounts:-name:nacos-confmountPath:/home/nacos/conf/application.propertiessubPath:application.propertiesvolumes:-name:nacos-confconfigMap:name:nacos-config

Helm 一键部署(懒人版)

# 添加 Nacos Helm 仓库helm repoaddnacos https://nacos-group.github.io/nacos-helm helm repo update# 一键安装helminstallnacos nacos/nacos\--namespacenacos\--create-namespace\--setglobal.mode=cluster\--setreplicaCount=3\--setmysql.enabled=true\--setmysql.mysqlUser=nacos\--setmysql.mysqlPassword=Nacos@2024# 验证kubectl get pods-nnacos-w# nacos-0 nacos-1 nacos-2 Running

常见 k8s 部署问题速查

现象原因解决
Pod 反复 CrashLoopBackOffLiveness Probe 太激进initialDelaySeconds设 120s+
集群成员列表只看到自己NACOS_SERVERS写的是 Pod IP 不是 DNS改用 Headless Service DNS 名
注册的服务跨 Pod 查不到未共享 MySQL,各 Pod 用内置 Derby配置共享 MySQL
启动后 Pod 被 Service 路由但仍 503Readiness Probe 还没探活成功耐心等 30~60s,不要过早请求
podAntiAffinity导致 Pending节点数少于 Pod 数改为preferredDuringScheduling

总结

Nacos 上 k8s 的五个核心决策:

  1. StatefulSet 不是 Deployment:需要固定 Pod 名 + DNS 做集群发现。
  2. Headless Service 不是普通 ServiceclusterIP: None给每个 Pod 独立 DNS。
  3. cluster.conf 用 DNS 名不是 IPnacos-0.nacos-headless.nacos.svc.cluster.local:9849
  4. Probe 要宽松initialDelaySeconds给 60~120 秒,选举期间容忍失败。
  5. MySQL 是必须的:不能指望 Pod 本地的 Derby 来做集群数据同步。

从 Deployment 踩坑到 StatefulSet + Headless Service 组合,其实就改了三处:kind: StatefulSet+serviceName绑定 +NACOS_SERVERS换 DNS。但每一处都踩过坑才知道。


你们 Nacos 跑在什么环境?评论区留个数字:1=传统虚拟机部署 2=裸 Docker 容器 3=k8s StatefulSet 4=Nacos 托管服务(MSE/PolarisMesh 等)。顺带说一句你觉得 Nacos 上 k8s 最大的坑是什么。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/15 2:04:28

在Azure Pipelines中使用Cypress进行端到端测试的实践

在现代Web开发中,端到端(E2E)测试是确保应用程序功能完整性的关键步骤。特别是在微服务架构和复杂的前后端分离应用中,E2E测试变得尤为重要。本文将介绍如何在Azure Pipelines中配置并运行Cypress测试,以确保.NET Angular应用的质量。 背景介绍 假设我们有一个使用dotne…

作者头像 李华
网站建设 2026/6/15 4:06:21

遗传算法工程落地:编码、适应度与参数调优三重实战

1. 项目概述:为什么第二部分比第一部分更“落地”?“遗传算法入门——第二部分”这个标题乍看平平无奇,但如果你翻过第一部分,就会发现它几乎只讲了生物隐喻:染色体、基因、交叉、变异、适应度……像一本精美的科普插画…

作者头像 李华
网站建设 2026/6/14 19:26:13

前端综合实战:跨域通信、离线存储与 URL 到页面全流程

文章目录前言一、同源策略与跨域1.1 同源定义1.2 跨域解决方案二、跨标签页通信2.1 BroadcastChannel2.2 localStorage 事件2.3 SharedWorker2.4 方案对比三、SSE vs WebSocket3.1 SSE(Server-Sent Events)3.2 WebSocket3.3 区别四、离线存储方案选型4.1…

作者头像 李华
网站建设 2026/6/15 1:25:02

Mythos推理架构:可编程、可审计的门控式高阶推理系统

1. 项目概述:一次被刻意“锁住”的能力跃迁如果你最近关注大模型前沿动态,大概率在技术社区、AI从业者群或邮件列表里见过“TAI #200”这个编号——它不是某篇论文的DOI,也不是某个开源项目的Release Tag,而是The AI Alignment Ne…

作者头像 李华
网站建设 2026/6/14 14:37:57

如何高效实现番茄小说离线阅读:专业工具完整指南

如何高效实现番茄小说离线阅读:专业工具完整指南 【免费下载链接】Tomato-Novel-Downloader 番茄小说下载器不精简版 项目地址: https://gitcode.com/gh_mirrors/to/Tomato-Novel-Downloader 在数字阅读日益普及的今天,番茄小说下载器为读者提供了…

作者头像 李华
网站建设 2026/6/14 15:21:53

OpCore-Simplify:终极Hackintosh配置简化引擎实战指南

OpCore-Simplify:终极Hackintosh配置简化引擎实战指南 【免费下载链接】OpCore-Simplify A tool designed to simplify the creation of OpenCore EFI 项目地址: https://gitcode.com/GitHub_Trending/op/OpCore-Simplify OpCore-Simplify是一款革命性的Open…

作者头像 李华