使用docker搭建NACOS集群

学习SpringCloud Alibaba,必然会使用Nacos进行服务注册与配置管理。然而,在实际的生产环境中,使用单服务器搭建nacos服务器是十分危险的,如若发生宕机或网络故障,整个微服务将无法访问。因此,通常使用集群的方式进行部署。

Nacos搭建集群要求至少部署3台服务器实例。Nacos使用delby作为内嵌数据库,在使用集群作为部署方式时,内嵌数据库无法保持数据同步与数据一致,故一般使用外接MySQL数据库的方式保存配置文件。

本次MySQL数据库使用一主一从的方式搭建,实现主从复制与读写分离。使用Nginx做反向代理与负载均衡,同样使用一主一从的方式,根据LVS/Keepalived来实现高可用。整体架构如下图所示。

整体架构

Nacos集群整体架构

部署环境

  • Docker 1.13.1
  • Cent0S 7.6
  • Nacos 2.1.0-BETA
  • MySQL 8.0.27
  • nps 0.26.10

一、搭建MySQL主从复制

1.1 准备挂载文件

为了将配置文件在宿主机做挂载,先运行测试镜像拷贝配置文件

docker run -itd -p 3300:3306 \
--name mysql-demo \
-e MYSQL_ROOT_PASSWORD=root \
-d mysql:8.0.27

mkdir -p ~/mysql-master/conf ~/mysql-master/data

docker cp mysql-demo:/etc/mysql/my.cnf ~/mysql-master/conf
cp -r ~/mysql-master ~/mysql-slave

docker stop mysql-demo
docker rm mysql-demo

默认的bridge 网桥无法指定固定的ip,会导致mysql服务的ip不固定,最好配置为自定义网络

创建自定义网络类型

docker network create --subnet=172.18.0.0/16 -d bridge mynet

1.2 创建主从容器

创建两个自定义网路的MySQL容器,使用mynet定义IP时,前面两个数字要与mynet的对应,后面两个可以随便指定,但不能超过255

docker run -itd -p 3301:3306 \
--name mysql-master \
--net mynet --ip 172.18.0.10 \
-v ~/mysql-master/conf/my.cnf:/etc/mysql/my.cnf \
-v ~/mysql-master/data:/var/lib/mysql \
--privileged=true \
--restart=always \
-e MYSQL_ROOT_PASSWORD=root \
-e TZ=Asia/Shanghai \
mysql:8.0.27

docker run -itd -p 3302:3306 \
--name mysql-slave \
--net mynet --ip 172.18.0.11 \
-v ~/mysql-slave/conf/my.cnf:/etc/mysql/my.cnf \
-v ~/mysql-slave/data:/var/lib/mysql \
--privileged=true \
--restart=always \
-e MYSQL_ROOT_PASSWORD=root \
-e TZ=Asia/Shanghai \
mysql:8.0.27

没有学习过docker的同学我在这里简单说明一下参数含义

ParamValue
–name容器名(自定义)
–net指定容器的网络模式
–ip指定容器ip
-v挂载宿主机的一个目录。
–privileged使容器内的root拥有真正的root权限
–restart设置自动重启
-e设置容器环境变量
-p宿主机端口号 : 容器端口号
-d后台运行容器,并返回容器ID
nginx镜像名称/镜像ID

若想要添加其他参数,可使用docker run --help命令,查看帮助手册。

在宿主机中,配置mysql-master挂载的my.cnf文件

vim ~/mysql-master/conf/my.cnf

server-id=100
log-bin=master-bin #开启二进制文件
#binlog-do-db=demo    #需要同步的二进制数据库名;
binlog-ignore-db=information_schema    #不同步的二进制数据库名,如果不设置可以将其注释掉;
binlog-ignore-db=mysql
binlog-ignore-db=performance_schema
binlog-ignore-db=sys
#log-slave-update  #这个是把更新的记录写到二进制文件中;  

配置完成后,需要重启mysql-master容器使其修改的配置文件生效,使用如下命令使mysql进行重启

docker restart mysql-master

在Master数据库创建数据同步用户,授予用户 slave REPLICATION SLAVE权限和REPLICATION CLIENT权限,用于在主从库之间同步数据。首先,使用docker exec -it mysql-master bash命令进入容器。

CREATE USER 'slave'@'%' IDENTIFIED WITH mysql_native_password BY 'slave';
GRANT REPLICATION SLAVE, REPLICATION CLIENT ON *.* TO 'slave'@'%';

输入show master status;查看Master状态:

FilePositionBinlog_Do_DBBinlog_Ignore_DBExecuted_Gtid_Set
master-bin.000018156information_schema,mysql,performance_schema,sys

记住File和Position,后面需要用到。此时一定不要操作Master库,否则将会引起Master状态的变化,File和Position字段也将会进行变化。

相同方法配置mysql-slave挂载的my.cnf文件

vim ~/mysql-slave/conf/my.cnf

## 设置server_id,注意要唯一
server-id=101  
## 开启二进制日志功能,以备Slave作为其它Slave的Master时使用
log-bin=slave-bin   
## relay_log配置中继日志
relay_log=/var/lib/mysql/relay.log  
read_only=1  ## 设置为只读,该项如果不设置,表示slave可读可写

配置完成后,同样重启mysql-slave容器

docker restart mysql-slave

1.3 开启主从复制

进入到mysql-slave容器的mysql客户端,执行如下命令:

change master to master_host='172.18.0.10',
 master_user='slave', 
 master_password='slave', 
 master_port=3306, 
 master_log_file='master-bin.000018', 
 master_log_pos=156, 
 master_connect_retry=30;

命令说明:

ParamValue
master_hostMaster的地址,指的是容器的独立ip,可以通过docker inspect 容器名称
master_portMaster的端口号,指的是容器的端口号
master_user用于数据同步的用户
master_password用于同步的用户的密码
master_log_file指定 Slave 从哪个日志文件开始复制数据,即上文中提到的 File 字段的值
master_log_pos从哪个 Position 开始读,即上文中提到的 Position 字段的值
master_connect_retry如果连接失败,重试的时间间隔,单位是秒,默认是60秒

关于docker启动后的IP地址,可能有些同学不太熟悉,可以通过上面所说的:docker inspect 镜像ID查看:

docker inspect mysql-master | grep \"IPAddress\"

此时,可执行show slave status \G;命令查看主从同步状态

*************************** 1. row ***************************
               Slave_IO_State:
                  Master_Host: 172.18.0.10
                  Master_User: slave
                  Master_Port: 3306
                Connect_Retry: 30
              Master_Log_File: master-bin.000018
          Read_Master_Log_Pos: 156
               Relay_Log_File: relay.000001
                Relay_Log_Pos: 4
        Relay_Master_Log_File: master-bin.000018
             Slave_IO_Running: No
            Slave_SQL_Running: No

上面的Slave_IO_RunningSlave_SQL_Running是需要关注的地方,因为我们还没有开启主从复制过程,所以两者都是No,此时执行命令start slave;开启同步。

*************************** 1. row ***************************
               Slave_IO_State: Waiting for source to send event
                  Master_Host: 172.18.0.10
                  Master_User: slave
                  Master_Port: 3306
                Connect_Retry: 30
              Master_Log_File: master-bin.000018
          Read_Master_Log_Pos: 156
               Relay_Log_File: relay.000002
                Relay_Log_Pos: 325
        Relay_Master_Log_File: master-bin.000018
             Slave_IO_Running: Yes
            Slave_SQL_Running: Yes

如果Slave_SQL_Running:显示为No,请检查宿主机~/mysql-master/data/auto.cnf 与~/mysql-slave/data/auto.cnf 是否相同,若相同,请根据容器中mysql命令select uuid();进行修改。

1.4 测试

使用如下命令进入mysql-master容器内部

docker exec -it mysql-master bash
mysql -uroot -proot

连接mysql数据库,执行nacos-db.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 DATABASE nacos_config;
USE nacos_config;

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 '2010-05-05 00:00:00' COMMENT '创建时间',
  `gmt_modified` datetime NOT NULL DEFAULT '2010-05-05 00:00:00' COMMENT '修改时间',
  `src_user` text COMMENT 'source user',
  `src_ip` varchar(20) 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 '2010-05-05 00:00:00' COMMENT '创建时间',
  `gmt_modified` datetime NOT NULL DEFAULT '2010-05-05 00:00:00' COMMENT '修改时间',
  `src_user` text COMMENT 'source user',
  `src_ip` varchar(20) 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 '2010-05-05 00:00:00' COMMENT '创建时间',
  `gmt_modified` datetime NOT NULL DEFAULT '2010-05-05 00:00:00' COMMENT '修改时间',
  `src_user` text COMMENT 'source user',
  `src_ip` varchar(20) 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 '2010-05-05 00:00:00' COMMENT '创建时间',
  `gmt_modified` datetime NOT NULL DEFAULT '2010-05-05 00:00:00' 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(64) 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 '2010-05-05 00:00:00',
  `gmt_modified` datetime NOT NULL DEFAULT '2010-05-05 00:00:00',
  `src_user` text,
  `src_ip` varchar(20) 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 '2010-05-05 00:00:00' COMMENT '创建时间',
  `gmt_modified` datetime NOT NULL DEFAULT '2010-05-05 00:00:00' 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,
	constraint uk_username_role UNIQUE (username,role)
);

CREATE TABLE permissions (
    role varchar(50) NOT NULL,
    resource varchar(512) NOT NULL,
    action varchar(8) NOT NULL,
    constraint uk_role_permission UNIQUE (role,resource,action)
);

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

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

此时进入mysql-slave容器中查看同步是否成功

docker exec -it mysql-slave bash
mysql -uroot -proot
show databases;

若与master一致,则MySQL集群搭建成功。

二、搭建NACOS集群

2.1 创建Nacos容器

启动第一个Nacos容器

docker run -itd \
-e PREFER_HOST_MODE=ip \
-e MODE=cluster \
-e NACOS_SERVERS="172.18.0.21:8848 172.18.0.22:8848" \
-e SPRING_DATASOURCE_PLATFORM=mysql \
-e MYSQL_SERVICE_HOST=172.18.0.10 \
-e MYSQL_SERVICE_PORT=3306 \
-e MYSQL_SERVICE_DB_NAME=nacos_config \
-e MYSQL_SERVICE_USER=root \
-e MYSQL_SERVICE_PASSWORD=root \
-e MYSQL_SLAVE_SERVICE_HOST=172.18.0.11 \
-e MYSQL_SLAVE_SERVICE_PORT=3306 \
-e MYSQL_DATABASE_NUM=2 \
-e JVM_XMS=256m \
-e JVM_XMX=512m \
-e JVM_XMN=256m \
-p 8801:8848 \
--name nacos01 \
--net mynet --ip 172.18.0.20 \
--privileged=true \
--restart=always \
nacos/nacos-server:v2.1.0-BETA

Nacos-docker的一些环境参数含义如下表所示

NameDescriptionOption
MODEcluster模式/standalone模式cluster/standalone default cluster
NACOS_SERVERSnacos cluster地址eg. ip1,ip2,ip3
PREFER_HOST_MODE是否支持hostnamehostname/ip default ip
NACOS_SERVER_PORTnacos服务器端口default 8848
NACOS_SERVER_IP多网卡下的自定义nacos服务器IP
SPRING_DATASOURCE_PLATFORMstandalone 支持 mysqlmysql / empty default empty
MYSQL_MASTER_SERVICE_HOSTmysql 主节点host
MYSQL_MASTER_SERVICE_PORTmysql 主节点端口default : 3306
MYSQL_MASTER_SERVICE_DB_NAMEmysql 主节点数据库
MYSQL_MASTER_SERVICE_USER数据库用户名
MYSQL_MASTER_SERVICE_PASSWORD数据库密码
MYSQL_SLAVE_SERVICE_HOSTmysql从节点host
MYSQL_SLAVE_SERVICE_PORTmysql从节点端口default :3306
MYSQL_DATABASE_NUM数据库数量default :2
JVM_XMS-Xmsdefault :2g
JVM_XMX-Xmxdefault :2g
JVM_XMN-Xmndefault :1g
JVM_MS-XX:MetaspaceSizedefault :128m
JVM_MMS-XX:MaxMetaspaceSizedefault :320m
NACOS_DEBUG开启远程调试y/n default :n
TOMCAT_ACCESSLOG_ENABLEDserver.tomcat.accesslog.enableddefault :false

启动第二、第三个容器

docker run -itd \
-e PREFER_HOST_MODE=ip \
-e MODE=cluster \
-e NACOS_SERVERS="172.18.0.20:8848 172.18.0.22:8848" \
-e SPRING_DATASOURCE_PLATFORM=mysql \
-e MYSQL_SERVICE_HOST=172.18.0.10 \
-e MYSQL_SERVICE_PORT=3306 \
-e MYSQL_SERVICE_DB_NAME=nacos_config \
-e MYSQL_SERVICE_USER=root \
-e MYSQL_SERVICE_PASSWORD=root \
-e MYSQL_SLAVE_SERVICE_HOST=172.18.0.11 \
-e MYSQL_SLAVE_SERVICE_PORT=3306 \
-e MYSQL_DATABASE_NUM=2 \
-e JVM_XMS=256m \
-e JVM_XMX=512m \
-e JVM_XMN=256m \
-p 8802:8848 \
--name nacos02 \
--net mynet --ip 172.18.0.21 \
--privileged=true \
--restart=always \
nacos/nacos-server:v2.1.0-BETA

docker run -itd \
-e PREFER_HOST_MODE=ip \
-e MODE=cluster \
-e NACOS_SERVERS="172.18.0.20:8848 172.18.0.21:8848" \
-e SPRING_DATASOURCE_PLATFORM=mysql \
-e MYSQL_SERVICE_HOST=172.18.0.10 \
-e MYSQL_SERVICE_PORT=3306 \
-e MYSQL_SERVICE_DB_NAME=nacos_config \
-e MYSQL_SERVICE_USER=root \
-e MYSQL_SERVICE_PASSWORD=root \
-e MYSQL_SLAVE_SERVICE_HOST=172.18.0.11 \
-e MYSQL_SLAVE_SERVICE_PORT=3306 \
-e MYSQL_DATABASE_NUM=2 \
-e JVM_XMS=256m \
-e JVM_XMX=512m \
-e JVM_XMN=256m \
-p 8803:8848 \
--name nacos03 \
--net mynet --ip 172.18.0.22 \
--privileged=true \
--restart=always \
nacos/nacos-server:v2.1.0-BETA

如果此时在容器内curl -X POST "http://127.0.0.1:8848/nacos/v1/cs/configs?dataId=nacos.cfg.dataId&group=test&content=helloWorld"有返回true,而在宿主机telnet 172.18.0.20 8801成功,curl -X POST "http://127.0.0.1:8848/nacos/v1/cs/configs?dataId=nacos.cfg.dataId&group=test&content=helloWorld"提示Recv failure: Connection reset by peer,请尝试添加docker0网桥。

systemctl stop docker
ip link set dev docker0 down
ip addr add 172.18.10.1/24 dev docker0
ip link set dev docker0 up
systemctl start docker

待容器启动成功后,重新curl -X POST "http://127.0.0.1:8801/nacos/v1/cs/configs?dataId=nacos.cfg.dataId&group=test&content=helloWorld",若返回true,则表示成功。

2.2 测试

在浏览器中输入http://192.168.229.131:8801/nacos,使用 username:nacos password:nacos 登录系统后,查看节点列表。

Nacos集群节点列表

三、搭建NGINX集群

1.1 配置模板容器

下载centos:7.6.1810镜像

docker  pull  centos:7.6.1810

启动并进入容器

docker run -it centos:7.6.1810 /bin/bash

安装基础工具

yum install -y iproute

yum  install -y net-tools

安装keepalived

yum install -y keepalived

在/etc/keepalived目录下创建Keepalived检测nginx的脚本check_nginx.sh,并赋权

#!/bin/bash

A=$(ps -ef  | grep nginx: | grep -v  grep |  wc  -l)

if [ $A -eq 0 ];then

  nginx

  echo  "restart nginx, sleep 2 s" >> /etc/keepalived/keepalived.log

  sleep  2

  num=$(ps -ef  | grep  nginx:  |  grep -v grep | wc  -l)

  if [ $num -eq  0  ];then

    ip addr delete 172.18.0.30/32 dev eth0

    ps -ef | grep keepalived  |  grep  -v grep  | awk '{print $2}'| xargs kill -9

    echo  "start nginx failed,kill keepalived" >> /etc/keepalived/keepalived.log

  fi

else

  echo  "nginx not  dead" >> /etc/keepalived/keepalived.log

fi

chmod +x nginx_check.sh

备份并修改keepalived.conf配置脚本

cp /etc/keepalived/keepalived.conf /etc/keepalived/keepalived.conf.backup

vim keepalived.conf

global_defs {
    router_id LVS_DEVEL  #表示节点id 可以修改 比如 nodeA nodeB
}


vrrp_script chk_nginx {
    script "/etc/keepalived/check_nginx.sh"  #执行一段监测nginx进程是否正常如果不正常尝试启动
    interval 5
    fall 3
    rise 2
}


vrrp_instance VI_1 {
    state MASTER   #标识该节点是master 还是backup
    interface eth0   #该处必须是ifconfig之后得到的网卡名称
    virtual_router_id 51   #虚拟节点id 与backup的需保持一致
    priority 100  #优先级,master的优先级数值要大于backup
    advert_int 2
    authentication {
        auth_type PASS  #相关授权 可以配置,也可不修改
        auth_pass 1111
    }
    virtual_ipaddress {
        172.18.0.30   #虚拟节点ip ,需要配置,这样在网关处可以访问该ip 用来跳转到某一个节点
    }
    track_script {
       chk_nginx #调用执行脚本的函数,上面已经定义该函数
    }
}

设置keepalived服务

chkconfig keepalived on  

安装nginx及service

#使用yum安装nginx需要包括Nginx的库,安装Nginx的库
rpm -Uvh http://nginx.org/packages/centos/7/noarch/RPMS/nginx-release-centos-7-0.el7.ngx.noarch.rpm
# 使用下面命令安装nginx
yum install -y nginx

退出容器,制作镜像

docker commit `docker ps -a | grep centos:7.6.1810 | awk '{print $1}'` keepalived_nginx:v1

1.2 启动主备keepalived容器

docker run -itd \
--privileged=true \
--name keepalived_master  \
--restart=always \
--net mynet --ip 172.18.0.31 \
keepalived_nginx:v1 \
/usr/sbin/init

docker run -itd \
--privileged=true \
--name keepalived_slave  \
--restart=always \
--net mynet --ip 172.18.0.32 \
keepalived_nginx:v1 \
/usr/sbin/init

进入备机中修改keepalived配置

global_defs {
    router_id LVS_DEVEL
}


vrrp_script chk_nginx {
    script "/etc/keepalived/check_nginx.sh"
    interval 5
    fall 3
    rise 2
}


vrrp_instance VI_1 {
    state BACKUP //修改名称
    interface eth0
    virtual_router_id 51
    priority 90 //修改优先级
    advert_int 2
    authentication {
        auth_type PASS
        auth_pass 1111
    }
    virtual_ipaddress {
        172.18.0.30
    }
    track_script {
       chk_nginx
    }
}

修改完后重启keepalived

systemctl reload keepalived
systemctl restart keepalived

使用ip a命令查看主备容器的ip情况

keepalived_master
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
67: eth0@if68: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
    link/ether 02:42:ac:12:00:1f brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet 172.18.0.31/16 scope global eth0
       valid_lft forever preferred_lft forever
    inet 172.18.0.30/32 scope global eth0
       valid_lft forever preferred_lft forever
    inet6 fe80::42:acff:fe12:1f/64 scope link
       valid_lft forever preferred_lft forever

keepalived_slave
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
69: eth0@if70: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
    link/ether 02:42:ac:12:00:20 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet 172.18.0.32/16 scope global eth0
       valid_lft forever preferred_lft forever
    inet6 fe80::42:acff:fe12:20/64 scope link
       valid_lft forever preferred_lft forever

可以发现虚拟ip [inet 172.18.0.30/32]此时已绑定在主容器上

1.3 测试

因脚本会自动重启nginx,关闭主容器的keepalived服务,查看备容器ip情况

systemctl stop nginx

keepalived_slave
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
69: eth0@if70: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
    link/ether 02:42:ac:12:00:20 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet 172.18.0.32/16 scope global eth0
       valid_lft forever preferred_lft forever
    inet 172.18.0.30/32 scope global eth0
       valid_lft forever preferred_lft forever
    inet6 fe80::42:acff:fe12:20/64 scope link
       valid_lft forever preferred_lft forever

此时虚拟ip漂移到了从机上。

1.4 实现nginx反向代理

修改/etc/nginx/conf.d目录下default.conf配置文件

vim /etc/nginx/nginx.conf


upstream nacosList {
    server nacos01:8848;
    server nacos02:8848;
    server nacos03:8848;
}

server {
    listen  80;
    server_name  localhost;

    location / {
        root   /usr/share/nginx/html;
        index  index.html index.htm;
    }

    error_page   500 502 503 504  /50x.html;


    location = /50x.html {
        root   /usr/share/nginx/html;
    }

    location /nacos {
        proxy_pass  http://nacosList/nacos;
    }

}

重启nginx服务

systemctl reload nginx
systemctl restart nginx

使用curl命令测试

curl -X GET "http://172.18.0.30/nacos/v1/cs/configs?dataId=nacos.cfg.dataId&group=test"

若返回helloWorld,则反向代理搭建成功。

四、实现内网穿透

这样一个内网环境的Nacos集群就搭建完成了,但是无法在外网进行访问,为此需要实现内网穿透。

这里我使用的是nps可视化穿透服务,同样使用docker的方式来进行安装

打开下面的网址下载配置文件目录

下载conf配置文件

将文件解压并放至~/nps/server目录下

启动docker容器

docker run -itd \
--name nps \
--net mynet --ip 172.18.0.40 \
-p 8088:8080 \
-p 15876:15876 \
-p 15877:15877 \
-p 15878:15878 \
-v ~/nps/server/conf:/conf \
ffdfgdfg/nps

此时可访问宿主机8088端口打开控制页面,使用admin/123登录

在客户端选项卡中新增一条记录,记录此时的vkey

现在需要在nginx容器内安装客户端。

docker exec -it keepalived_master bash
cd /opt
wget -e use_proxy=yes -e http_proxy=127.0.0.1:1080 https://github.com/ehang-io/nps/releases/download/v0.26.10/linux_amd64_client.tar.gz
mkdir -p linux_amd64_client
tar -zxvf linux_amd64_client.tar.gz -C linux_amd64_client

将客户端注册到系统服务

cd /opt/linux_amd64_client
nohup ./npc -server=172.18.0.40:8024 -vkey=${vkey} > npc.out 2>&1 &

此时可以在客户端页面看到连接为在线

在SOCKS代理页面,根据客户端ID,新增一条服务端端口为15876的SOCKS 代理

下载并安装Proxifier工具

在配置文件 → 代理服务器 → 添加 添加代理服务器

Address填写宿主机ip,Port填写15876

Protocol选择Socks Version5

在主机浏览器中输入172.18.0.30/nacos

在这里插入图片描述

成功在外网访问到内网网段的Nacos集群!

Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐