Блокчейн-ноды делятся на две роли - валидатор-ноды и api-ноды. Валидатор-ноды производят блоки, но не отвечают на запросы к API. API-ноды отвечают на запросы к API, но не производят блоки. См документацию по substrate:
By default the node will refuse to start if you try to expose RPC and run a
validator node at the same time.
Может быть только одна активная валидатор-нода (запущенная с флагом --validator). Другие валидатор-ноды должны быть запущены без флага --validator. Они только синхронизируются, но не производят блоки, находясь в резерве. В случае отказа активной валидатор-ноды, надо провести failover, запустив одну из неактивных нод с флагом --validator.
API-ноды синхронизируются с валидаторами и дают доступ к API. Две api-ноды нужны для high availability - если одна откажет, то вторая продолжит работать.
Блокчейн не обязательно должен быть high available все время. У каждого сервиса который пишет в блокчейн есть своя база данных в которую идет синхронная запись, и информация из которой eventually копируется в блокчейн. Поэтому короткие остановки блокчейна терпимы.
На каждой машине должен быть открыт следующий порт для входящего траффика:
- 30333 (p2p-протокол между нодами)
Этот порт должен быть доступен для других нод, но не доступен из интернета.
На API нодах также должны быть открыты и доступны для load-балансера следующие порты:
- 9933 (http-интерфейс)
- 9944 (websocket-интерфейс)
На валидатор-нодах порты 9933 и 9944 должны быть ЗАКРЫТЫ для входящего траффика.
Все API-ноды запускаются с одинаковой конфигурацией.
Все валидаторы запускаются с одинаковой конфигурацией, за исключением одного параметра.
Одна из нод-валидаторов является boot-нодой и служит для peer discovery других нод (как api- так и валидатор-). Boot-ноде при запуске передается ее секретный private key (node-key). Другим двум нодам передается адрес бут-ноды, включая ее публичный ключ.
Перед запуском валидатор-ноды, ей в keystore надо добавить ее приватный ключ (отмечу, что это не node-key, о котором шла речь выше, а другой ключ). Без добавления ключа она не может производить блоки.
Для доступа к вебсокет- и http- интерфейсам должен быть настроен nginx как прокси. Nginx должен проксировать API-ноды в режиме ip_hash, то есть запросы с одного ip-адреса должны всегда идти на одну и ту же ноду. Nginx должен давать https доступ с использованием следующих адресов:
https://blockchain-ws.coldstack.io
для ws (proxy_pass на порт 9944)https://blockchain-rpc.coldstack.io
для http (proxy_pass на порт 9933)
В случае ws nginx должен быть настроен как ws proxy. Кажется, для этого достаточно такой конфигурации, но я не тестировал это тщательно:
location / {
proxy_pass http://host:9944;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
Для стейждинга аналогично, только домен coldstack.io
меняется на домен, на
котором развернут стейджинг.
Тут пока не окончательная информация.
Вероятно для бэкапа нужно завести отдельную ноду, которая не будет участвовать в производстве блоков, а будет только синхронизироваться с другими нодами. Для бэкапа надо останавливать эту ноду, снимать бэкап и запускать снова.
See https://substrate.dev/docs/en/tutorials/visualize-node-metrics/
Для разворачивания описанного кластера нод используется скрипт
./deploy/deploy.py
Его надо запускать из-под SSH-агента, так как он выполняет много операций по SSH, и было бы непрактично все время вводить пароль.
На вход скрипту подаются SSH-адреса нод. Надо чтобы пользователь, из-под которого выполняется ssh-логин, имел sudo права.
На машинах на которых разворачивается блокчейн должен быть установлен docker.
Скрипт ./deploy/cleanup.py
откатывает деплоймент и удаляет все данные
блокчейна.
Пример запуска скрипта:
./deploy/deploy.py \
--validator-node stage-bc-validator-1 stage-bc-validator-2 \
--api-node stage-bc-api-1 stage-bc-api-2 \
--boot-node-addr 52.77.253.1 \
--secrets deploy/secrets/staging.json \
--env stage
Аргументы:
-
validator-node
- список SSH-хостов, на которых разворачиваются ноды в режиме валидатора -
api-node
- список SSH-хостов, на которых разворачиваются ноды в режиме API-ноды -
boot-node-addr
- адрес первой валидатор-ноды. Он будет указан в качестве аргумента для других нод. -
env
-stage
илиprod
-
secrets
- файл с секретами.
Разберем подробно файл с секретами. Этот файл можно сгенерировать скриптом
./deploy/gen-secrets.py
. Для стейджинга я сгенерировал этот файл и положил в
./deploy/secrets/staging.json
. Для продакшена этот файл должен храниться
как-то более секьюрно.
Рассмотрим структуру файла с секретами:
-
authorities
- списокauthorities
блокчейна, которые участвуют в создании блоков. У нас используется единственная authority. Authority - это passphrase из которой выводится ее приватный ключ. -
sudo
- passphrase аккаунта, который используется для некоторых специальных транзакций блокчейна, например для runtime upgrades. -
admin
- passphrase административного аккаунта, который имеет особые права в нашем блокчейне. Например, он способен выдавать привилегии file-и billing-ноды.
Вышеперечисленные поля используются при генерации нулевого блока блокчейна (так
называемый chain spec). Его можно сгенерировать скриптом
./chainspec/create_chainspec.py
. Для стейджинга я сгенерировал chainspec и
положил в ./chainspec/staging/chainspecRaw.json
. Впоследствии надо будет
сгенерировать chainspec-файл для продакшена. При сборке докер-образа
chainspec-файл добавляется в докер-образ (см ./Dockerfile
) и его можно
указывать в качестве аргумента для параметра --chain
при запуске ноды.
После запуска блокчейна, эти параметры невозможно поменять, так как они зашиты в нулевом блоке.
Кроме того, в secrets-файле есть менее важные параметры, которые не входят в chainspec и которые можно менять в процессе эксплуатации блокчейна.
-
nodekey
- секретный ключ бут-ноды. Он нужен чтобы другие ноды могли проверить подлинность бут-ноды. -
peer_id
- адрес буд-ноды, который выводится из ее секретного ключа. Он указывается в качестве аргумента при запуске других (отличных от бут-ноды) нод.
При деплое используются следующие параметры из secrets-файла: authorities
,
nodekey
, peer_id
. nodekey
передается как аргумент бут-ноде. peer_id
передается в качестве аргумента другим (не бут-) нодам. authorities
ключ
добавляется в keystore валидатор-нодам.
Для healthcheck можно использовать скрипт ./deploy/healthcheck.py
. Ему
передается адрес api-ноды. Он проверяет что API работает, и блокчейн производит
блоки.
Для скрипта нужен пакет substrate-interface
:
pip3 install substrate-interface
Вместе с блокчейном надо развернуть админку. Она представляет собой статический js-сайт.
Мне кажется, проще всего ее деплоить докером. По ссылке есть документация по деплойменту. Фрагмент докер-компоуз файла:
polkadot-js-app:
image: jacogr/polkadot-js-apps
ports:
- 80:80
environment:
- WS_URL=wss://blockchain-ws.coldstack.io
Она должна быть доступна по адресу https://blockchain-admin.coldstack.io
. Для
стейджинга адреса такие же с точностью до домена второго уровня.
http-сервер для healthcheck API-ноды находится тут ./deploy/rpc_healthcheck/.
Он собирается в докер-образ в github workflows. Название образа:
ghcr.io/coldstack-network/blockchain_rpc_healthcheck
ENV-переменные контейнера
- PORT - порт на котором запускается http-сервер
- NODE_URL - URL ws-интерфейса API-ноды