* Validator를 운영하기 위한 개발 공부를 위해 쓰는 글입니다. 스테이킹을 하시려면 솔플레어나 팬텀 웹지갑을 만들어 이미 존재하는 Validator 중 가장 신뢰가 가는 곳에 스테이킹하시면 됩니다. Validator 운영에는 매우 높은 서버 스펙이 필요하고, 일반 가정에서는 운영하기 다소 힘들 것으로 보입니다.
* CLI 도구가 없다면 먼저 설치해야 합니다. 아래 글을 참고해주세요.
Solana CLI 구성
솔라나 cli는 자동으로 --url argument를 자동으로 설정하는 get 과 set 구성 커맨드가 포함되어 있다.
solana config set --url http://api.devnet.solana.com
위는 devnet 클러스터에 연결하는 방법에 대한 예시다.
다른 솔라나 클러스터로 하고 싶은 경우 데브넷 자리에 mainnet-beta, testnet을 입력하면 된다.
클러스터에 연결이 가능한지 확인
validator 노드에 연결하기 전에 트랜잭션 수를 가져와 클러스터가 시스템에 액세스할 수 있는지 확실히 확인하자.
solana transaction-count
설치 확인
다음 커맨드를 실행해 가십 네트워크에 참여하고 클러스터의 모든 노드를 보자.
solana-gossip spy --entrypoint entrypoint.devnet.solana.com:8001
# Press ^C to exit
그랬더니 다음과 같은 에러가 떴다 :
dyld: Library not loaded: /usr/local/opt/openssl@1.1/lib/libssl.1.1.dylib
Referenced from: ~~~
검색해보니 MacOS를 사용하면 자주 겪는 라이브러리 관련 오류인가 보더라.
맥만 해당될 것 같으니 해결하는 과정은 밑에 접어놓겠다.
이 에러를 해결하기 위해 우선 homebrew를 설치했다.
위 사이트에서 메인의 코드를 복사해 넣으면 된다.
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
sudo 액세스를 확인한다고 비밀번호를 입력하라 해서 맥 로그인에 사용하는 비번을 입력했다.
엔터를 누르니 한참 설치가 진행됐다.
homebrew로 프로그램 설치하기 전에 cask 라는 패키지를 먼저 설치해야 그래픽 작업 프로그램 설치할 수 있다고 해서 cask도 설치했다.
brew install cask
설치가 완료되면 brew list 로 cask가 설치됐는지 확인한다.
프로그램 설치 전에는 항상 brew update로 꾸준히 업데이트를 해주자.
brew list
brew update
이제 우리에게 필요한 openssl 패키지를 설치해보자.
brew install openssl@1.1
나는 아래의 에러가 떴다.
Warning: openssl@1.1 1.1.1l_1 is already installed and up-to-date.
To reinstall 1.1.1l_1, run:
brew reinstall openssl@1.1
이 경우 심볼릭 링크를 직접 추가해주면 된다.
ln -s /usr/local/opt/openssl/lib/libssl.1.1.dylib /usr/local/lib/
ln -s /usr/local/opt/openssl/lib/libcrypto.1.1.dylib /usr/local/lib
이제 하려던 실행을 다시 하면 된다. 경우에 따라 터미널을 껐다 켜야될 수도 있다고 한다.
에러를 고치고 다시 가십 네트워크에 커맨드를 입력하니 클러스터의 노드들이 나왔는데.... 끊임 없이 나와서 중간에 끊었다.
CUDA 활성화
머신에 CUDA가 설치된 GPU가 있는 경우(현재 리눅스 전용), --cuda argument를 solana-validator에 포함하자.
validator가 시작되면 CUDA가 활성화되었음을 나타내는 다음의 로그 메시지를 찾자 :
"[<timestamp> solana::validator] CUDA is enabled"
CUDA는 GPU의 가상 명령어셋을 사용할 수 있도록 해주는 소프트웨어 레이어이며, NVIDIA가 만든 CUDA 코어가 장착된 GPU에서 작동된다. 시스템에서 GPU를 사용하는 데 필요하다고 하는데, 꼭 필요한건지는 써봐야 알 것 같다.
시스템 튜닝
리눅스
자동
솔라나 리포지토리에는 성능을 최적화(OS UDP 버퍼 증가, 파일 매핑 제한 증가)하기 위해 시스템 설정을 조정하는 데몬이 포함돼있다.
데몬(solana-sys-tuner)은 솔라나 바이너리 릴리스에 포함돼있다.
우리 validator를 재시작해야할 때, 각 소프트웨어에 최신 권장 설정이 적용되게 업그레이드하고 난 후 재시작하자 :
sudo $(command -v solana-sys-tuner) --user $(whoami) > sys-tuner.log 2>&1 &
매뉴얼
시스템 설정을 직접 관리할 수도 있다.
UDP 버퍼를 증가시키고, 메모리 매핑된 파일의 제한을 증가시키는 방법 등이 있지만 생략하겠다.
위에 링크한 솔라나 문서 페이지에서 볼 수 있다.
아이디 생성
내 validator의 id keypair를 만들자.
이 때 키페어를 파일로 만들 수도 있고, 보안을 위해 파일화하지 않는 방법이 있다.
파일화를 하면 개인키가 들어있는 파일이 만들어지기 때문에 키페어 자리에 파일경로를 넣을 수 있어 작업이 간편해진다.
파일화를 하지 않으면 키페어를 입력해야하는 자리에 prompt:// 를 넣고 매번 시드와 암호를 넣어줘야 한다.
메인넷에 올리려면 파일화를 하지 않아야 하고, 테스트넷이나 데브넷에 테스트용으로 올릴 때는 파일화 해서 쓰는 것이 더 편할 것이다.
실제 vallidator 들은 더 안전하고 간편하도록 하드웨어 지갑으로 키페어를 사용하지 않을까 싶다.
파일 시스템 지갑 id
다음으로 키페어 파일을 만들 수 있다 :
solana-keygen new -o ~/validator-keypair.json
bip39 암호를 입력하라고 한다. 나는 그냥 이 사이트에서 만들어서 했다.
나온 시드와 bip39, pubkey를 따로 저장해두자.
참고로 파일의 pubkey는 다음 커맨드로 조회할 수 있다.
solana-keygen pubkey ~/validator-keypair.json
참고 : validator-keypair.json 파일은 (ed25519) 개인키 이기도 하다.
종이 지갑 id
다음으로 키페어 파일을 디스크에 쓰지 않고 id 파일에 대한 종이 지갑을 만들 수 있다 :
solana-keygen new --no-outfile
다음을 실행해 해당 id 공개키를 볼 수 있다.
solana-keygen pubkey ASK
그리고 내 시드 문구를 입력한다.
자세한 내용은 공식 문서 내 종이 지갑 사용 파트를 참조하자.
가상 키페어(vanity keypair)
solana-keygen을 사용해 공개키를 커스텀해서 vanity 키페어를 생성할 수 있다.
키페어를 생성할 때 pubkey 맨앞부분, 맨뒷부분 등에 올 문자+숫자를 정해서 생성할 수 있다.
이렇게 생성한 공개키는 홍보용으로 쓰기 좋을 것이다.
아래 명령문을 치면 더 많은 옵션을 볼 수 있다.
solana-keygen grind --help
가상 키페어 생성 예시 :
solana-keygen grind --starts-with cod:1
--starts-with 뒤에 오는 것은 [접두사:생성할 pubkey 개수]로 생각하면 된다.
짧게 칠수록 가능한 키페어를 빨리 찾아준다.
참고로 pubkey 주소에는 0이 못 들어가는 모양이다.
접두사를 'coding'처럼 길게 치니까 몇분동안 가능한 키페어를 못 찾았다. 그래서 접두사를 좀 줄여봤다.
solana-keygen grind --starts-with c1d:1
세글자는 금방 찾아서 만들어줬다. 네글자부터만 해도 몇분동안 못 찾아서 그냥 종료했다(Ctrl+c).
아래처럼 --use-mnemonic 명령문을 치면 bip39 암호 구문(선택)으로 표현하도록 요청할 수 있다.
단, mnemonic 없이 grinding 하는 것보다 훨씬 느리다. 요청한 문자열에 따라 일치하는 항목을 찾는 데 며칠이 걸릴 수도 있다.
solana-keygen grind --use-mnemonic --starts-with c1d:1
해보니까 몇분동안 키페어 찾아봤다는 한 줄도 못 띄우던데 테스트 시에는 사용하지 않는 게 나을 것 같다.
현재 메인넷의 스테이킹 1위, 3위 validator는 이 커맨드를 이용해 찾은 해시로 위처럼 공개키와 투표계정 주소를 만든 것 같더라.
validator id keypair는 네트워크 내에서 validator를 고유하게 식별하므로 키페어를 잘 백업해놓아야 한다.
키페어를 백업 해놓지 않으면 액세스 권한을 잃었을 경우 validator를 복구할 수 없다. 당연히 할당받았던 SOL도 잃게 된다.
키페어 파일이나 시드 구문과 암호를 안전한 위치에 잘 백업해놓자.
Solana CLI 추가 구성
이제 키페어가 있으므로, 모든 명령에 대해 validator 키페어를 사용하도록 솔라나 구성을 설정할 수 있다.
앞으로의 커맨드에 적용될 키페어를 validator-keypair.json으로 설정하는 커맨드다.
solana config set --keypair ~/validator-keypair.json
다음처럼 내용이 출력되면 제대로 설정된 것이다.
Config File: /home/solana/.config/solana/cli/config.yml
RPC URL: http://api.devnet.solana.com
WebSocket URL: ws://api.devnet.solana.com/ (computed)
Keypair Path: /home/solana/validator-keypair.json
Commitment: confirmed
에어 드랍 & validator 잔액 확인
시작하기 위해 직접 SOL을 에어드랍한다 :
solana airdrop 1
나는 위에서 기본으로 적용되는 키페어를 validator-keypair 파일로 정해놨기 때문에 validator 계정의 잔액이 보여진다.
에어드랍은 데브넷과 테스트넷에서만 가능하며, 요청당 1 SOL로 제한된다.
현재 잔액을 보려면 :
solana balance
solana balance --lamports //소수점 단위를 더 자세히 볼 수 있음
1 SOL == 10^9 lamports 다. 아주 작은 소수 단위까지 오차없이 계산해야할 때 사용하자.
승인된 인출 계정 생성
(아직 만들지 않았을 경우 만들기)
validator의 최종권한으로, 승인된 인출 키페어를 만들자.
이 키페어는 투표 계정에서 인출 권한을 가지며, 투표 계정의 다른 모든 측면을 변경할 수 있는 추가 권한을 가진다.
그리고 소유한 사람이 영구적으로 소유권을 갖는 것을 포함해 투표 계정을 변경할 수 있기 때문에 매우 중요한 키페어다.
그러므로 꼭 안전한 곳에 보관해야 한다. validator에 저장해야 하는 것이 아니고, 승인되지 않은 당사자가 액세스할 수 없는 위치에 저장해야 한다.
solana-keygen new -o ~/authorized-withdrawer-keypair.json
bip39 암호도 넣자.
투표 계정 생성
(아직 만들지 않았을 경우 만들기)
투표 계정 키페어를 만들고 네트워크에서 투표 계정을 만들자.
solana-keygen new -o ~/vote-account-keypair.json
solana create-vote-account ~/vote-account-keypair.json ~/validator-keypair.json ~/authorized-withdrawer-keypair.json
알려진 Validator
믿을만한 validator operator를 알고 있다면, solana-validator 에 인수로 --known-validator <PUBKEY> 인수를 사용해 명령문에서 지정할 수 있다. 이 때 --known-validator <PUBKEY1> --known-validator <PUBKEY2> 처럼 인수를 반복함으로써 여러 validator를 지정할 수도 있다.
이는 2가지 효과가 있다.
- validator를 --only-known-rpc 와 함께 부팅하면 제네시스 및 스냅샷 데이터를 다운받을 때 알려진 노드 집합만 요청할 수 있다.
- --halt-on-known-validators-accounts-hash-mismatch 옵션을 함께 사용하면, 가십에서 다른 알려진 노드 전체 계정의 머클루트 해시를 모니터링하고 해시가 어떤 불일치를 생성하면 validator가 잠재적으로 잘못된 상태 값에 투표하거나 처리하지 못하도록 노드를 중지한다.
* 공식 문서에는 다르게 나와있는데, known-validator 여러개도 가능하다는 것을 직관적으로 표현하여 업데이트가 된 것 같다.
* 옵션이라고 했지만, 사실상 [FLAGS]기 때문에 [OPTIONS]에 포함되는 known-validator보다 먼저 와야 한다. 자세한 내용은 solana-validator --help를 통해 확인할 수 있다.
현재 validator가 해시를 게시하는 슬롯은 스냅샷 간격과 연관되어 있다. 기능을 제대로 하려면 알려진 세트의 모든 validators가 같은 스냅샷 간격 값 또는 그 배수로 설정돼야 한다.
악의적인 스냅샷 상태의 다운로드나 계정 상태 차이를 방지하려면 이런 옵션을 사용하는 것이 좋다.
Validator 연결
다음을 실행해 클러스터에 연결할 수 있다 :
solana-validator \
--identity ~/validator-keypair.json \
--vote-account ~/vote-account-keypair.json \
--rpc-port 8899 \
--entrypoint entrypoint.devnet.solana.com:8001 \
--limit-ledger-size \
--log ~/solana-validator.log
validator가 콘솔에 로그를 남기도록 강제하려면 --log - 인수를 추가하면 된다. 추가하지 않으면 자동으로 파일에 로그를 남길 거다.
원장은 ledger/ 경로에 배치되며 --ledger 인수를 사용해서 다른 위치를 지정할 수 있다.
생성된 ledger 폴더 안에는 다음의 빈 폴더들과 파일들이 있었다.
참고:
--identity 및/또는 --authorized-voter 키페어에 종이지갑 시드문구를 사용할 수 있다. 이를 사용하려면 해당 인수를
solana-validator --identity ASK ... --authorized-voter ASK ... 로 전달하면 시드 구문과 bip39 암호 구문(선택)을 입력하라는 메시지가 표시된다.
새 터미널을 열고 다음을 실행해 validator가 네트워크에 연결돼있는지 확인할 수 있다 :
solana gossip
validator가 연결되면 공개키와 IP주소가 목록에 나타난다.
나는 이런 식으로 65개의 노드가 나왔다. --rpc-port 8899 로 8899 포트에서 JSON RPC를 활성화한 상태다.
로컬 네트워크 포트 할당 제어하기
기본적으로 validator는 8000-10000 범위에서 사용 가능한 네트워크 포트를 동적으로 선택하며, --dynamic-port-range로 재정의할 수 있다. 예를 들어, solana-validator --dynamic-port-range 11000-11010 ... 는 validator가 포트 11000-11010 포트만 사용할 수 있도록 제한할 것이다.
디스크 공간을 절약하기 위해 원장 크기 제한하기
--limit-ledger-size 매개변수는 내 노드가 얼마나 많은 원장 조각을 디스크에 유지할지를 지정할 수 있다. 이 매개변수를 포함하지 않으면 validator는 디스크 공간이 부족해질 때까지 전체 원장을 유지할 것이다.
설정된 기본값은 원장 디스크 사용량을 500GB 미만으로 유지하려고 한다.
디스크 사용량을 더 많거나 적게 하려면 --limit-ledger-size에 인수를 추가해서 요청해야 한다.
그런데 원장 크기를 제한하는 단위가 바이트가 아닌 <SHRED_COUNT> 다.
* shred는 블록의 일부로, validator 간에 전송되는 가장 작은 단위다
제한 용량을 커스텀하려면 위의 코드를 참고하면 된다고 한다.
계산해보니까 400 GB에 200m shred라고 하니 1 TB에는 500m~ 530m shred 정도 잡으면 되지 않을까 싶다.
Systemd 유닛
Validator를 systemd 유닛으로 실행해서 백그라운드에서의 실행을 쉽게 관리할 수 있다.
컴퓨터에서 유저명이 sol이라고 가정할 때, 다음을 사용해 /etc/systemd/system/sol.service 파일을 만들자 :
[Unit]
Description=Solana Validator
After=network.target
Wants=solana-sys-tuner.service
StartLimitIntervalSec=0
[Service]
Type=simple
Restart=always
RestartSec=1
User=sol
LimitNOFILE=1000000
LogRateLimitIntervalSec=0
Environment="PATH=/bin:/usr/bin:/home/sol/.local/share/solana/install/active_release/bin"
ExecStart=/home/sol/bin/validator.sh
[Install]
WantedBy=multi-user.target
* 맥북은 systemd 폴더를 통해 시스템 데몬을 돌리는게 어떤 식으로 이루어지는 건지 잘 모르겠어서 여기부터 윈도우 환경에 우분투 20.04 LTS를 설치해서 했다.
이제 원하는 solana-validator 커맨드라인을 포함하도록 해서 /home/sol/bin/validator.sh를 만들자.
validator 프로세스를 시작할 때는 'exec' 명령이 사용돼야 한다.(i.e. exec solana-validator ...)
만약 'exec' 없이 사용하면 로그가 회전할 때마다 매번 logrotate가 validator를 종료하게 되므로 중요하다.
수동으로 /home/sol/bin/validator.sh를 실행하면 예상한대로 validator가 시작되는지 확인하자. 실행하기 전에 chmod +x /home/sol/bin/validator.sh로 실행 가능하게 하는 것도 잊지 말자.
다음을 사용해 서비스를 시작하자 :
$ sudo systemctl enable --now sol
Logging(로깅)
로그 출력 튜닝
Validator가 로그에 보내는 메세지는 RUST_LOG 환경변수로 제어할 수 있다.
세부사항은 env_logger Rust crate 문서에서 찾을 수 있다. (아래 링크)
로깅 출력이 줄어들면 나중에 발생하는 문제를 디버깅하기 어려울 수 있다.
팀에서 지원을 요청해야할 때 변경사항을 되돌리고 문제를 재현해야 도움이 제공될 수 있다.
로그 회전
--log ~/solana-validator.log로 지정된 Validator 로그 파일은 시간이 지남에 따라 매우 커질 수 있으므로 로그 회전을 구성하는 것이 좋다.
Validator 는 로그 회전이 가능하게 하는 기본 원시(primitive) USR1 신호를 받았을 때 로그 파일을 다시 연다.
Validator가 쉘 스크립트 래퍼에 의해 시작되는 경우, logrotate를 사용할 때 프로세스를 exec(exec solana-validator ...)로 시작하는 것이 중요하다. 이렇게 하면 USR1 신호가 validator의 프로세스 대신 스크립트의 프로세스로 보내져서 둘 다 종료되는 현상을 방지할 수 있다.
logrotate 사용
logrotate 설정의 예시로, validator가 sol.service 라는 시스템 서비스로 실행중이고 로그 파일을 /home/sol/solana-validator.log에 작성한다고 가정해보자 :
# Setup log rotation
cat > logrotate.sol <<EOF
/home/sol/solana-validator.log {
rotate 7
daily
missingok
postrotate
systemctl kill -s USR1 sol.service
endscript
}
EOF
sudo cp logrotate.sol /etc/logrotate.d/sol
systemctl restart logrotate.service
위에서도 말했지만, logrotate를 쓸 때는 솔라나 validator 프로세스를 시작하는 모든 스크립트에서 'exec'를 사용해 수행해야 한다(ex : exec solana-validator...). 그렇지 않으면 logrotate가 validator에 신호를 보낼 때 포함된 스크립트가 종료되고 validator 프로세스가 수행된다.
재시작 속도를 높이기 위해 포트 검사 비활성화
validator가 정상적으로 작동하면, solana-validator 커맨드라인에 --no-port-check 플래그를 추가해서 validator를 다시 시작하는 데 걸리는 시간을 줄일 수 있다.
CPU 사용량을 줄이기 위해 스냅샷 압축 비활성화
다른 Validator에게 스냅샷을 제공하지 않는 경우 스냅샷 압축을 비활성화해서 로컬 스냅샷 스토리지에 대한 디스크 사용량을 약간 늘리는 대신 CPU 로드를 줄일 수 있다.
solana-validator 커맨드라인 인수에 --snapshot-compression none 인수를 추가해서 validator를 다시 시작하면 된다.
SSD 마모를 줄이기 위해 계정 db의 스왑으로 스필오버가 있는 램디스크 사용
컴퓨터에서 RAM이 충분한 경우 tmpfs ramdisk를 사용해 계정 db를 저장할 수 있다.
* tmpfs : 가상 메모리 파일 시스템
tmpfs를 사용할 때 tmpfs 공간이 주기적으로 부족해지는 것을 방지하기 위해 컴퓨터에서도 스왑을 구성하는게 중요하다.
250 GB 스왑 파티션과 함께 300GB tmpfs 파티션이 권장된다고 한다.
구성 예시 )
- sudo mkdir /mnt/solana-accounts
- /etc/fstab에 tmpfs /mnt/solana-accounts tmpfs rw,size=300G,user=sol 0 0(내 validator가 user 'sol'에서 실행된다고 가정)를 포함하는 새로운 라인을 추가해서 300GB tmpfs 파티션을 추가한다.
<주의> /etc/fstab을 잘못 편집하면 컴퓨터가 더 이상 부팅되지 않을 수도 있다! - 최소 250GB의 스왑 공간을 생성한다.
- 이 지침의 나머지 부분에서 SWAPDEV 대신 사용할 장치를 선택하자. 빠른 디스크에서 250GB 이상의 여유 디스크 파티션을 선택하는 것이 가장 좋다. 불가능한 경우 sudo dd if=/dev/zero of=/swapfile bs=1MiB count=250KiB로 스왑파일을 만들고 sudo chmod 0600 /swapfile로 권한을 설정하고 지침의 나머지 부분에 대해 /swapfile을 SWAPDEV로 사용하자.
- sudo mkswap SWAPDEV로 스왑으로 사용할 장치를 포맷하자. - /etc/fstab에 SWAPDEV swap swap defaults 0 0를 포함하는 새 라인을 추가하자.
- sudo swapon -a로 스왑을 활성화하고 sudo mount /mnt/solana-accounts/로 tmpfs를 마운트하자.
- free -g 로 스왑이 활성화됐는지, mount 로 tmpfs가 마운트 됐는지 확인하자.
이제 solana-validator 커맨드라인 인수에 --accounts /mnt/solana-accounts 인수를 추가하고 validator를 다시 시작하자.
계정 인덱싱
클러스터에 채워진 계정 수가 증가함에 따라 getProgramAccounts 및 SPL 토큰 관련 요청과 같이 전체 계정 세트를 스캔하는 계정 데이터 RPC 요청이 제대로 수행되지 않을 수 있다.
Validator가 이런 요청들을 지원해야하는 경우, --account-index 매개변수를 사용해 키 필드로 계정을 인덱싱해서 RPC 성능을 크게 향상시키는 하나 이상의 인메모리 계정 인덱스를 활성화할 수 있다.
현재는 다음 매개변수 값들을 지원한다 :
- program-id : 소유 프로그램에 의해 인덱싱된 각 계정;
getProgramAccounts 로 사용 - spl-token-mint : 해당 토큰 Mint로 인덱싱된 각 SPL 토큰 계정.
- spl-token-owner : 토큰 소유자 주소로 인덱싱된 각 SPL 토큰 계정;
getTokenAccountsByOwner 및 spl-token-owner 필터를 포함하는 getProgramAccounts 요청에서 사용한다.
'Solana > Validator - 공부' 카테고리의 다른 글
[Solana] Validating - 5. 검증인 정보 게시 (0) | 2021.11.08 |
---|---|
[Solana] Validating - 4. 벨리데이터 모니터링 (0) | 2021.11.05 |
[Solana] Validating - 3. 스테이킹 (0) | 2021.11.05 |
[Solana] Validating - 2. 투표 계정 관리 (0) | 2021.11.02 |
[Solana] 솔라나 검증인(Validator) 실행 팁 (미디움) (0) | 2021.10.22 |