本工具帮助用户方便的在k8s
环境中启动一条CITA-Cloud
链。本工具会为链的每一个节点生成必须的配置文件,以及用于部署到k8s
的yaml
文件。
链的所有节点都在同一个k8s
集群中。
- python 3
- docker
安装依赖包:
pip install -r requirements.txt
$ ./create_k8s_config.py local_cluster -h
usage: create_k8s_config.py local_cluster [-h] [--block_delay_number BLOCK_DELAY_NUMBER] [--chain_name CHAIN_NAME] [--peers_count PEERS_COUNT]
[--kms_password KMS_PASSWORD] [--state_db_user STATE_DB_USER] [--state_db_password STATE_DB_PASSWORD]
[--service_config SERVICE_CONFIG] [--node_port NODE_PORT] [--need_monitor NEED_MONITOR] [--pvc_name PVC_NAME]
optional arguments:
-h, --help show this help message and exit
--block_delay_number BLOCK_DELAY_NUMBER
The block delay number of chain.
--chain_name CHAIN_NAME
The name of chain.
--peers_count PEERS_COUNT
Count of peers.
--kms_password KMS_PASSWORD
Password of kms.
--state_db_user STATE_DB_USER
User of state db.
--state_db_password STATE_DB_PASSWORD
Password of state db.
--service_config SERVICE_CONFIG
Config file about service information.
--node_port NODE_PORT
The node port of rpc.
--need_monitor NEED_MONITOR
Is need monitor
--pvc_name PVC_NAME Name of persistentVolumeClaim.
节点是有状态的服务,需要挂载持久化存储来保存数据。
为了方便对接不同的存储服务,我们使用了k8s
的pv/pvc
对存储进行了抽象。
目前支持local path
和nfs
。
直接指定节点上的一个目录作为持久化存储。
对于集群中有多个节点的情况,则要在每个节点上都创建同样的目录。生成的配置文件也要在多个节点的目录中都放一份。
$ ./create_pvc.py local_pvc -h
usage: create_pvc.py local_pvc [-h] [--data_dir DATA_DIR] [--node_list NODE_LIST]
optional arguments:
-h, --help show this help message and exit
--data_dir DATA_DIR Root data dir where store data of each node.
--node_list NODE_LIST
Host name list of nodes of k8s cluster.
data_dir
参数设置要使用的目录。
node_list
参数指定集群中节点的hostname
列表,以,
分割。
集群节点的hostname
列表,可以通过如下命令获取:
$ kubectl get nodes
NAME STATUS ROLES AGE VERSION
minikube Ready master 23d v1.18.3
以minikube
环境举例:
$ minikube ssh
docker@minikube:~$ mkdir cita-cloud-datadir
docker@minikube:~$ exit
$ ./create_pvc.py local_pvc
$ ls
local-pvc.yaml
$ kubectl apply -f local-pvc.yaml
即可创建名为local-pvc
的PVC
。
搭建一个集群节点可以访问的nfs server
,作为持久化存储。
$ ./create_pvc.py nfs_pvc -h
usage: create_pvc.py nfs_pvc [-h] [--nfs_server NFS_SERVER] [--nfs_path NFS_PATH]
optional arguments:
-h, --help show this help message and exit
--nfs_server NFS_SERVER
Address of nfs server.
--nfs_path NFS_PATH Path of nfs server.
nfs_server
和nfs_path
两个参数分别传递NFS
的ip
和路径。
$ ./create_pvc.py nfs_pvc --nfs_server 127.0.0.1 --nfs_path /data/nfs
$ ls
nfs-pvc.yaml
$ kubectl apply -f nfs-pvc.yaml
即可创建名为nfs-pvc
的PVC
。
cita-cloud
分为六个微服务:network
, consensus
, executor
, storage
, controller
, kms
。
每个微服务都可能有多个不同的实现,service-config.toml
用来配置每个微服务分别选择哪些实现,以及相应的启动命令。
目前微服务的实现有:
network
。目前只有network_p2p
这一个实现,选择该实现,需要将is_need_network_key
设置为true
。consensus
。目前有consensus_raft
一个实现。executor
。目前有executor_chaincode
和executor_chaincode_ext
两个实现,其中executor_chaincode_ext
是不开源的。storage
。目前有storage_sqlite
和storage_tikv
两个实现。如果选择使用storage_tikv
,需要先按照文档安装运行tikv
。controller
。目前只有controller_poc
这一个实现。kms
。目前有kms_eth
和kms_sm
两个实现,分别兼容以太坊和国密。
注意:六个微服务缺一不可;每个微服务只能选择一个实现,不能多选。
运行命令生成相应的文件。kms
的密码,pvc
的名字是必选参数,其他参数可以使用默认值。
注意:如果要在一个集群中同时运行多条链,请务必保证chain_name
是唯一的。它会作为配置文件的文件夹名称,k8s
配置文件的名称,以及经过sha256
运算后作为chainid
。
$ ./create_k8s_config.py local_cluster --kms_password 123456 --peers_count 3 --pvc_name local-pvc
$ ls
cita-cloud test-chain.yaml
生成的cita-cloud
目录结构如下:
$ tree cita-cloud
cita-cloud
└── test-chain
├── node0
├── node1
├── node2
最外层是cita-cloud
;第二层是链的名称,跟chain_name
参数保持一致;最里面是各个节点的文件夹。
node0
,node1
, node2
是三个节点文件夹,里面有相应节点的配置文件。
test-chain.yaml
用于将链部署到k8s
,里面声明了相关的secret
/deployment
/service
,文件名跟chain_name
参数保持一致。
为了方便客户端使用,需要暴露到集群外的端口都设置了固定的端口号。同时为了防止在一个集群中部署多条链时引起端口冲突,通过node_port
参数传递起始端口号,各个需要暴露的端口号依如下次序递增:
RPC
端口为node_port
参数的值。- 如果
need_monitor
设置为true
,每个节点会有两个monitor
端口,分别是process
和exporter
。它们的端口号分别为node_port + 1 + 5 * i
和node_port + 1 + 5 * i + 1
。 - 如果
executor
为chaincode
。每个节点会有:一个chaincode
端口,端口号是node_port + 1 + 5 * i + 2
;一个eventhub
端口,端口号是node_port + 1 + 5 * i + 3
;一个call
端口,端口号是node_port + 1 + 5 * i + 4
;
以node_port
参数默认值30004,三个节点为例:
test-chain-node-port 50004:30004/TCP // RPC端口
monitor-test-chain-0 9256:30005/TCP,9349:30006/TCP // node0的两个监控端口
monitor-test-chain-1 9256:30010/TCP,9349:30011/TCP // node1的两个监控端口
monitor-test-chain-2 9256:30015/TCP,9349:30016/TCP // node1的两个监控端口
chaincode-test-chain-0 7052:30007/TCP,7053:30008/TCP,50002:30009/TCP // node0的chaincode相关的三个端口
chaincode-test-chain-1 7052:30012/TCP,7053:30013/TCP,50002:30014/TCP // node1的chaincode相关的三个端口
chaincode-test-chain-2 7052:30017/TCP,7053:30018/TCP,50002:30019/TCP // node2的chaincode相关的三个端口
注意:无论功能是否打开,相关的端口号都会保留。例如,即使没有打开监控功能,chaincode的端口号依然跟上述例子相同。
这里演示的是在单机的minikube
环境中部署,确保minikube
已经在本机安装并正常运行。
$ scp -i ~/.minikube/machines/minikube/id_rsa -r cita-cloud docker@`minikube ip`:~/cita-cloud-datadir/
$ kubectl apply -f test-chain.yaml
secret/kms-secret created
service/test-chain-node-port created
secret/node0-network-secret created
service/test-chain-0 created
deployment.apps/deployment-test-chain-0 created
service/executor-test-chain-0 created
secret/node1-network-secret created
service/test-chain-1 created
deployment.apps/deployment-test-chain-1 created
service/executor-test-chain-1 created
secret/node2-network-secret created
service/test-chain-2 created
deployment.apps/deployment-test-chain-2 created
service/executor-test-chain-2 created
查看运行情况:
$ kubectl get po
NAME READY STATUS RESTARTS AGE
test-chain-0-6549db45f8-9j75p 7/7 Running 0 67s
test-chain-1-75ff584bcb-v5nw4 7/7 Running 0 66s
test-chain-2-7774f7dd46-pvw5t 7/7 Running 0 66s
$ kubectl get deployments.apps
NAME READY UP-TO-DATE AVAILABLE AGE
test-chain-0 1/1 1 1 71s
test-chain-1 1/1 1 1 71s
test-chain-2 1/1 1 1 70s
$ minikube ssh
docker@minikube:~$ tail -10f cita-cloud-datadir/cita-cloud/test-chain/node0/logs/controller-service.log
2020-08-27T07:42:43.280172163+00:00 INFO controller::chain - 1 blocks finalized
2020-08-27T07:42:43.282871996+00:00 INFO controller::chain - executed block 1397 hash: 0x 16469..e061
2020-08-27T07:42:43.354375501+00:00 INFO controller::pool - before update len of pool 0, will update 0 tx
2020-08-27T07:42:43.354447445+00:00 INFO controller::pool - after update len of pool 0
2020-08-27T07:42:43.354467947+00:00 INFO controller::pool - low_bound before update: 0
2020-08-27T07:42:43.354484999+00:00 INFO controller::pool - low_bound after update: 0
2020-08-27T07:42:43.385062636+00:00 INFO controller::controller - get block from network
2020-08-27T07:42:43.385154627+00:00 INFO controller::controller - add block
2020-08-27T07:42:43.386148650+00:00 INFO controller::chain - add block 0x 11cf7..cad9
2020-08-27T07:42:46.319058783+00:00 INFO controller - reconfigure consensus!
停止
$ kubectl delete -f test-chain.yaml
secret "kms-secret" deleted
service "test-chain-node-port" deleted
secret "node0-network-secret" deleted
service "test-chain-0" deleted
deployment.apps "deployment-test-chain-0" deleted
service "executor-test-chain-0" deleted
secret "node1-network-secret" deleted
service "test-chain-1" deleted
deployment.apps "deployment-test-chain-1" deleted
service "executor-test-chain-1" deleted
secret "node2-network-secret" deleted
service "test-chain-2" deleted
deployment.apps "deployment-test-chain-2" deleted
service "executor-test-chain-2" deleted
链的节点分布在多个k8s
集群中。此部分内容跟单集群部分重复的地方将不再赘述,仅描述差异的内容。
安装依赖包:
pip install -r requirements.txt
$ ./create_k8s_config.py multi_cluster -h
usage: create_k8s_config.py multi_cluster [-h] [--block_delay_number BLOCK_DELAY_NUMBER] [--chain_name CHAIN_NAME]
[--service_config SERVICE_CONFIG] [--need_monitor NEED_MONITOR]
[--timestamp TIMESTAMP] [--super_admin SUPER_ADMIN] [--authorities AUTHORITIES]
[--nodes NODES] [--lbs_tokens LBS_TOKENS] [--sync_device_ids SYNC_DEVICE_IDS]
[--kms_passwords KMS_PASSWORDS] [--node_ports NODE_PORTS]
[--pvc_names PVC_NAMES] [--state_db_user STATE_DB_USER]
[--state_db_password STATE_DB_PASSWORD]
optional arguments:
-h, --help show this help message and exit
--block_delay_number BLOCK_DELAY_NUMBER
The block delay number of chain.
--chain_name CHAIN_NAME
The name of chain.
--service_config SERVICE_CONFIG
Config file about service information.
--need_monitor NEED_MONITOR
Is need monitor
--timestamp TIMESTAMP
Timestamp of genesis block.
--super_admin SUPER_ADMIN
Address of super admin.
--authorities AUTHORITIES
Authorities (addresses) list.
--nodes NODES Node network ip list.
--lbs_tokens LBS_TOKENS
The token list of LBS.
--sync_device_ids SYNC_DEVICE_IDS
Device id list of syncthings.
--kms_passwords KMS_PASSWORDS
Password list of kms.
--node_ports NODE_PORTS
The list of start port of Nodeport.
--pvc_names PVC_NAMES
The list of persistentVolumeClaim names.
--state_db_user STATE_DB_USER
User of state db.
--state_db_password STATE_DB_PASSWORD
Password of state db.
$ echo "password" > key_file
$ ls
create_account.py key_file kms kms.db kms-log4rs.yaml logs
$ ./create_account.py
kms create output: key_id:1,address:0x88b3fd84e3b10ac04cd04def0876cb513452c74e
$ ls
0x88b3fd84e3b10ac04cd04def0876cb513452c74e create_account.py kms kms-log4rs.yaml logs
$ ls 0x88b3fd84e3b10ac04cd04def0876cb513452c74e
key_file key_id kms.db node_address
0x88b3fd84e3b10ac04cd04def0876cb513452c74e
为账户地址。
key_id
和kms.db
分别保存了账户的id
和私钥,后续需要使用,所以先归档到以账户地址命名的文件夹中。
使用同样的方法,按照规划的节点数量,为每个节点都生成一个账户地址。
kms create output: key_id:1,address:0xbdfa0bbd30e5219d7778c461e49b600fdfb703bb
kms create output: key_id:1,address:0xdff342dadae5abcb4ca9f899c2168ab69f967c85
kms create output: key_id:1,address:0x914743835c855baf2f59015179f89f4f7f59e3ff
创建这三个节点账号时的密码,也要作为创建配置时的参数。
假设密码分别为:password0
,password1
,password2
。
$ ls
create_syncthing_config.py
$ ./create_syncthing_config.py
device_id: 536EVEY-MZPLRMI-XWOOAXV-OWMHHNC-ZSE25NQ-Z22TZIS-YKPTCKJ-ESBUUQW
$ ls
536EVEY-MZPLRMI-XWOOAXV-OWMHHNC-ZSE25NQ-Z22TZIS-YKPTCKJ-ESBUUQW create_syncthing_config.py
$ ls 536EVEY-MZPLRMI-XWOOAXV-OWMHHNC-ZSE25NQ-Z22TZIS-YKPTCKJ-ESBUUQW
cert.pem key.pem
536EVEY-MZPLRMI-XWOOAXV-OWMHHNC-ZSE25NQ-Z22TZIS-YKPTCKJ-ESBUUQW
为生成的device id
。
cert.pem
和key.pem
为对应的证书文件,后续需要使用,所以先归档到以device id
命名的文件夹中。
使用同样的方法,按照规划的节点数量,为每个节点都生成一个device id
。
device_id: NVSFY4A-Z22XP3J-WHA5GPL-AGFCVVA-IWECW3E-GE34T2O-3MUXT63-LTE6YQP
device_id: EROQJHV-QCEVWQB-F5ZD72M-ZEIRKGP-XLGJWBL-JQZ44AO-UO7NSWQ-7TK3HQJ
device_id: MWVAAOD-YGTHWBA-WG2BMRY-GCB5O5V-JR5JYRU-WL5YYEW-5CURT7W-4ZUVEQY
此处操作请咨询当前使用的云服务商。
以阿里云为例,创建之后会得到一个集群对外的ip
和一个形如lb-hddhfjg****
的LoadBalancerId
。
这里假设有三个集群,对外ip
分别为:cluster0_ip
,cluster1_ip
,cluster2_ip
;LoadBalancerId
分别为:lb-hddhfjg1234
,lb-hddhfjg2234
,lb-hddhfjg3234
。
每个节点有9个端口需要暴露到集群之外:
- 网络 40000
- syncthing 22000
- rpc 50004
- executor_call 50002
- monitor_process 9256
- monitor_exporter 9349
- executor_chaincode 7052
- executor_eventhub 7053
- debug 9999
所以需要预留连续的9个端口,然后将起始端口作为创建配置时的参数。
比如,预留端口为30000~30008,则要使用的参数为30000。
注意:根据配置参数的不同,其中部分端口背后的服务可能不会启动,但是端口依然会保留。
例如,预留端口为30000~30008,不开启monitor
的时候,30005和30006端口将不会使用,但是debug
对应的依然是30008,而不会往前顺延。
参见单集群的方法,或者咨询当前使用的云服务商,提前创建好pv/pvc
。
将每个节点对应的集群的pvc name
作为创建配置时的参数。
这里假设有三个集群,pvc name
分别为:cluster0_pvc
,cluster1_pvc
,cluster2_pvc
。
使用前述准备工作中准备好的信息生成配置文件。
注意:三个集群的各项信息,其顺序一定要保持一致。
$ ./create_k8s_config.py multi_cluster --authorities 0xbdfa0bbd30e5219d7778c461e49b600fdfb703bb,0xdff342dadae5abcb4ca9f899c2168ab69f967c85,0x914743835c855baf2f59015179f89f4f7f59e3ff --nodes cluster0_ip,cluster1_ip,cluster2_ip --lbs_tokens lb-hddhfjg1234,lb-hddhfjg2234,lb-hddhfjg3234 --sync_device_ids NVSFY4A-Z22XP3J-WHA5GPL-AGFCVVA-IWECW3E-GE34T2O-3MUXT63-LTE6YQP,EROQJHV-QCEVWQB-F5ZD72M-ZEIRKGP-XLGJWBL-JQZ44AO-UO7NSWQ-7TK3HQJ,MWVAAOD-YGTHWBA-WG2BMRY-GCB5O5V-JR5JYRU-WL5YYEW-5CURT7W-4ZUVEQY --kms_passwords password0,password1,password2 --node_ports 30000,30000,30000 --pvc_names cluster0_pvc,cluster1_pvc,cluster2_pvc --super_admin 0x88b3fd84e3b10ac04cd04def0876cb513452c74e
$ ls
cita-cloud test-chain-0.yaml test-chain-1.yaml test-chain-2.yaml
生成的cita-cloud
目录结构如下:
$ tree cita-cloud
cita-cloud
└── test-chain
├── node0
├── node1
├── node2
三个yaml
文件分别是用于部署对应节点到k8s
集群的配置文件。
上面生成的配置文件并不完整,还需要将准备阶段归档的文件拷贝进去补充完整。
节点0对应的账户为0xbdfa0bbd30e5219d7778c461e49b600fdfb703bb
,因此需要将创建该账号时归档的node_address
,key_id
和kms.db
三个文件拷贝到cita-cloud/test-chain/node0/
下。
节点0对应的device id
为NVSFY4A-Z22XP3J-WHA5GPL-AGFCVVA-IWECW3E-GE34T2O-3MUXT63-LTE6YQP
。因此需要将创建该device id
时归档的cert.pem
和key.pem
两个文件拷贝到cita-cloud/test-chain/node0/config/
下。
其他两个节点采用同样的操作进行处理。
将三个节点配置文件夹分别下发到对应集群的NFS
服务器上,但是注意要保持三层目录结构不变。
在三个k8s
集群中,分别应用对应节点的yaml
文件,启动节点。