在 Kubernetes 中部署 Nacos 集群实现高可用,核心在于使用 StatefulSet 保证节点身份稳定,外接 MySQL 持久化配置,并正确配置 K8s 服务发现端口。
先说结论:生产环境建议使用至少 3 个节点组建集群,必须外接数据库,且需注意 Nacos 2.x 版本的端口变化。
- 适合:对服务发现可靠性有要求的生产环境
- 先准备:独立 MySQL 实例、持久化存储类(StorageClass)
- 验收:检查集群节点状态、注册服务心跳及配置读写
前置准备
1. 数据库初始化:下载 Nacos 官方提供的 MySQL 脚本 nacos-mysql.sql 并在独立 MySQL 实例中执行,创建数据库 nacos_config 及相关表。
2. 存储类检查:确认集群存在可用的 StorageClass,执行 kubectl get sc 查看。若无,需先配置持久化存储。
核心资源配置
以下 YAML 基于 Nacos 2.x 版本设计,包含 ConfigMap、Service 和 StatefulSet。请根据实际环境修改数据库密码及存储类名称。
1. 配置 ConfigMap
虽然支持动态发现,但建议保留基础配置。注意:在 K8s 中更推荐通过环境变量 NACOS_SERVERS 指定节点列表,避免手动维护文件。
apiVersion: v1
kind: ConfigMap
metadata:
name: nacos-config
data:
cluster.conf: |
nacos-0.nacos-headless.default.svc.cluster.local:8848
nacos-1.nacos-headless.default.svc.cluster.local:8848
nacos-2.nacos-headless.default.svc.cluster.local:8848
application.properties: |
db.num=1
db.url.0=jdbc:mysql://mysql-host:3306/nacos_config?characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true
db.user=nacos
db.password=nacos
2. 创建 Service
需要两个 Service:一个 Headless Service 用于 StatefulSet 内部域名解析,一个 ClusterIP 用于外部访问。
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: v1
kind: Service
metadata:
name: nacos-client
spec:
type: ClusterIP
selector:
app: nacos
ports:
- name: server
port: 8848
targetPort: 8848
- name: client-rpc
port: 9848
targetPort: 9848
3. 部署 StatefulSet
重点配置环境变量、资源限制及持久化存储。注意 Nacos 2.x 需暴露 9848 和 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:2.2.0
resources:
requests:
memory: "1Gi"
cpu: "500m"
limits:
memory: "2Gi"
cpu: "1000m"
ports:
- containerPort: 8848
name: server
- containerPort: 9848
name: client-rpc
- containerPort: 9849
name: raft-rpc
env:
- name: MODE
value: "cluster"
- name: NACOS_SERVERS
value: "nacos-0.nacos-headless.default.svc.cluster.local:8848 nacos-1.nacos-headless.default.svc.cluster.local:8848 nacos-2.nacos-headless.default.svc.cluster.local:8848"
- name: MYSQL_SERVICE_HOST
value: "mysql-host"
- name: MYSQL_SERVICE_DB_NAME
value: "nacos_config"
- name: MYSQL_SERVICE_USER
value: "nacos"
- name: MYSQL_SERVICE_PASSWORD
value: "nacos"
- name: SPRING_DATASOURCE_PLATFORM
value: "mysql"
volumeMounts:
- name: data
mountPath: /home/nacos/data
- name: config
mountPath: /home/nacos/conf/cluster.conf
subPath: cluster.conf
volumes:
- name: config
configMap:
name: nacos-config
volumeClaimTemplates:
- metadata:
name: data
spec:
accessModes: [ "ReadWriteOnce" ]
storageClassName: "your-storage-class"
resources:
requests:
storage: 10Gi
验证部署结果
应用配置后,执行以下命令验证:
# 1. 检查 Pod 状态,确保 3 个节点均为 Running
kubectl get pods -l app=nacos
# 2. 查看日志确认无启动报错
kubectl logs -f nacos-0
# 3. 检查集群健康状态 (替换为实际 Service IP)
curl http://<nacos-service-ip>:8848/nacos/actuator/health
# 4. 查看集群节点列表
curl http://<nacos-service-ip>:8848/nacos/v1/ns/operator/cluster/nodes
常见故障排查
- 客户端连接失败:Nacos 2.x 使用 gRPC 通信,若防火墙或 SecurityGroup 未开放 9848 和 9849 端口,SDK 会报错。请确保 Service 中映射了这两个端口。
- 节点状态异常:检查
NACOS_SERVERS环境变量中的域名是否能在 Pod 内解析。可使用kubectl exec -it nacos-0 -- ping nacos-1.nacos-headless测试连通性。 - 数据库连接错误:确认 MySQL 允许远程连接,且账号密码正确。检查 Pod 日志中是否有
Communications link failure。 - PVC Pending:若 Pod 无法启动,检查
kubectl get pvc。通常是因为storageClassName填写错误或不匹配集群现有存储类。
参考来源
- Nacos 官方文档 - 集群部署指南:https://nacos.io/zh-cn/docs/cluster-setup-1.4.0.html
- Nacos GitHub - K8s 部署示例:https://github.com/alibaba/nacos/tree/develop/deployment/k8s
- Nacos 官方文档 - 2.0 兼容性说明:https://nacos.io/zh-cn/docs/2.0.0-compatibility.html