
1. 为什么需要专门的Nacos生产部署方案在Kubernetes环境中部署Nacos集群与传统的物理机部署存在显著差异。我经历过从虚拟机迁移到Kubernetes的完整过程发现至少有三个方面需要特别注意首先是网络拓扑的变化。Kubernetes的Pod IP是动态分配的传统的基于固定IP的集群发现机制需要调整为Service域名发现。这直接影响到nacos-cluster.conf的配置方式我曾因此导致整个集群无法形成法定人数(quorum)。其次是存储的持久化问题。在默认配置下Nacos的嵌入式Derby数据库会随着Pod的重启而丢失数据。生产环境必须配置外部MySQL集群但官方文档对Kubernetes下的MySQL连接配置描述不够详细。最后是资源管理的差异。物理机部署时我们可以根据机器配置估算资源需求但在Kubernetes中需要精确设置requests/limits。特别是JVM内存参数与容器内存限制的关系配置不当会导致频繁OOMKilled。2. 生产级部署架构设计2.1 高可用架构拓扑经过多次生产验证我推荐采用下图所示架构[Nginx Ingress] | [Service: nacos-headless] | [Pod: nacos-0] --- [Pod: nacos-1] --- [Pod: nacos-2] | | | [PVC: nacos-0] [PVC: nacos-1] [PVC: nacos-2] | | | [MySQL MGR集群] [Redis哨兵集群] [PrometheusAlertmanager]关键设计要点使用Headless Service实现Pod间直接通信每个Pod绑定独立PVC保证日志持久化MySQL采用MGR集群确保数据高可用监控体系需要覆盖JVM、中间件和K8s指标2.2 资源配置计算公式对于生产环境我总结出以下资源配置公式CPU:基础需求 核数 × 1.5 (安全系数)例如3节点集群3 × 2核 × 1.5 9核总量内存:JVM堆内存 (容器内存限制 - 1GB) × 0.7例如设置4GB限制-Xms2457m -Xmx2457m存储:日志存储 每日日志量 × 保留天数 × 副本数通常配置50Gi/节点能满足两周需求3. 详细部署步骤3.1 前置条件准备# 创建专用命名空间 kubectl create ns nacos-prod # 准备MySQL配置文件 cat EOF mysql-config.cnf [mysqld] server-id \${POD_INDEX} log-bin mysql-bin binlog_format ROW transaction_isolation READ-COMMITTED EOF # 创建Secret存储数据库密码 kubectl create secret generic mysql-secret \ --from-literalpasswordNacos123 \ -n nacos-prod3.2 StatefulSet核心配置apiVersion: apps/v1 kind: StatefulSet metadata: name: nacos namespace: nacos-prod spec: serviceName: nacos-headless replicas: 3 template: spec: containers: - name: nacos image: nacos/nacos-server:2.4.0 env: - name: MODE value: cluster - name: SPRING_DATASOURCE_PLATFORM value: mysql - name: MYSQL_SERVICE_HOST value: mysql-mgr.nacos-prod.svc.cluster.local - name: MYSQL_SERVICE_DB_NAME value: nacos_config - name: MYSQL_SERVICE_USER value: nacos - name: MYSQL_SERVICE_PASSWORD valueFrom: secretKeyRef: name: mysql-secret key: password ports: - containerPort: 8848 name: client - containerPort: 9848 name: raft readinessProbe: httpGet: path: /nacos/health port: 8848 initialDelaySeconds: 30 periodSeconds: 10 resources: limits: cpu: 2 memory: 4Gi requests: cpu: 1 memory: 2Gi volumeMounts: - name: config mountPath: /home/nacos/conf - name: logs mountPath: /home/nacos/logs volumeClaimTemplates: - metadata: name: logs spec: accessModes: [ ReadWriteOnce ] storageClassName: csi-rbd-sc resources: requests: storage: 50Gi3.3 网络与服务配置apiVersion: v1 kind: Service metadata: name: nacos-headless namespace: nacos-prod annotations: service.alpha.kubernetes.io/tolerate-unready-endpoints: true spec: clusterIP: None ports: - name: client port: 8848 targetPort: client - name: raft port: 9848 targetPort: raft selector: app: nacos publishNotReadyAddresses: true --- apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: nacos-ingress namespace: nacos-prod annotations: nginx.ingress.kubernetes.io/upstream-hash-by: $remote_addr spec: ingressClassName: nginx rules: - host: nacos.company.com http: paths: - path: / pathType: Prefix backend: service: name: nacos-headless port: number: 88484. 关键调优参数4.1 JVM参数优化在configmap中添加以下JVM参数JAVA_OPT${JAVA_OPT} -server -Xms2g -Xmx2g JAVA_OPT${JAVA_OPT} -XX:MetaspaceSize256m -XX:MaxMetaspaceSize512m JAVA_OPT${JAVA_OPT} -XX:UseG1GC -XX:MaxGCPauseMillis200 JAVA_OPT${JAVA_OPT} -XX:HeapDumpOnOutOfMemoryError JAVA_OPT${JAVA_OPT} -Djava.security.egdfile:/dev/./urandom4.2 集群通信参数# conf/cluster.conf nacos-0.nacos-headless.nacos-prod.svc.cluster.local:8848 nacos-1.nacos-headless.nacos-prod.svc.cluster.local:8848 nacos-2.nacos-headless.nacos-prod.svc.cluster.local:8848 # conf/application.properties nacos.core.protocol.raft.data.dir/home/nacos/data/raft nacos.naming.distro.taskDispatchThreadCount8 nacos.naming.distro.taskDispatchPeriod1000 nacos.naming.distro.batchSyncKeyCount10005. 生产验证与监控5.1 健康检查方案# 集群状态检查 curl -X GET http://nacos.company.com/nacos/v1/ns/operator/health?formatjson # 节点健康检查 for pod in $(kubectl get pods -n nacos-prod -l appnacos -o name); do kubectl exec -n nacos-prod $pod -- curl -s localhost:8848/nacos/health done # 数据库连接检查 kubectl exec -n nacos-prod nacos-0 -- \ mysql -hmysql-mgr -unacos -p$MYSQL_PWD -e SHOW DATABASES;5.2 Prometheus监控配置- job_name: nacos metrics_path: /nacos/actuator/prometheus kubernetes_sd_configs: - role: pod namespaces: names: [nacos-prod] relabel_configs: - source_labels: [__meta_kubernetes_pod_label_app] action: keep regex: nacos - source_labels: [__address__] action: replace regex: ([^:])(?::\d)? replacement: ${1}:8848 target_label: __address__6. 故障处理实录6.1 脑裂问题处理当网络分区发生时可能出现以下症状控制台显示节点健康但配置修改不同步客户端获取的配置出现不一致日志中出现leader timeout警告解决方案检查raft日志确认leader状态kubectl exec -n nacos-prod nacos-0 -- \ tail -100 /home/nacos/logs/nacos-raft.log强制重置集群状态谨慎操作# 停止所有Pod kubectl scale sts nacos --replicas0 -n nacos-prod # 清理raft数据 for i in 0 1 2; do kubectl exec -n nacos-prod nacos-$i -- \ rm -rf /home/nacos/data/raft/* done # 重启集群 kubectl scale sts nacos --replicas3 -n nacos-prod6.2 客户端连接优化常见客户端问题及解决方案问题现象可能原因解决方案长轮询超时客户端未使用集群模式配置所有节点地址配置更新延迟客户端缓存时间过长调整cacheMillis参数频繁重连网络抖动或DNS解析问题启用客户端本地缓存Java客户端推荐配置Properties properties new Properties(); properties.put(PropertyKeyConst.SERVER_ADDR, nacos.company.com:8848); properties.put(PropertyKeyConst.NAMESPACE, prod-env); // 启用故障转移模式 properties.put(PropertyKeyConst.ENABLE_REMOTE_SYNC_CONFIG, true); // 设置本地缓存 properties.put(PropertyKeyConst.CONFIG_LONG_POLL_TIMEOUT, 30000); properties.put(PropertyKeyConst.CONFIG_RETRY_TIME, 5000);7. 升级与维护策略7.1 滚动升级方案采用分批次升级策略确保服务不中断先升级一个从节点并验证手动触发leader切换curl -X PUT http://nacos-0:8848/nacos/v1/ns/operator/leader升级原leader节点最后升级剩余从节点7.2 数据迁移流程从旧版本迁移的关键步骤使用官方工具导出配置nacos-export.sh --export --dir /backup \ --host old.nacos.com --port 8848验证备份数据完整性在新集群执行导入nacos-import.sh --import --dir /backup \ --host new.nacos.com --port 8848保持双集群并行运行至少24小时8. 安全加固措施8.1 认证与鉴权配置# application.properties nacos.core.auth.enabledtrue nacos.core.auth.system.typenacos nacos.core.auth.plugin.nacos.token.secret.keyVGhpc0lzQXZlcnlTZWNyZXRLZXlEZjM nacos.core.auth.server.identity.keyserverIdentity nacos.core.auth.server.identity.valuesecurity # 创建管理员账号 kubectl exec -n nacos-prod nacos-0 -- \ curl -X POST http://localhost:8848/nacos/v1/auth/users?usernameadminpasswordStrongPass1238.2 网络策略限制apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: name: nacos-access-control namespace: nacos-prod spec: podSelector: matchLabels: app: nacos policyTypes: - Ingress ingress: - from: - namespaceSelector: matchLabels: project: microservices ports: - protocol: TCP port: 8848 - protocol: TCP port: 9848在实际生产环境中运行Nacos集群两年多最大的经验是一定要提前规划好容量。我们曾经因为低估了配置变更频率导致磁盘频繁告警后来通过以下措施彻底解决配置日志自动归档脚本对历史配置设置保留策略定期清理不用的命名空间为监控系统设置合理的告警阈值