Nacos

Nacos 注册中心与配置中心 Nacos 提供服务发现、健康管理和动态配置。服务发现中的 namespace、group、service name 与配置中心的 namespace、group、Data ID 是不同维度,客户端和服务端必须使用匹配的值。 Nacos 2.x 引入 gRPC:默认主

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 兼容矩阵、数据库变更和回滚条件,并在隔离环境验证恢复。

评论