Home | 简体中文 | 繁体中文 | 杂文 | Github | 知乎专栏 | Facebook | Linkedin | Youtube | 打赏(Donations) | About
知乎专栏

第 68 章 Spring Cloud Alibaba

目录

68.1. 安装 Nacos
68.1.1. Docker 安装 Nacos
68.1.2. Kubernetes 安装 Nacos
68.1.3. IP限制,白名单
68.1.4. 防火墙配置
68.2. Kubernetes 部署微服务
68.2.1. pom.xml 中加入 docker 插件
68.2.2. 容器启动脚本
68.2.3. 构建 docker 镜像
68.2.4. 编排 kubernetes 容器
68.2.5. 启动指定 nacos
68.3. Nacos 配置中心/注册中心代码实例
68.3.1. Maven
68.3.2. SpringBootApplication
68.3.3. ConfigController
68.3.4. 配置文件
68.4. FAQ
68.4.1. 禁用 Nacos
68.4.2. 禁止注册
68.4.3. Failed to bind properties under 'server.tomcat.basedir' to java.io.File:
68.4.4. 不读取 bootstrap.yaml 文件
68.4.5. WARN [com.alibaba.nacos.client.naming:177] [,] - out of date data received, old-t: 1665711914993, new-t: 1665711902390
68.4.6. User limit of inotify instances reached or too many open files
68.4.7. 开启权限
68.4.8. ERROR Whitelabel
68.4.9.

68.1. 安装 Nacos

68.1.1. Docker 安装 Nacos

安装 netkiller-devops 库

		
pip install netkiller-devops		
		
			

创建 docker.py 编排文件

		
#!/usr/bin/env python3
from netkiller.docker import *

volume = Volumes()
volume.create('mysql')

mysql = Services('mysql')
mysql.image('mysql:5.7').container_name('mysql').restart('always').hostname('db.netkiller.cn').env_file(os.getcwd()+'/nacos/env/mysql.env')
mysql.ports(['3306:3306']).volumes([
	'mysql:/var/lib/mysql'
]).command([
	'--socket=/var/lib/mysql/mysql.sock',
	'--default-authentication-plugin=mysql_native_password',
    '--character-set-server=utf8mb4',
    '--collation-server=utf8mb4_general_ci',
    '--explicit_defaults_for_timestamp=true',
    '--lower_case_table_names=1',
    '--max_execution_time=0'
])

nacos = Services('nacos')
nacos.container_name('nacos').env_file(os.getcwd()+'/nacos/env/nacos-mysql.env')
# .environment([
# 	'PREFER_HOST_MODE=hostname',
# 	'MODE=standalone'
# ])
nacos.image('nacos/nacos-server').volumes([
	'../nacos/logs/:/home/nacos/logs',
	'../nacos/init.d/custom.properties:/home/nacos/init.d/custom.properties'
]).ports([
	"8848:8848",
    "9848:9848",
	'9555:9555'
]).depends_on('mysql').restart('on-failure')

experiment = Composes('experiment')
experiment.version('3.9')
experiment.volumes(volume)
experiment.services(mysql)
experiment.services(nacos)

if __name__ == '__main__':
	try:
		docker = Docker()
		docker.sysctl([{'vm.max_map_count':'262144'}])
		docker.environment(experiment)
		docker.main()
	except KeyboardInterrupt:
		print ("Crtl+C Pressed. Shutting down.")
		
			

查看帮助信息

		
[root@localhost ~]# python3 docker.py 
Python controls the docker manager.
Usage: docker.py [options] up|rm|start|stop|restart|logs|top|images|exec <service>

Options:
  -h, --help            show this help message and exit
  --debug               debug mode
  -e development|testing|production, --environment=development|testing|production
                        environment
  -d, --daemon          run as daemon
  --logfile=LOGFILE     logs file.
  -l, --list            print service of environment
  -f, --follow          following logging
  -c, --compose         show docker compose
  --export              export docker compose

Homepage: http://www.netkiller.cn	Author: Neo <netkiller@msn.com>		
		
			

启动 nacos

		
[root@localhost ~]# python3 docker.py -e experiment up nacos
mysql is up-to-date
Starting nacos ... done

[root@localhost ~]# python3 docker.py -e experiment ps 
    Name                   Command               State                                                         Ports                                                      
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------                            
mysql           docker-entrypoint.sh --soc ...   Up      0.0.0.0:3306->3306/tcp,:::3306->3306/tcp, 33060/tcp                                                              
nacos           bin/docker-startup.sh            Up      0.0.0.0:8848->8848/tcp,:::8848->8848/tcp, 0.0.0.0:9555->9555/tcp,:::9555->9555/tcp,                              
                                                         0.0.0.0:9848->9848/tcp,:::9848->9848/tcp   		
		
			

查看启动端口

		
[root@localhost ~]# ss -lnt | grep -E "(8848|9848)"
LISTEN 0      1024         0.0.0.0:8848       0.0.0.0:*          
LISTEN 0      1024         0.0.0.0:9848       0.0.0.0:*          
LISTEN 0      1024            [::]:8848          [::]:*          
LISTEN 0      1024            [::]:9848          [::]:*   		
		
			

测试配置中心

		
[root@localhost ~]# curl -X POST "http://127.0.0.1:8848/nacos/v1/cs/configs?dataId=nacos.cfg.dataId&group=test&content=helloWorld"
true

[root@localhost ~]# curl -X GET "http://127.0.0.1:8848/nacos/v1/cs/configs?dataId=nacos.cfg.dataId&group=test"
helloWorld
		
			

登陆 Web 界面 http://192.168.30.12:8848/nacos/ 默认的账号密码是:nacos/nacos

68.1.2. Kubernetes 安装 Nacos

创建 nacos 数据库用户

			
CREATE USER 'nacos'@'%' IDENTIFIED BY 'nacos';

GRANT ALL PRIVILEGES ON nacos.* TO 'nacos'@'%';

SHOW GRANTS FOR 'nacos'@'%';			
			
			

前往 https://github.com/alibaba/nacos/blob/master/distribution/conf/nacos-mysql.sql 下来SQL文件,恢复到 nacos 数据中。

			
import sys
sys.path.insert(0, '/Users/neo/workspace/devops')
from netkiller.kubernetes import *
namespace = 'default'

config = ConfigMap('nacos')
config.apiVersion('v1')
config.metadata().name('nacos').namespace(namespace)
config.data({
    'mysql.host': "rm-bp1g441na9an26wsb.mysql.rds.aliyuncs.com",
    'mysql.port': "3306",
    'mysql.dbname': "nacos",
    'mysql.user': "nacos",
    'mysql.password': "nacos"
})
# config.debug()

statefulSet = StatefulSet()
statefulSet = StatefulSet()
statefulSet.apiVersion('apps/v1')
statefulSet.metadata().name('nacos').labels(
    {'app': 'nacos'}).namespace(namespace)
statefulSet.spec().replicas(3)
statefulSet.spec().serviceName('nacos')
statefulSet.spec().selector({'matchLabels': {'app': 'nacos'}})
statefulSet.spec().template().metadata().labels({'app': 'nacos'})
statefulSet.spec().template().metadata().annotations(
    {'pod.alpha.kubernetes.io/initialized': "true"})
# statefulSet.spec().template().spec().affinity().nodeAffinity({
#     'requiredDuringSchedulingIgnoredDuringExecution': [
#         {'labelSelector': {
#             'matchExpressions': [
#                 {'key': 'app',
#                  'operator': 'In',
#                  'values': ['nacos']
#                  }]
#             },
#         'topologyKey': "kubernetes.io/hostname"
#         }
#     ]
# })
statefulSet.spec().template().spec().containers().name('nacos').imagePullPolicy(Define.containers.imagePullPolicy.IfNotPresent).image(
    'nacos/nacos-server:latest').resources(
        # {'requests': {
        # # 'cpu':'200m',
        # 'memory': "2Gi"}}
        ).ports([
        {'name':'client','containerPort': 8848},
        {'name':'client-rpc','containerPort': 9848},
        {'name':'raft-rpc','containerPort': 9849}
    ]).env([
        {'name': 'TZ', 'value': 'Asia/Shanghai'},
        {'name': 'LANG', 'value': 'en_US.UTF-8'},
        {'name': 'NACOS_REPLICAS', 'value': '1'},

        # {'name': 'SPRING_DATASOURCE_PLATFORM', 'value': 'mysql'},
        # {'name': 'MYSQL_SERVICE_HOST', 'value': 'mysql-0.mysql.default.svc.cluster.local'},
        {'name': 'MYSQL_SERVICE_HOST', 'valueFrom':{'configMapKeyRef':{'name': 'nacos','key': 'mysql.host'}}},
        {'name': 'MYSQL_SERVICE_PORT', 'valueFrom':{'configMapKeyRef':{'name': 'nacos','key': 'mysql.port'}}},
        {'name': 'MYSQL_SERVICE_DB_NAME', 'valueFrom':{'configMapKeyRef':{'name': 'nacos','key': 'mysql.dbname'}}},
        {'name': 'MYSQL_SERVICE_USER', 'valueFrom':{'configMapKeyRef':{'name': 'nacos','key': 'mysql.user'}}},
        {'name': 'MYSQL_SERVICE_PASSWORD', 'valueFrom':{'configMapKeyRef':{'name': 'nacos','key': 'mysql.password'}}},
        # {'name': 'MYSQL_SERVICE_DB_PARAM', 'value': 'characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true&useSSL=false&serverTimezone=GMT%2B8'},
        
        {'name': 'NACOS_SERVER_PORT', 'value': '8848'},
        {'name': 'NACOS_APPLICATION_PORT', 'value': '8848'},
        {'name': 'PREFER_HOST_MODE', 'value': 'hostname'},
        {'name': 'NACOS_SERVERS', 'value': 'nacos-0.nacos.default.svc.cluster.local:8848 nacos-1.nacos.default.svc.cluster.local:8848 nacos-2.nacos.default.svc.cluster.local:8848'},

        # {'name': 'JVM_XMX', 'value': '4g'},
        # {'name': 'NACOS_DEBUG', 'value': 'true'},
        # {'name': 'TOMCAT_ACCESSLOG_ENABLED', 'value': 'true'},
    ])

# statefulSet.debug()

service = Service()
service.metadata().name('nacos')
service.metadata().namespace(namespace)
service.metadata().labels({'app':'nacos'})
service.spec().selector({'app': 'nacos'})
service.spec().type('ClusterIP')
service.spec().ports([
    {'name': 'server', 'protocol': 'TCP', 'port': 8848, 'targetPort': 8848},
    {'name': 'client-rpc', 'protocol': 'TCP', 'port': 9848, 'targetPort': 9848},
    {'name': 'raft-rpc', 'protocol': 'TCP', 'port': 9555, 'targetPort': 9555}
])

# service.debug()

ingress = Ingress()
ingress.apiVersion('networking.k8s.io/v1')
ingress.metadata().name('nacos')
ingress.metadata().namespace(namespace)
# ingress.metadata().annotations({'kubernetes.io/ingress.class': 'nginx'})
ingress.spec().rules([{
    'host': 'nacos.netkiller.com',
    'http':{
        'paths': [{
            'pathType': Define.Ingress.pathType.Prefix,
            'path': '/nacos', 
            'backend':{
                'service':{
                    'name':'nacos', 
                    'port':{'number': 8848}
                }
            }}]
}}])
# ingress.debug()

kubernetes = Kubernetes('/Volumes/Data/kubeconfig')
compose = Compose('nacos')
compose.add(config)
compose.add(statefulSet)
compose.add(service)
compose.add(ingress)
kubernetes.compose(compose)
kubernetes.main()

			
			
			
			

68.1.3. IP限制,白名单

			 
	location /nacos {
        allow 192.168.0.0/24;
        allow 172.18.0.0/16;
        allow 202.104.66.10;        
        deny all;

        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;

        proxy_pass http://192.168.0.10:8848;
    }
			
			

68.1.4. 防火墙配置

配置防火墙,限制 8848 端口的访问策略,防止本地或其他服务注册到 Nacos 中。

			 
$ iptables -A INPUT -s 172.18.5.0/24 -p tcp --dport 8848 -j REJECT
			
			

172.18.5.0/24 是办公网络,添加上面IP规则,可以防止开发人的电脑注册到测试环境。

删除规则

删除方法一

			 
$ iptables -L -n --line-number | grep 8848
8    REJECT     tcp  --  172.18.5.0/24        0.0.0.0/0            tcp dpt:8848 reject-with icmp-port-unreachable
134  ACCEPT     tcp  --  0.0.0.0/0            172.17.0.119         tcp dpt:8848

$ iptables -D INPUT 8
			
			

删除方法二

			 
$ iptables -D INPUT -s 172.18.5.0/24 -p tcp --dport 8848 -j REJECT