etcdを用いたLNDクラスタを構築する
日本ビットコイン産業株式会社 R&D事業部・ライトニング事業部の押川拓夢です。
本記事ではLNDのetcd機能を用いてリーダー選出、DB共有、フェイルオーバーを実現するLNDクラスタの構築手順を解説します。
Lightningノードは、常にオンラインで稼働している必要がある一方で、一般的なサービスのような単純な冗長化が難しいです。
その理由の一つとして、一般的なサービスでは複数DB立てて定期的にバックアップをとる冗長化を行いますが、LNでは古いデータでノードを起動した時、LNプロトコルの仕様によりプロトコル違反の不正な行為と見なされてLNチャネルにロックしたデータを全て没収されてしまう可能性があります。
つまりバックアップでノードを再起動した場合、少しでも最新のデータとズレがあれば資金を失うリスクがあります。
Lightning Networkの可用性を高めるために、LNDでは etcdをバックエンドとしたクラスタ構成 を実験的にサポートさしています。
etcdとは?:何ができるようになるか

上のGIFではLNDを3台のホストで起動し、1台がダウンすると他のホストでノードが動き出しています。(見づらくてすみません)
etcdは、Raftコンセンサスアルゴリズムを用いて動作する分散型のキー・バリュー型データベースです。複数ノードでクラスタを構成し、Raftによってリーダーを選出しながらデータの更新を管理することで、全ノード間で強い一貫性を保ちます。そのため、ノードの一部に障害が発生してもデータの整合性を維持したまま動作を継続できるのが特徴です。
LNDでは、このetcdを利用することでデータベースの共有とLeader electionを実現し、ノードのフェイルオーバーを可能にします。
⚠️注意
LNDにおいてetcd機能は実験的機能であり、将来的に削除される可能性もあります。
本格運用しているノードで試すのは絶対にオススメしません。あくまで遊びとして試してみることをお勧めします。
問題が発生したとしても責任は取れません。
構築環境
筆者は以下のような構成で構築しました。
もちろんラズパイではなく仮想化環境を用いて同様のことが可能ですが、筆者は電源をぶっこぬいても動作し続けますというような実演をしたかったので、ラズパイを使っています。


確ホストで以下の環境を構築します。

1. etcdクラスタ構築
etcdは単一ノードではなく最低3ノードのクラスタ で構成します。
以下の手順を各ホストで実行してください。
インストール(全ノード)
wget https://github.com/etcd-io/etcd/releases/download/v3.5.12/etcd-v3.5.12-linux-arm64.tar.gz
tar xvf etcd-v3.5.12-linux-arm64.tar.gz
cd etcd-v3.5.12-linux-arm64
sudocp etcd etcdctl /usr/local/bin/
systemd設定(例:node1)
etcdをsystemdで起動できるように設定します。
sudo vim /etc/systemd/system/etcd.service
[Unit]
Description=etcd
After=network.target
[Service]
User=etcd
Type=notify
ExecStart=/usr/local/bin/etcd \
--name node1 \
--data-dir /var/lib/etcd \
--listen-client-urls http://127.0.0.1:2379,http://192.168.10.20:2379 \
--advertise-client-urls http://192.168.10.20:2379 \
--listen-peer-urls http://192.168.10.20:2380 \
--initial-advertise-peer-urls http://192.168.10.20:2380 \
--initial-cluster node1=http://192.168.10.20:2380,node2=http://192.168.10.21:2380,node3=http://192.168.10.22:2380 \
--initial-cluster-state new \
--initial-cluster-token etcd-cluster-1 \
--max-txn-ops=16384 \
--max-request-bytes=104857600
Restart=always
RestartSec=5
[Install]
WantedBy=multi-user.target
ポイント
2379: クライアント用(LNDが接続)2380: etcdノード間通信initial-cluster: 全ノードで一致させる- transaction制限を拡張している
起動
sudo systemctl daemon-reload
sudo systemctl enable etcd
sudo systemctlstart etcd
確認
etcdctl endpoint health
2. LND環境構築
以下の手順を各ホストで実行してください。
LNDインストール&ビルド
通常のLNDのビルドと同じですが、kvdb_etcdのオプションを有効化します。
git clone https://github.com/lightningnetwork/lnd.git
cd lnd
git checkout v0.20.1-beta
maketags="kvdb_etcd"
sudo install-m0755 lnd lncli /usr/local/bin/
LND設定
LNDの設定は通常 lnd.conf に記述します。
しかし今回の環境では、なぜかlnd.conf に書いた etcd / cluster 設定が正しく反映されず、詰まりました。
そのため、systemdのExecStartで直接指定することで対応しました。(ゴリ押し)
[Unit]
Description=LND Lightning Network Daemon
Wants=bitcoind.service
After=bitcoind.service network.target
[Service]
User=bitcoin
Group=bitcoin
Type=simple
ExecStart=/usr/local/bin/lnd \
--configfile=/home/bitcoin/.lnd/lnd.conf \
--db.backend=etcd \
--db.etcd.disabletls \
--db.etcd.host=192.168.10.20:2379 \
--cluster.enable-leader-election \
--cluster.leader-elector=etcd \
--cluster.etcd-election-prefix=/leader/ \
--cluster.id=node1
Restart=on-failure
RestartSec=10
TimeoutStartSec=120
NoNewPrivileges=true
PrivateTmp=true
ProtectSystem=full
ProtectHome=false
PrivateDevices=true
MemoryDenyWriteExecute=true
LimitNOFILE=128000
[Install]
WantedBy=multi-user.target
設定の意味
- etcdをDBとして使用
- Leader electionを有効化
- etcd上にleader情報を保存
ノードごとの差分
ノードごとに変更するのは以下のみ:
-db.etcd.host-cluster.id
例:
node1 →192.168.10.20 / node1
node2 →192.168.10.21 / node2
node3 →192.168.10.22 / node3
起動
各ホストのノードを起動します。
sudo systemctl daemon-reload
sudo systemctl enable lnd
sudo systemctl start lnd
リーダー選出確認
ログを確認し、walletの作成・アンロックを求められているノードが一つあるはずです。そのノードがリーダーノードです。
リーダーノードのログ:

その他ノード(フォロワー)のログ:

3. 動作確認:フェイルオーバー確認
リーダーノードを停止し、他のノードにリーダーが移ることを確認します。
sudo systemctl stop lnd
以下の動画では、3台のノードがスタンバイし、左のノードがリーダーの状態でスタートしています。

- 左ノードでWalletアンロック → ブロック同期開始
- 左ノードを停止 → 真ん中のノードがリーダー昇格
- 真ん中のノードでWalletアンロック → ブロック同期開始
- 真ん中ノードを停止 → 右のノードがリーダー昇格
- 右のノードでWalletアンロック → ブロック同期開始
3台ともダウンするまで生きる冗長化されたLNDが動作していることを確認できました。
ノードの外部公開時注意点
また、それぞれのLNDノードが別のIPアドレスで動いていると、それぞれのLNDノードに対してピアを張る必要があり、冗長化の意味が薄れます。
そのため、同一のオニオンアドレス設定する、同一のVPSのIPをextarnalipに設定するなどが必要になります。
まとめ
etcdを用いることで:
- LNDのActive/Standby構成
- リーダー選出
- DB共有
が実現できます。
おわりに
構築にはドキュメントが少なく、結構苦戦しました。
Spotlightが残念ながら動画をそのまま載せられないのでGIFにしましたが見にくいと思います、、、。
今後も実験的に動作させて、どのような問題が発生するのかを継続的に観察してみようと思います。




