Nacos
注册中心与配置中心
Nacos 提供服务发现、健康管理和动态配置。服务发现中的 namespace、group、service name 与配置中心的 namespace、group、Data ID 是不同维度,客户端和服务端必须使用匹配的值。
Nacos 2.x 引入 gRPC:默认主端口 8848,客户端 gRPC 为 9848,服务端 gRPC 为 9849,部分集群通信使用 7848。Nacos 3.x 的控制台、鉴权和部署方式有变化,下面固定采用 2.4.3,不能直接替换为 3.x 镜像沿用全部配置。新部署应依据兼容矩阵选择仍受支持的补丁版本。
临时实例通常由客户端心跳维护,持久实例的存储及健康检查机制不同;集群并非所有数据都只存 MySQL。外部数据库故障、节点间网络故障和客户端连接故障应分别排查。
部署前提
Kubernetes 至少有 3 个可调度节点、默认 StorageClass,以及可达的独立 MySQL。示例 namespace 为 middleware,数据库地址为 mysql.example.internal。MySQL 生产环境自行实现高可用、TLS、备份与恢复。
数据库表结构必须来自与服务端相同版本的发行包,不能复制旧版本建表 SQL 覆盖现有数据库。新库初始化示例:
curl -fL -o mysql-schema.sql \
https://raw.githubusercontent.com/alibaba/nacos/2.4.3/distribution/conf/mysql-schema.sql
mysql -h mysql.example.internal -u root -p
在 MySQL 中创建新库和专用账号;10.0.% 代表实际 Nacos 来源网段,按实际地址进一步收紧:
CREATE DATABASE nacos CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE USER 'nacos'@'10.0.%' IDENTIFIED BY 'REPLACE_WITH_DB_PASSWORD';
GRANT SELECT, INSERT, UPDATE, DELETE ON nacos.* TO 'nacos'@'10.0.%';
使用具备建表权限的初始化账号导入,运行账号只保留所需 DML 权限:
mysql -h mysql.example.internal -u root -p nacos < mysql-schema.sql
升级已有库先备份,再按版本升级 SQL 操作,不要重新执行全量初始化脚本。
创建 namespace 与 Secret
kubectl create namespace middleware
保存为 nacos-secret.yaml,替换全部占位符后应用;本文件含明文敏感配置,不应提交仓库:
apiVersion: v1
kind: Secret
metadata:
name: nacos-secret
namespace: middleware
type: Opaque
stringData:
mysql-user: nacos
mysql-password: REPLACE_WITH_DB_PASSWORD
auth-token: REPLACE_WITH_BASE64_ENCODED_RANDOM_KEY
identity-key: REPLACE_WITH_IDENTITY_KEY
identity-value: REPLACE_WITH_RANDOM_IDENTITY_VALUE
Token 密钥要求为满足 Nacos 要求的 Base64 编码密钥,底层随机值至少 32 字节,三节点保持一致:
openssl rand -base64 32
kubectl apply -f nacos-secret.yaml
Kubernetes Secret 的 Base64 不是加密,需结合 RBAC、etcd 静态加密或外部 Secret 管理器,并限制文件和集群 API 访问。
三节点 StatefulSet
保存为 nacos.yaml。Headless Service 用于节点互访;客户端 Service 只提供 8848 和 9848,不把内部通信端口对外暴露。
apiVersion: v1
kind: Service
metadata:
name: nacos-headless
namespace: middleware
spec:
clusterIP: None
publishNotReadyAddresses: true
selector:
app: nacos
ports:
- name: http
port: 8848
- name: client-grpc
port: 9848
- name: server-grpc
port: 9849
- name: raft
port: 7848
---
apiVersion: v1
kind: Service
metadata:
name: nacos
namespace: middleware
spec:
selector:
app: nacos
ports:
- name: http
port: 8848
- name: client-grpc
port: 9848
---
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
name: nacos
namespace: middleware
spec:
maxUnavailable: 1
selector:
matchLabels:
app: nacos
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: nacos
namespace: middleware
spec:
serviceName: nacos-headless
replicas: 3
podManagementPolicy: Parallel
selector:
matchLabels:
app: nacos
template:
metadata:
labels:
app: nacos
spec:
terminationGracePeriodSeconds: 60
affinity:
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchLabels:
app: nacos
topologyKey: kubernetes.io/hostname
containers:
- name: nacos
image: nacos/nacos-server:v2.4.3
ports:
- name: http
containerPort: 8848
- name: client-grpc
containerPort: 9848
- name: server-grpc
containerPort: 9849
- name: raft
containerPort: 7848
env:
- name: MODE
value: cluster
- name: PREFER_HOST_MODE
value: hostname
- name: NACOS_SERVERS
value: "nacos-0.nacos-headless.middleware.svc.cluster.local:8848 nacos-1.nacos-headless.middleware.svc.cluster.local:8848 nacos-2.nacos-headless.middleware.svc.cluster.local:8848"
- name: SPRING_DATASOURCE_PLATFORM
value: mysql
- name: MYSQL_SERVICE_HOST
value: mysql.example.internal
- name: MYSQL_SERVICE_PORT
value: "3306"
- name: MYSQL_SERVICE_DB_NAME
value: nacos
- name: MYSQL_SERVICE_USER
valueFrom:
secretKeyRef:
name: nacos-secret
key: mysql-user
- name: MYSQL_SERVICE_PASSWORD
valueFrom:
secretKeyRef:
name: nacos-secret
key: mysql-password
- name: NACOS_AUTH_ENABLE
value: "true"
- name: NACOS_AUTH_TOKEN
valueFrom:
secretKeyRef:
name: nacos-secret
key: auth-token
- name: NACOS_AUTH_IDENTITY_KEY
valueFrom:
secretKeyRef:
name: nacos-secret
key: identity-key
- name: NACOS_AUTH_IDENTITY_VALUE
valueFrom:
secretKeyRef:
name: nacos-secret
key: identity-value
- name: JVM_XMS
value: 512m
- name: JVM_XMX
value: 1g
resources:
requests:
cpu: 500m
memory: 1Gi
limits:
memory: 2Gi
startupProbe:
httpGet:
path: /nacos/v1/console/health/readiness
port: http
periodSeconds: 10
failureThreshold: 30
readinessProbe:
httpGet:
path: /nacos/v1/console/health/readiness
port: http
periodSeconds: 10
timeoutSeconds: 5
volumeMounts:
- name: data
mountPath: /home/nacos/data
- name: data
mountPath: /home/nacos/logs
subPath: logs
volumeClaimTemplates:
- metadata:
name: data
spec:
accessModes: [ReadWriteOnce]
resources:
requests:
storage: 10Gi
kubectl apply --dry-run=server -f nacos.yaml
kubectl apply -f nacos.yaml
kubectl -n middleware rollout status statefulset/nacos --timeout=10m
kubectl -n middleware get pods,pvc,svc
kubectl -n middleware logs nacos-0 --tail=100
kubectl -n middleware port-forward service/nacos 8848:8848
浏览器本机访问 http://127.0.0.1:8848/nacos/。Nacos 2.4.x 开启鉴权后需按控制台或官方管理员初始化流程设置管理员密码,不能假设存在可用的默认账号密码。
客户端接入与验证
集群内客户端配置服务地址 nacos.middleware.svc.cluster.local:8848,并配置服务端对应的 namespace ID、group、认证用户和权限。Nacos 2.x 客户端会连接偏移后的 gRPC 端口,验证 8848 和 9848 均可达;仅代理 8848 的普通 HTTP Ingress 不能完整承载客户端通信。
验收至少覆盖:创建并读取配置、发布配置后客户端动态更新、注册实例后消费者发现、单节点重启和客户端重连。动态刷新依赖应用所用框架和配置方式,不能把服务端发布成功等同于进程内所有配置已生效。
安全与备份
- 业务用户按 namespace 和资源授权,管理员账号只用于管理;认证接口、控制台和 OpenAPI 限制来源。
- 三节点共享 Token 密钥与服务器身份配置,轮换时按官方步骤操作,避免混用新旧密钥造成内部请求失败。
- MySQL 连接、客户端与服务端通信按目标版本支持情况启用 TLS;HTTP 网关 TLS 不代表内部 gRPC 和数据库链路已加密。
- 使用 NetworkPolicy 限制客户端到 8848/9848,节点间到 7848/9849,以及服务端到 MySQL 的访问。
- 备份数据库、配置导出、部署清单、受保护的凭据及必要持久化数据;不同类型数据的权威存储不同,不能认为只复制 PVC 或只导出配置就覆盖全部状态。
常见故障
| 现象 | 检查方向 |
|---|---|
| 无法启动 / No DataSource | 数据库 DNS、端口、账号、schema 版本及连接池日志 |
| 节点 Pending | 默认 StorageClass、PVC、节点数量与反亲和性 |
| 控制台正常但客户端失败 | SDK 版本、9848、代理端口映射、namespace 和认证 |
| 集群节点互相拒绝 | Token 密钥、identity 配置、时间、7848/9849 和 DNS |
| 配置发布后应用没变化 | Data ID/group、namespace ID、监听与刷新机制、应用本地缓存 |
监控节点健康、JVM/GC、请求延迟、注册实例数、配置推送、数据库连接和 Raft 异常。升级前核对服务端/SDK 兼容矩阵、数据库变更和回滚条件,并在隔离环境验证恢复。
评论