如何在 K8s 环境中配置 Nacos StatefulSet 服务发现

文章导读
先说结论:生产环境建议使用 StatefulSet 部署 Nacos 集群,通过 Headless Service 实现节点间稳定域名解析,并强制接入外部 MySQL 避免数据一致性风险。
📋 目录
  1. A 1. 敏感信息安全管理
  2. B 2. 完整资源配置 YAML
  3. C 3. 数据库初始化
  4. D 4. 验证与排查
  5. E 5. 扩缩容注意事项
  6. F 参考文档
A A

先说结论:生产环境建议使用 StatefulSet 部署 Nacos 集群,通过 Headless Service 实现节点间稳定域名解析,并强制接入外部 MySQL 避免数据一致性风险。

  • 适合:需要高可用服务发现与配置管理的微服务架构场景
  • 先准备:外部 MySQL 数据库、StorageClass 存储类及集群内部域名解析环境
  • 验收:Pod 状态 Running 且集群节点间能互相 ping 通域名,控制台显示集群健康

1. 敏感信息安全管理

避免在 YAML 中明文配置数据库密码。建议使用 Kubernetes Secret 管理敏感信息,并在 StatefulSet 中引用。

# 创建 Secret(替换 your_password 为实际密码)
kubectl create secret generic nacos-db-secret \
  `--from-literal`=MYSQL_SERVICE_PASSWORD='your_password' \
  `--namespace`=default

2. 完整资源配置 YAML

以下是包含 Headless Service 和 StatefulSet 的完整配置。注意 volumeClaimTemplates 用于持久化日志,envFrom 用于安全加载密码。

apiVersion: v1
kind: Service
metadata:
  name: nacos-headless
spec:
  clusterIP: None
  selector:
    app: nacos
  ports:
    - name: server
      port: 8848
      targetPort: 8848
    - name: client-rpc
      port: 9848
      targetPort: 9848
    - name: raft-rpc
      port: 9849
      targetPort: 9849
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: nacos
spec:
  serviceName: nacos-headless
  replicas: 3
  selector:
    matchLabels:
      app: nacos
  template:
    metadata:
      labels:
        app: nacos
    spec:
      containers:
        - name: nacos
          image: nacos/nacos-server:latest
          env:
            - name: NACOS_REPLICAS
              value: "3"
            - name: PREFER_HOST_MODE
              value: "hostname"
            - name: MYSQL_SERVICE_HOST
              value: "mysql-host"
            - name: MYSQL_SERVICE_DB_NAME
              value: "nacos_config"
            - name: MYSQL_SERVICE_USER
              value: "nacos"
            - name: NACOS_SERVERS
              value: "nacos-0.nacos-headless:8848,nacos-1.nacos-headless:8848,nacos-2.nacos-headless:8848"
            - name: SPRING_DATASOURCE_PLATFORM
              value: "mysql"
          envFrom:
            - secretRef:
                name: nacos-db-secret
          ports:
            - containerPort: 8848
            - containerPort: 9848
            - containerPort: 9849
          volumeMounts:
            - name: data
              mountPath: /home/nacos/logs
  volumeClaimTemplates:
    - metadata:
        name: data
      spec:
        accessModes: ["ReadWriteOnce"]
        resources:
          requests:
            storage: 10Gi

3. 数据库初始化

Nacos 集群模式必须使用外部 MySQL。需提前创建数据库 nacos_config 并导入官方初始化脚本。

操作步骤:

如何在 K8s 环境中配置 Nacos StatefulSet 服务发现
  1. 登录 MySQL 执行:CREATE DATABASE nacos_config DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
  2. 下载官方脚本:mysql-schema.sql
  3. 导入脚本到数据库。

4. 验证与排查

1. 检查 Pod 状态

确保所有副本状态为 Running 且 READY 为 1/1。

kubectl get pods -l app=nacos -o wide

2. 验证内部域名解析

进入任意 Pod 内部,测试 Headless Service 域名解析是否生效(避免硬编码具体 Pod 名称)。

如何在 K8s 环境中配置 Nacos StatefulSet 服务发现
kubectl exec -it nacos-0 -- nslookup nacos-headless

3. 查看集群状态

通过 API 查询集群节点列表,确认所有节点均显示健康状态。

kubectl exec -it nacos-0 -- curl http://localhost:8848/nacos/v1/ns/cluster/nodes

4. 常见错误排查

  • Pod 启动失败:检查日志 kubectl logs nacos-0,若报 DB 连接错误,确认 Secret 密码正确且网络可达。
  • PVC Pending:检查集群是否有可用的 StorageClass,kubectl get storageclass
  • 集群节点不全:确认 NACOS_SERVERS 环境变量中的节点列表与当前 replicas 数量一致。

5. 扩缩容注意事项

StatefulSet 支持扩缩容,但 Nacos 集群模式下的 NACOS_SERVERS 环境变量是静态配置的。

  • 扩容:若将 replicas 从 3 改为 5,必须同步更新 StatefulSet 中的 NACOS_SERVERS 列表,增加新节点域名,否则新节点无法加入集群。
  • 缩容:直接减少 replicas 通常安全,但建议先在控制台确认节点下线。
  • 建议:生产环境若需频繁弹性伸缩,建议调研 Nacos K8s Plugin 或基于域名发现的启动脚本方案。

参考文档