[nacos] 基於Docker安裝Nacos

0 序

  • 環境信息
  • centos : 7.9
  • docker : 25.0.4
  • mysql : 5.7.x
  • nacos-server : 2.1.1 (部署模式: nacos standalone / 單機mysql5.7)
    注:調研了多個版本後的結論————不同nacos-server版本之間的差異較大,容器內的目錄結構、腳本等變化較大。

1 安裝步驟(nacos/nacos-server鏡像方式)

Step1 拉取鏡像

docker pull nacos/nacos-server:v2.1.1

docker images

Step2 創建、並運行 Nacos Server Demo 容器

  • 創建、並運行 Nacos Demo 容器
docker run --name demo-nacos-server \
-p 8848:8848 \
-p 9848:9848 \
-p 9849:9849 \
--privileged=true \
--restart=always \
-e JVM_XMS=256m \
-e JVM_XMX=256m \
-e MODE=standalone \
-e PREFER_HOST_MODE=hostname \
-d nacos/nacos-server:v2.1.1

docker ps -a

  • 訪問 Nacos Server Demo 容器

http://127.0.0.1:8848/nacos/index.html
賬號 / 密碼 【默認】 : nacos / nacos

Step3 在宿主機中創建持久化文件目錄(日誌/核心配置)

  • 在宿主機中創建日誌、配置目錄
mkdir -p /data/nacos/logs
 
mkdir -p /data/nacos/conf
  • 從Demo容器中拷貝默認配置到宿主機中
docker exec -it demo-nacos-server sh -c "ls -la /home/nacos/conf"

docker cp demo-nacos-server:/home/nacos/conf/application.properties /data/nacos/conf/

# 拷貝 mysql 8 的 ddl sql : schema.sql (本教程中,實際不會使用)
docker cp demo-nacos-server:/home/nacos/conf/schema.sql /data/nacos/conf/
# nacos-server : 2.1.1 的docker鏡像中漏掉了 mysql 5.7 的 ddl sql : nacos-mysql | 詳情參加: https://github.com/alibaba/nacos/releases/tag/2.1.1 的 release 包

# 拷貝 ipv6的補丁 ddl sql : 1.4.0-ipv6_support-update.sql
docker cp demo-nacos-server:/home/nacos/conf/1.4.0-ipv6_support-update.sql /data/nacos/conf/

ls -la /data/nacos/conf/

nacos-server-2.1.1.zip 中存在 mysql 5.7 的 ddl 腳本

Step4 MySQL(5.7)數據庫初始化

創建數據庫

CREATE DATABASE nacos DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

創建用戶

CREATE USER nacos@'%';
ALTER USER nacos@'%' IDENTIFIED BY 'nacosPassword';
GRANT ALL PRIVILEGES ON nacos.* TO nacos@'%';
FLUSH PRIVILEGES;

use nacos; -- 使用 nacos 數據庫

創建表

  • 執行 : nacos-mysql.sql

腳本內容來源於 : https://github.com/alibaba/nacos/releases/tag/2.1.1nacos-server-2.1.1.zip 包的conf目錄的nacos-mysql.sql腳本文件
或參見:https://github.com/alibaba/nacos/blob/2.1.1/distribution/conf/nacos-mysql.sql

/*
 * Copyright 1999-2018 Alibaba Group Holding Ltd.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/******************************************/
/*   數據庫全名 = nacos_config   */
/*   表名稱 = config_info   */
/******************************************/
CREATE TABLE `config_info` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id',
  `data_id` varchar(255) NOT NULL COMMENT 'data_id',
  `group_id` varchar(255) DEFAULT NULL,
  `content` longtext NOT NULL COMMENT 'content',
  `md5` varchar(32) DEFAULT NULL COMMENT 'md5',
  `gmt_create` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '創建時間',
  `gmt_modified` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '修改時間',
  `src_user` text COMMENT 'source user',
  `src_ip` varchar(50) DEFAULT NULL COMMENT 'source ip',
  `app_name` varchar(128) DEFAULT NULL,
  `tenant_id` varchar(128) DEFAULT '' COMMENT '租戶字段',
  `c_desc` varchar(256) DEFAULT NULL,
  `c_use` varchar(64) DEFAULT NULL,
  `effect` varchar(64) DEFAULT NULL,
  `type` varchar(64) DEFAULT NULL,
  `c_schema` text,
  `encrypted_data_key` text NOT NULL COMMENT '祕鑰',
  PRIMARY KEY (`id`),
  UNIQUE KEY `uk_configinfo_datagrouptenant` (`data_id`,`group_id`,`tenant_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='config_info';

/******************************************/
/*   數據庫全名 = nacos_config   */
/*   表名稱 = config_info_aggr   */
/******************************************/
CREATE TABLE `config_info_aggr` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id',
  `data_id` varchar(255) NOT NULL COMMENT 'data_id',
  `group_id` varchar(255) NOT NULL COMMENT 'group_id',
  `datum_id` varchar(255) NOT NULL COMMENT 'datum_id',
  `content` longtext NOT NULL COMMENT '內容',
  `gmt_modified` datetime NOT NULL COMMENT '修改時間',
  `app_name` varchar(128) DEFAULT NULL,
  `tenant_id` varchar(128) DEFAULT '' COMMENT '租戶字段',
  PRIMARY KEY (`id`),
  UNIQUE KEY `uk_configinfoaggr_datagrouptenantdatum` (`data_id`,`group_id`,`tenant_id`,`datum_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='增加租戶字段';


/******************************************/
/*   數據庫全名 = nacos_config   */
/*   表名稱 = config_info_beta   */
/******************************************/
CREATE TABLE `config_info_beta` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id',
  `data_id` varchar(255) NOT NULL COMMENT 'data_id',
  `group_id` varchar(128) NOT NULL COMMENT 'group_id',
  `app_name` varchar(128) DEFAULT NULL COMMENT 'app_name',
  `content` longtext NOT NULL COMMENT 'content',
  `beta_ips` varchar(1024) DEFAULT NULL COMMENT 'betaIps',
  `md5` varchar(32) DEFAULT NULL COMMENT 'md5',
  `gmt_create` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '創建時間',
  `gmt_modified` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '修改時間',
  `src_user` text COMMENT 'source user',
  `src_ip` varchar(50) DEFAULT NULL COMMENT 'source ip',
  `tenant_id` varchar(128) DEFAULT '' COMMENT '租戶字段',
  `encrypted_data_key` text NOT NULL COMMENT '祕鑰',
  PRIMARY KEY (`id`),
  UNIQUE KEY `uk_configinfobeta_datagrouptenant` (`data_id`,`group_id`,`tenant_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='config_info_beta';

/******************************************/
/*   數據庫全名 = nacos_config   */
/*   表名稱 = config_info_tag   */
/******************************************/
CREATE TABLE `config_info_tag` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id',
  `data_id` varchar(255) NOT NULL COMMENT 'data_id',
  `group_id` varchar(128) NOT NULL COMMENT 'group_id',
  `tenant_id` varchar(128) DEFAULT '' COMMENT 'tenant_id',
  `tag_id` varchar(128) NOT NULL COMMENT 'tag_id',
  `app_name` varchar(128) DEFAULT NULL COMMENT 'app_name',
  `content` longtext NOT NULL COMMENT 'content',
  `md5` varchar(32) DEFAULT NULL COMMENT 'md5',
  `gmt_create` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '創建時間',
  `gmt_modified` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '修改時間',
  `src_user` text COMMENT 'source user',
  `src_ip` varchar(50) DEFAULT NULL COMMENT 'source ip',
  PRIMARY KEY (`id`),
  UNIQUE KEY `uk_configinfotag_datagrouptenanttag` (`data_id`,`group_id`,`tenant_id`,`tag_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='config_info_tag';

/******************************************/
/*   數據庫全名 = nacos_config   */
/*   表名稱 = config_tags_relation   */
/******************************************/
CREATE TABLE `config_tags_relation` (
  `id` bigint(20) NOT NULL COMMENT 'id',
  `tag_name` varchar(128) NOT NULL COMMENT 'tag_name',
  `tag_type` varchar(64) DEFAULT NULL COMMENT 'tag_type',
  `data_id` varchar(255) NOT NULL COMMENT 'data_id',
  `group_id` varchar(128) NOT NULL COMMENT 'group_id',
  `tenant_id` varchar(128) DEFAULT '' COMMENT 'tenant_id',
  `nid` bigint(20) NOT NULL AUTO_INCREMENT,
  PRIMARY KEY (`nid`),
  UNIQUE KEY `uk_configtagrelation_configidtag` (`id`,`tag_name`,`tag_type`),
  KEY `idx_tenant_id` (`tenant_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='config_tag_relation';

/******************************************/
/*   數據庫全名 = nacos_config   */
/*   表名稱 = group_capacity   */
/******************************************/
CREATE TABLE `group_capacity` (
  `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主鍵ID',
  `group_id` varchar(128) NOT NULL DEFAULT '' COMMENT 'Group ID,空字符表示整個集羣',
  `quota` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '配額,0表示使用默認值',
  `usage` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '使用量',
  `max_size` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '單個配置大小上限,單位爲字節,0表示使用默認值',
  `max_aggr_count` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '聚合子配置最大個數,,0表示使用默認值',
  `max_aggr_size` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '單個聚合數據的子配置大小上限,單位爲字節,0表示使用默認值',
  `max_history_count` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '最大變更歷史數量',
  `gmt_create` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '創建時間',
  `gmt_modified` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '修改時間',
  PRIMARY KEY (`id`),
  UNIQUE KEY `uk_group_id` (`group_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='集羣、各Group容量信息表';

/******************************************/
/*   數據庫全名 = nacos_config   */
/*   表名稱 = his_config_info   */
/******************************************/
CREATE TABLE `his_config_info` (
  `id` bigint(20) unsigned NOT NULL,
  `nid` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
  `data_id` varchar(255) NOT NULL,
  `group_id` varchar(128) NOT NULL,
  `app_name` varchar(128) DEFAULT NULL COMMENT 'app_name',
  `content` longtext NOT NULL,
  `md5` varchar(32) DEFAULT NULL,
  `gmt_create` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
  `gmt_modified` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
  `src_user` text,
  `src_ip` varchar(50) DEFAULT NULL,
  `op_type` char(10) DEFAULT NULL,
  `tenant_id` varchar(128) DEFAULT '' COMMENT '租戶字段',
  `encrypted_data_key` text NOT NULL COMMENT '祕鑰',
  PRIMARY KEY (`nid`),
  KEY `idx_gmt_create` (`gmt_create`),
  KEY `idx_gmt_modified` (`gmt_modified`),
  KEY `idx_did` (`data_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='多租戶改造';


/******************************************/
/*   數據庫全名 = nacos_config   */
/*   表名稱 = tenant_capacity   */
/******************************************/
CREATE TABLE `tenant_capacity` (
  `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主鍵ID',
  `tenant_id` varchar(128) NOT NULL DEFAULT '' COMMENT 'Tenant ID',
  `quota` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '配額,0表示使用默認值',
  `usage` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '使用量',
  `max_size` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '單個配置大小上限,單位爲字節,0表示使用默認值',
  `max_aggr_count` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '聚合子配置最大個數',
  `max_aggr_size` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '單個聚合數據的子配置大小上限,單位爲字節,0表示使用默認值',
  `max_history_count` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '最大變更歷史數量',
  `gmt_create` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '創建時間',
  `gmt_modified` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '修改時間',
  PRIMARY KEY (`id`),
  UNIQUE KEY `uk_tenant_id` (`tenant_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='租戶容量信息表';


CREATE TABLE `tenant_info` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id',
  `kp` varchar(128) NOT NULL COMMENT 'kp',
  `tenant_id` varchar(128) default '' COMMENT 'tenant_id',
  `tenant_name` varchar(128) default '' COMMENT 'tenant_name',
  `tenant_desc` varchar(256) DEFAULT NULL COMMENT 'tenant_desc',
  `create_source` varchar(32) DEFAULT NULL COMMENT 'create_source',
  `gmt_create` bigint(20) NOT NULL COMMENT '創建時間',
  `gmt_modified` bigint(20) NOT NULL COMMENT '修改時間',
  PRIMARY KEY (`id`),
  UNIQUE KEY `uk_tenant_info_kptenantid` (`kp`,`tenant_id`),
  KEY `idx_tenant_id` (`tenant_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='tenant_info';

CREATE TABLE `users` (
	`username` varchar(50) NOT NULL PRIMARY KEY,
	`password` varchar(500) NOT NULL,
	`enabled` boolean NOT NULL
);

CREATE TABLE `roles` (
	`username` varchar(50) NOT NULL,
	`role` varchar(50) NOT NULL,
	UNIQUE INDEX `idx_user_role` (`username` ASC, `role` ASC) USING BTREE
);

CREATE TABLE `permissions` (
    `role` varchar(50) NOT NULL,
    `resource` varchar(255) NOT NULL,
    `action` varchar(8) NOT NULL,
    UNIQUE INDEX `uk_role_permission` (`role`,`resource`,`action`) USING BTREE
);

INSERT INTO users (username, password, enabled) VALUES ('nacos', '$2a$10$EuWPZHzz32dJN7jexM34MOeYirDdFAZm2kuWj7VEOJhhZkDrxfvUu', TRUE);

INSERT INTO roles (username, role) VALUES ('nacos', 'ROLE_ADMIN');

  • 1.4.0-ipv6_support-update.sql
ALTER TABLE `config_info_tag`
MODIFY COLUMN `src_ip` varchar(50) CHARACTER SET utf8 COLLATE utf8_bin NULL DEFAULT NULL COMMENT 'source ip' AFTER `src_user`;

ALTER TABLE `his_config_info`
MODIFY COLUMN `src_ip` varchar(50) CHARACTER SET utf8 COLLATE utf8_bin NULL DEFAULT NULL AFTER `src_user`;

ALTER TABLE `config_info`
MODIFY COLUMN `src_ip` varchar(50) CHARACTER SET utf8 COLLATE utf8_bin NULL DEFAULT NULL COMMENT 'source ip' AFTER `src_user`;

ALTER TABLE `config_info_beta`
MODIFY COLUMN `src_ip` varchar(50) CHARACTER SET utf8 COLLATE utf8_bin NULL DEFAULT NULL COMMENT 'source ip' AFTER `src_user`;

Step5 修改配置文件(application.properties)

  • vi /data/nacos/conf/application.properties

修改如下配置項

...

#spring.datasource.platform=${SPRING_DATASOURCE_PLATFORM:""}
spring.datasource.platform=${SPRING_DATASOURCE_PLATFORM:"mysql"}

...

db.num=${MYSQL_DATABASE_NUM:1}
# db.url.0=jdbc:mysql://127.0.0.1:3306/nacos?characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true&useSSL=false
db.url.0=jdbc:mysql://${MYSQL_SERVICE_HOST}:${MYSQL_SERVICE_PORT:3306}/${MYSQL_SERVICE_DB_NAME:nacos}?${MYSQL_SERVICE_DB_PARAM:characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&auto
Reconnect=true&useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true}
# [註釋此行] db.url.1=jdbc:mysql://${MYSQL_SERVICE_HOST}:${MYSQL_SERVICE_PORT:3306}/${MYSQL_SERVICE_DB_NAME}?${MYSQL_SERVICE_DB_PARAM:characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&aut
oReconnect=true&useSSL=false}
db.user=${MYSQL_SERVICE_USER}
db.password=${MYSQL_SERVICE_PASSWORD}

...

Step6 重建正式的 Nacos Server 容器

  • 刪除正在運行的 Nacos Demo 容器,重新用命令創建啓動
docker stop demo-nacos-server

docker rm demo-nacos-server
  • 啓動 正式的 Nacos Server 容器
docker run --name nacos-server \
-p 18848:8848 \
-p 19848:9848 \
-p 19849:9849 \
--privileged=true \
--restart=always \
-e MYSQL_SERVICE_HOST="172.17.0.1" \
-e "MYSQL_SERVICE_PORT=33060" \
-e MYSQL_SERVICE_DB_NAME=nacos \
-e MYSQL_SERVICE_USER=nacos \
-e MYSQL_SERVICE_PASSWORD="123456" \
-e JVM_XMS=256m \
-e JVM_XMX=256m \
-e MODE=standalone \
-e PREFER_HOST_MODE=hostname \
-v /data/nacos/logs:/home/nacos/logs \
-v /data/nacos/conf/application.properties:/home/nacos/conf/application.properties \
-d nacos/nacos-server:v2.1.1
  • 172.17.0.1 : 在Linux系統中,可以使用特殊的IP地址172.17.0.1來代表宿主機,這個IP地址通常用於Docker默認的網絡橋接模式中。

注:docker 容器內的 127.0.0.1 ≠ 宿主機中的 127.0.0.1

  • 查看 Nacos Server 容器
docker ps -a
docker logs nacos-server

ls -la /data/nacos/logs

docker exec -it nacos-server sh -c "ls -la /home/nacos/conf/application.properties"
docker exec -it nacos-server sh -c "cat /home/nacos/conf/application.properties"

# ↓ 此命令無效,需進入容器內部才能查看到真實情況
# docker exec -it nacos-server sh -c "echo $MYSQL_SERVICE_HOST"

docker exec -it nacos-server bash
> echo $MYSQL_SERVICE_HOST
> exit

# 宿主機中測驗:
curl http://127.0.0.1:18848/nacos
  • 測驗:調用Nacos Web API
# 服務註冊
curl -X POST 'http://xx.yy.zz.ff:18848/nacos/v1/ns/instance?serviceName=nacos.naming.serviceName&ip=20.18.7.10&port=8080'

# 服務發現
curl -X GET 'http://xx.yy.zz.ff:18848/nacos/v1/ns/instance/list?serviceName=nacos.naming.serviceName'

# 發佈配置
curl -X POST "http://xx.yy.zz.ff:18848/nacos/v1/cs/configs?dataId=nacos.cfg.dataId&group=test&content=HelloWorld"

# 獲取配置
curl -X GET "http://xx.yy.zz.ff:18848/nacos/v1/cs/configs?dataId=nacos.cfg.dataId&group=test"

nacos ui

Y 擴展:nacos身份認證與鑑權

Y.1 Nacos啓用身份認證/鑑權

  • 注意
  • Nacos是一個內部微服務組件,需要在可信的內部網絡中運行,不可暴露在公網環境,防止帶來安全風險。
  • Nacos提供簡單的鑑權實現,爲防止業務錯用的弱鑑權體系,不是防止惡意攻擊的強鑑權體系。
  • 如果運行在不可信的網絡環境或者有強鑑權訴求,請參考官方簡單實現做替換增強。

Y.1.1 非Docker環境

  • 按照官方文檔配置啓動,默認是不需要登錄的,這樣會導致配置中心對外直接暴露。而啓用鑑權之後,需要在使用用戶名和密碼登錄之後,才能正常使用nacos。
  • 開啓鑑權之前,application.properties中的配置信息爲:
### If turn on auth system:
nacos.core.auth.enabled=false
  • 開啓鑑權之後,application.properties中的配置信息爲:
### If turn on auth system:
nacos.core.auth.system.type=nacos
nacos.core.auth.enabled=true
  • 【自定義密鑰】
    開啓鑑權之後,你可以自定義用於生成JWT令牌的密鑰,application.properties中的配置信息爲:

注意:
文檔中提供的密鑰爲公開密鑰,在實際部署時請更換爲其他密鑰內容,防止密鑰泄漏導致安全風險。
在2.2.1版本後,社區發佈版本將移除以文檔如下值作爲默認值,需要自行填充,否則無法啓動節點。
密鑰需要保持節點間一致,長時間不一致可能導致403 invalid token錯誤。

### The default token(Base64 String):
nacos.core.auth.default.token.secret.key=SecretKey012345678901234567890123456789012345678901234567890123456789

自定義密鑰時,推薦將配置項設置爲Base64編碼的字符串,且原始密鑰長度不得低於32字符。例如下面的的例子:

### The default token(Base64 String):
nacos.core.auth.default.token.secret.key=VGhpc0lzTXlDdXN0b21TZWNyZXRLZXkwMTIzNDU2Nzg=

注意:鑑權開關是修改之後立馬生效的,不需要重啓服務端。

Y.1.2 Docker環境

  • 官方鏡像

如果使用官方鏡像,請在啓動docker容器時,添加如下環境變量

NACOS_AUTH_ENABLE=true

例如,可以通過如下命令運行開啓了鑑權的容器:

docker run --env PREFER_HOST_MODE=hostname --env MODE=standalone --env NACOS_AUTH_ENABLE=true -p 8848:8848 nacos/nacos-server

除此之外,還可以添加其他鑑權相關的環境變量信息:

name description option
NACOS_AUTH_ENABLE 是否開啓權限系統 默認:false
NACOS_AUTH_TOKEN_EXPIRE_SECONDS token 失效時間 默認:18000
NACOS_AUTH_TOKEN token 默認:SecretKey012345678901234567890123456789012345678901234567890123456789
NACOS_AUTH_CACHE_ENABLE 權限緩存開關 ,開啓後權限緩存的更新默認有15秒的延遲 默認 : false

然後運行docker-compose構建命令,例如

docker-compose -f example/standalone-derby.yaml up
  • 自定義鏡像

如果選擇自定義鏡像,請在構建鏡像之前,修改nacos工程中的application.properties文件,
將下面這一行配置信息

nacos.core.auth.enabled=false

修改爲

nacos.core.auth.system.type=nacos
nacos.core.auth.enabled=true

然後再配置nacos啓動命令。

Y.2 客戶端如何進行鑑權

Y.2.1 Java SDK鑑權

在構建“Properties”類時,需傳入用戶名和密碼。

properties.put("username","${username}");
properties.put("password","${password}");
  • 示例代碼
try {
    // Initialize the configuration service, and the console automatically obtains the following parameters through the sample code.
	String serverAddr = "{serverAddr}";
	Properties properties = new Properties();
	properties.put("serverAddr", serverAddr);

    // if need username and password to login
        properties.put("username","nacos");
        properties.put("password","nacos");

	ConfigService configService = NacosFactory.createConfigService(properties);
} catch (NacosException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
}

Y.2.2 其他語言的SDK鑑權

  • Open-API鑑權

首先需要使用用戶名和密碼登陸nacos。

curl -X POST '127.0.0.1:8848/nacos/v1/auth/login' -d 'username=nacos&password=nacos'

若用戶名和密碼正確,返回信息如下:

{"accessToken":"eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJuYWNvcyIsImV4cCI6MTYwNTYyOTE2Nn0.2TogGhhr11_vLEjqKko1HJHUJEmsPuCxkur-CfNojDo","tokenTtl":18000,"globalAdmin":true}

接下來進行配置信息或服務信息時,應當使用該accessToken鑑權,在url後添加參數accessToken={accessToken},其中{accessToken}爲登錄時返回的token信息,例如

curl -X GET '127.0.0.1:8848/nacos/v1/cs/configs?accessToken=eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJuYWNvcyIsImV4cCI6MTYwNTYyMzkyM30.O-s2yWfDSUZ7Svd3Vs7jy9tsfDNHs1SuebJB4KlNY8Q&dataId=nacos.example.1&group=nacos_group'
curl -X POST 'http://127.0.0.1:8848/nacos/v1/ns/instance?accessToken=eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJuYWNvcyIsImV4cCI6MTYwNTYyMzkyM30.O-s2yWfDSUZ7Svd3Vs7jy9tsfDNHs1SuebJB4KlNY8Q&port=8848&healthy=true&ip=11.11.11.11&weight=1.0&serviceName=nacos.test.3&encoding=GBK&namespaceId=n1'

Y.2.x 身份鑑權測試類 NacosConfigTest

  • 引入Maven依賴
    <!-- nacos-client [start] -->
    <!-- https://mvnrepository.com/artifact/com.alibaba.nacos/nacos-api -->
    <dependency>
      <groupId>com.alibaba.nacos</groupId>
      <artifactId>nacos-api</artifactId>
      <version>${nacos-client.version}</version>
    </dependency>

    <!-- https://mvnrepository.com/artifact/com.alibaba.nacos/nacos-client -->
    <dependency>
      <groupId>com.alibaba.nacos</groupId>
      <artifactId>nacos-client</artifactId>
      <version>${nacos-client.version}</version>
    </dependency>
    <!-- nacos-client [end] -->
  • nacos-client.version : 1.4.3
  • NacosConfigTest
package org.example;

import com.alibaba.nacos.api.NacosFactory;
import com.alibaba.nacos.api.PropertyKeyConst;
import com.alibaba.nacos.api.config.ConfigService;
import com.alibaba.nacos.api.exception.NacosException;
import org.junit.Test;

import java.util.Properties;

/**
 * nacos 配置中心測試
 * @description NACOS Server 端 : 2.0.3 / NACOS 客戶端 : 1.4.3
 * @reference-doc
 *  [1] NACOS 用戶指南(JAVA SDK) - nacos - https://nacos.io/zh-cn/docs/sdk.html
 *  [2] https://mvnrepository.com/artifact/com.alibaba.nacos/nacos-client
 */
public class NacosConfigTest {
    /** NACOS 服務器地址 **/
    private final static String SERVER_ADDR = "https://config-uat.xxxx.com.cn"; // 形如 : 127.0.0.1:8848 或 http://127.0.0.1:8848

    private final static String USERNAME = "nacos";//nacos
    private final static String PASSWORD = "nacos";//nacos
    private final static String NAMESPACE = "xxx_team";//public
    private final static String GROUP = "DEFAULT_GROUP";//DEFAULT_GROUP
    private final static String DATA_ID = "cn.com.xxxx.business.parse";

    /**
     * NACOS 服務器端啓用強制客戶端輸入密碼,但客戶端不提供密碼
     * @sample [shell] curl -X GET 'http://127.0.0.1:8848/nacos/v1/cs/configs?dataId=nacos.example&group=com.alibaba.nacos'
     * @descrption
     * [1] nacos server 2.0.3 : 執行成功
     * [2] nacos server 2.3.1 : 執行失敗,ErrCode:403, ErrMsg:<html><body><h1>Whitelabel Error Page</h1><p>This application has no explicit mapping for /error, so you are seeing this as a fallback
     */
    @Test
    public void nacosServerEnablePasswordButClientNotUsePasswordTest(){
        try {
            Properties properties = new Properties();
            properties.put(PropertyKeyConst.SERVER_ADDR, SERVER_ADDR);
            properties.put(PropertyKeyConst.NAMESPACE, NAMESPACE);
            //properties.put(PropertyKeyConst.USERNAME, USERNAME);
            //properties.put(PropertyKeyConst.PASSWORD, PASSWORD);
            ConfigService configService = NacosFactory.createConfigService(properties);
            String content = configService.getConfig(DATA_ID, GROUP, 5000);
            System.out.println(content);
        } catch (NacosException e) {//讀取配置超時或網絡異常,拋出 NacosException 異常
            // TODO Auto-generated catch block
            e.printStackTrace();
            throw new RuntimeException(e);
        }
    }

    /**
     * NACOS 服務器端不啓用強制客戶端輸入密碼,且客戶端也提供密碼
     * @description
     * [1] nacos server 2.0.3 : 密碼正確時,執行成功 ; 密碼錯誤時, 報 403
     * [1] nacos server 2.3.1 : 密碼正確時,執行成功 ; 密碼錯誤時, 報 403
     */
    @Test
    public void nacosServerDisablePasswordAndClientUsePasswordTest(){
        try {
            Properties properties = new Properties();
            properties.put(PropertyKeyConst.SERVER_ADDR, SERVER_ADDR);
            properties.put(PropertyKeyConst.NAMESPACE, NAMESPACE);
            properties.put(PropertyKeyConst.USERNAME, USERNAME);
            properties.put(PropertyKeyConst.PASSWORD, PASSWORD);
            ConfigService configService = NacosFactory.createConfigService(properties);
            String content = configService.getConfig(DATA_ID, GROUP, 5000);
            System.out.println(content);
        } catch (NacosException e) {//讀取配置超時或網絡異常,拋出 NacosException 異常
            // TODO Auto-generated catch block
            e.printStackTrace();
            throw new RuntimeException(e);
        }
    }

    /**
     * NACOS 服務器端不啓用強制客戶端輸入密碼,但客戶端不提供密碼
     * @sample [shell] curl -X GET 'http://127.0.0.1:8848/nacos/v1/cs/configs?dataId=nacos.example&group=com.alibaba.nacos'
     * @description
     * [1] nacos server 2.0.3 : 請求成功
     * [2] nacos server 2.3.1 : 請求成功
     */
    @Test
    public void nacosServerDisablePasswordButClientNotUsePasswordTest(){
        try {
            Properties properties = new Properties();
            properties.put(PropertyKeyConst.SERVER_ADDR, SERVER_ADDR);
            properties.put(PropertyKeyConst.NAMESPACE, NAMESPACE);
            //properties.put(PropertyKeyConst.USERNAME, USERNAME);
            //properties.put(PropertyKeyConst.PASSWORD, PASSWORD);
            ConfigService configService = NacosFactory.createConfigService(properties);
            String content = configService.getConfig(DATA_ID, GROUP, 5000);
            System.out.println(content);
        } catch (NacosException e) {//讀取配置超時或網絡異常,拋出 NacosException 異常
            // TODO Auto-generated catch block
            e.printStackTrace();
            throw new RuntimeException(e);
        }
    }

    /**
     * NACOS 服務器端啓用強制客戶端輸入密碼,且客戶端也提供密碼
     * @description 執行成功
     */
    @Test
    public void nacosServerEnablePasswordAndClientUsePasswordTest(){
        try {
            Properties properties = new Properties();
            properties.put(PropertyKeyConst.SERVER_ADDR, SERVER_ADDR);
            properties.put(PropertyKeyConst.NAMESPACE, NAMESPACE);
            properties.put(PropertyKeyConst.USERNAME, USERNAME);
            properties.put(PropertyKeyConst.PASSWORD, PASSWORD);
            ConfigService configService = NacosFactory.createConfigService(properties);
            String content = configService.getConfig(DATA_ID, GROUP, 5000);
            System.out.println(content);
        } catch (NacosException e) {//讀取配置超時或網絡異常,拋出 NacosException 異常
            // TODO Auto-generated catch block
            e.printStackTrace();
            throw new RuntimeException(e);
        }
    }
}

Y.3 開啓服務身份識別功能

  • 開啓鑑權功能後,服務端之間的請求也會通過鑑權系統的影響。考慮到服務端之間的通信應該是可信的,因此在1.2~1.4.0版本期間,通過User-Agent中是否包含Nacos-Server來進行判斷請求是否來自其他服務端。

  • 但這種實現由於過於簡單且固定,導致可能存在安全問題。因此從1.4.1版本開始,Nacos添加服務身份識別功能,用戶可以自行配置服務端的Identity,不再使用User-Agent作爲服務端請求的判斷標準。

開啓方式:

### 開啓鑑權
nacos.core.auth.enabled=true

### 關閉使用user-agent判斷服務端請求並放行鑑權的功能
nacos.core.auth.enable.userAgentAuthWhite=false

### 配置自定義身份識別的key(不可爲空)和value(不可爲空)
nacos.core.auth.server.identity.key=example
nacos.core.auth.server.identity.value=example

注意 : 所有集羣均需要配置相同的server.identity信息,否則可能導致服務端之間數據不一致或無法刪除實例等問題。

Y.4 舊版本升級

  • 考慮到舊版本用戶需要升級,可以在升級期間,開啓nacos.core.auth.enable.userAgentAuthWhite=true功能,待集羣整體升級到1.4.1並穩定運行後,再關閉此功能。

X 參考文獻

  • nacos
  • docker

docker compose + standalone 方式

docker compose + standalone + mysql8 方式

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章