本文档描述了在 Kubernetes 环境下部署 Nacos 3.2.1 高可用集群的最佳实践。集群采用 StatefulSet + Headless Service 架构,并已解决 JVM OOM、端口冲突及跨节点调度等常见问题。
一、 部署前置准备
1. 数据库初始化
Nacos 3.x 在集群模式下不支持自动建表。在部署应用前,必须手动初始化 MySQL 数据库。
- 在你的 MySQL 服务器上创建数据库:
CREATE DATABASE nacos DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
- 获取 Nacos 3.2.1 官方 SQL 脚本,并在上述库中完整执行。
kubectl exec -it nacos-0 -n atai-ops -- cat /home/nacos/conf/mysql-schema.sql > nacos-3.2.1-init.sql
- 确保配置给 Nacos 容器的数据库账号拥有读写权限。
2. K8s 节点要求
为了保证真正的 Raft 高可用,当前 YAML 配置了硬性 Pod 反亲和性(Anti-Affinity)。
- 要求: Kubernetes 集群中必须至少有 3 个 可用的 Worker 节点,否则 Pod 会因为无法满足分散调度条件而处于
Pending状态。 - (如果测试环境节点不足,请将下方 YAML 中的
requiredDuringSchedulingIgnoredDuringExecution修改为preferredDuringSchedulingIgnoredDuringExecution)。
二、 核心部署脚本
将以下内容保存为 nacos-cluster.yaml。
注意: 部署前,请将
ConfigMap中的<your-mysql-host>、<your-db-user>和<your-db-password>替换为真实的数据库连接信息。
# 1. 命名空间
apiVersion: v1
kind: Namespace
metadata:
name: atai-ops
---
# 2. ConfigMap (Nacos 核心配置)
apiVersion: v1
kind: ConfigMap
metadata:
name: nacos-cm
namespace: atai-ops
data:
application.properties: |
# UI 控制台上下文路径 (注意: Nacos 3.x 千万不要在这里配置 server.port,会引发内部 Tomcat 端口冲突)
server.servlet.contextPath=/nacos
# 鉴权配置
nacos.core.auth.enabled=true
nacos.core.auth.server.identity.key=serverIdKey
nacos.core.auth.server.identity.value=inner-server-node-2024-secure-cluster-id
nacos.core.auth.plugin.nacos.token.secret.key=R2s3I21QOXhMMiR2TjVxVzhqUjQhVDZ5QjNjRTBmSDEza1M5dU8yJA==
# 外部 MySQL 数据源配置
spring.sql.init.platform=mysql
db.num=1
db.url.0=jdbc:mysql://<your-mysql-host>:3306/nacos?characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true&useUnicode=true&useSSL=false&serverTimezone=UTC
db.user.0=<your-db-user>
db.password.0=<your-db-password>
# 开启 Prometheus 监控指标
management.endpoints.web.exposure.include=*
---
# 3. Headless Service (集群节点内部通信与自动发现)
apiVersion: v1
kind: Service
metadata:
name: nacos-headless
namespace: atai-ops
labels:
app: nacos
spec:
type: ClusterIP
clusterIP: None
ports:
- port: 8848
name: client
- port: 9848
name: client-rpc
- port: 9849
name: raft-rpc
selector:
app: nacos
---
# 4. NodePort Service (对外暴露 API 与 UI 控制台)
apiVersion: v1
kind: Service
metadata:
name: nacos-service
namespace: atai-ops
labels:
app: nacos
spec:
type: NodePort
selector:
app: nacos
ports:
- name: client
port: 8848
targetPort: 8848
- name: client-rpc
port: 9848
targetPort: 9848
- name: console
port: 8080
targetPort: 8080
---
# 5. StatefulSet (Nacos 3 节点集群控制器)
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: nacos
namespace: atai-ops
spec:
serviceName: nacos-headless
replicas: 3
selector:
matchLabels:
app: nacos
template:
metadata:
labels:
app: nacos
spec:
# Pod 反亲和性:强制 3 个节点调度到不同的宿主机,保证物理高可用
affinity:
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: app
operator: In
values:
- nacos
topologyKey: "kubernetes.io/hostname"
containers:
- name: nacos
image: nacos/nacos-server:v3.2.1
imagePullPolicy: IfNotPresent
# 资源限制:Limits 内存必须大于 JVM 的 Xmx 至少 50%,防止被 K8s OOMKill
resources:
requests:
cpu: "500m"
memory: "1Gi"
limits:
cpu: "2"
memory: "2Gi"
ports:
- containerPort: 8848
name: client
- containerPort: 9848
name: client-rpc
- containerPort: 9849
name: raft-rpc
- containerPort: 8080
name: console
env:
- name: MODE
value: "cluster"
# 利用 K8s DNS 域名配置集群节点,镜像启动时自动渲染到 cluster.conf
- name: NACOS_SERVERS
value: "nacos-0.nacos-headless.atai-ops.svc.cluster.local:8848 nacos-1.nacos-headless.atai-ops.svc.cluster.local:8848 nacos-2.nacos-headless.atai-ops.svc.cluster.local:8848"
# 安全鉴权环境变量 (必须在此处注入,否则 Docker 启动脚本会校验失败(exit 255))
- name: NACOS_AUTH_TOKEN
value: "R2s3I21QOXhMMiR2TjVxVzhqUjQhVDZ5QjNjRTBmSDEza1M5dU8yJA=="
- name: NACOS_AUTH_IDENTITY_KEY
value: "serverIdKey"
- name: NACOS_AUTH_IDENTITY_VALUE
value: "inner-server-node-2024-secure-cluster-id"
# JVM 内存参数配置 (保守配置,为容器堆外内存留出空间)
- name: JVM_XMS
value: "512m"
- name: JVM_XMX
value: "512m"
- name: JVM_XMN
value: "256m"
volumeMounts:
- name: config-volume
mountPath: /home/nacos/conf/application.properties
subPath: application.properties
volumes:
- name: config-volume
configMap:
name: nacos-cm
三、 部署与验证
- 执行部署命令:
kubectl apply -f nacos-cluster.yaml
- 观察 Pod 启动状态:
kubectl get pods -n atai-ops -w
等待 nacos-0、nacos-1、nacos-2 的状态全部变为 Running。
3. 获取对外暴露的端口:
kubectl get svc nacos-service -n atai-ops
找到 8080 对应的 NodePort 端口(例如 32055)。
4. 访问控制台
在浏览器中输入:
http://<任意K8s节点IP>:<映射的8080_NodePort>/nacos
登录成功后,进入 集群管理 -> 节点列表,确认 3 个节点均处于 UP 状态,即代表集群部署成功!
评论区