0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

CosmosをはじめとしてCosmos-SDKのノードを立てる際にドキュメントを見ているとCosmovisorを使えよって書いてあると思う。
アップグレードを自動で行ってくれる便利ツールってのは知ってるけどわざわざ使うのはめんどくさいな。仕組みもわかってないし、止まった時にどう対応すればいいかわからないし、なんて思っていることもあったが、出てから結構経って安定もしていると思うのでまとめてみる。

Cosmovisorとは

チェインのバイナリ(gaiadなど)を起動したりするデーモン。cosmovisorコマンド経由でgaiadなどを起動させる。チェインのアップグレードをログから検知すると新しいバイナリをDLしてアクティベーション時に自動で差し替えてくれる優れもの。(バイナリの自動DLは推奨されていないぞ)

Cosmos-sdkの一部になっていてリポジトリ内にあるのでちょっと探しずらい。
https://github.com/cosmos/cosmos-sdk/tree/main/tools/cosmovisor

インストール

ここを参考にやっていく。

Github ReleaseにバイナリがあるのでそれをDLしてもよいし、go installでやってもよいと。
go installはバイナリの場所を見失うので、今回は前者で行う。Releaseページからcosmovisorで検索してバイナリゲット。

DLして~/bin/に配置

cosvi@deroris:~/Downloads$ wget -q https://github.com/cosmos/cosmos-sdk/releases/download/cosmovisor%2Fv1.7.1/cosmovisor-v1.7.1-linux-amd64.tar.gz
cosvi@deroris:~/Downloads$ tar zxfv cosmovisor-v1.7.1-linux-amd64.tar.gz
CHANGELOG.md
README.md
cosmovisor
cosvi@deroris:~/Downloads$ cp cosmovisor ~/bin/
cosvi@deroris:~/Downloads$ cosmovisor version
cosmovisor version: (devel)
Error: failed to run version command: DAEMON_NAME is not set
DAEMON_HOME is not set
DAEMON_DATA_BACKUP_DIR must not be empty
  • cosmovisor run: 設定したバイナリを実行する。cosmovisor run start -> gaiad start
  • cosmovisor config: 現在の設定を表示する。設定は環境変数で渡すので、それの値がでる。

cosmovisorセットアップ

使用するバイナリを設定する。環境変数もしくはconfigファイルで渡す。前者がデファクトのようだ。

ENVを食わせてcosmovisor initコマンドを使うとディレクトリを掘ってくれる。試しにgaiadをDLして配置してもらう。

cosvi@deroris:~/Downloads$ wget -q https://github.com/cosmos/gaia/releases/download/v25.1.0/gaiad-v25.1.0-linux-amd64
cosvi@deroris:~$ mkdir -p ~/data/cosmoshub-testnet

export DAEMON_NAME=gaiad
export DAEMON_HOME=~/data/cosmoshub-testnet
export DAEMON_ALLOW_DOWNLOAD_BINARIES=true
export DAEMON_DOWNLOAD_MUST_HAVE_CHECKSUM=true

cosvi@deroris:~/Downloads$ cosmovisor init ./gaiad-v25.1.0-linux-amd64
5:15PM INF checking on the genesis/bin directory module=cosmovisor
5:15PM INF creating directory (and any parents): "/home/cosvi/data/cosmoshub-testnet/cosmovisor/genesis/bin" module=cosmovisor
5:15PM INF checking on the genesis/bin executable module=cosmovisor
5:15PM INF copying executable into place: "/home/cosvi/data/cosmoshub-testnet/cosmovisor/genesis/bin/gaiad" module=cosmovisor
5:15PM INF making sure "/home/cosvi/data/cosmoshub-testnet/cosmovisor/genesis/bin/gaiad" is executable module=cosmovisor
5:15PM INF checking on the current symlink and creating it if needed module=cosmovisor
5:15PM INF the current symlink points to: "/home/cosvi/data/cosmoshub-testnet/cosmovisor/genesis/bin/gaiad" module=cosmovisor
5:15PM INF cosmovisor config.toml created at: /home/cosvi/data/cosmoshub-testnet/cosmovisor/config.toml module=cosmovisor

cosvi@deroris:~/Downloads$ tree ~/data/cosmoshub-testnet/
/home/cosvi/data/cosmoshub-testnet/
└── cosmovisor
    ├── config.toml
    ├── current -> genesis
    └── genesis
        └── bin
            └── gaiad

5 directories, 2 files

config.tomlにENVは入っているので環境変数は捨てておく。

cosvi@deroris:~/Downloads$ cat ~/data/cosmoshub-testnet/cosmovisor/config.toml
daemon_home = '/home/cosvi/data/cosmoshub-testnet'
daemon_name = 'gaiad'
daemon_allow_download_binaries = true
daemon_download_must_have_checksum = true
daemon_restart_after_upgrade = true
daemon_restart_delay = 0
daemon_shutdown_grace = 0
daemon_poll_interval = 300000000
unsafe_skip_backup = false
daemon_data_backup_dir = '/home/cosvi/data/cosmoshub-testnet'
daemon_preupgrade_max_retries = 0
daemon_grpc_address = 'localhost:9090'
cosmovisor_disable_logs = false
cosmovisor_color_logs = true
cosmovisor_timeformat_logs = 'kitchen'
cosmovisor_custom_preupgrade = ''
cosmovisor_disable_recase = false

chainの初期設定

gaiadの設定をする。cosmovisor run init xxxとなる。

cosvi@deroris:~$ cosmovisor --cosmovisor-config ~/data/cosmoshub-testnet/cosmovisor/config.toml run init deroris-moniker --home ~/data/cosmoshub-testnet/
Error: invalid path: /home/cosvi/data/cosmoshub-testnet/data must be an existing directory: stat /home/cosvi/data/cosmoshub-testnet/data: no such file or directory

ディレクトリがないと言われるので作る。

cosvi@deroris:~$ tree ~/data/cosmoshub-testnet/
/home/cosvi/data/cosmoshub-testnet/
└── cosmovisor
    ├── config.toml
    ├── current -> genesis
    └── genesis
        └── bin
            └── gaiad

5 directories, 2 files
cosvi@deroris:~$ mkdir ~/data/cosmoshub-testnet/data
cosvi@deroris:~$ cosmovisor --cosmovisor-config ~/data/cosmoshub-testnet/cosmovisor/config.toml run init deroris-moniker --home ~/data/cosmoshub-testnet/
5:46PM INF running app args=["init","deroris-moniker","--home","/home/cosvi/data/cosmoshub-testnet/"] module=cosmovisor path=/home/cosvi/data/cosmoshub-testnet/cosmovisor/genesis/bin/gaiad
5:46PM INF starting the batch watcher loop module=cosmovisor
{
 "moniker": "deroris-moniker",
 "chain_id": "test-chain-TmRsc7",
 "node_id": "177215901472ab18a55b3d22a2b361811039ab8a",
 "gentxs_dir": "",
 "app_message": {
 
~~snip;

cosvi@deroris:~$ tree ~/data/cosmoshub-testnet/
/home/cosvi/data/cosmoshub-testnet/
├── config
│   ├── app.toml
│   ├── client.toml
│   ├── config.toml
│   ├── genesis.json
│   ├── node_key.json
│   └── priv_validator_key.json
├── cosmovisor
│   ├── config.toml
│   ├── current -> genesis
│   └── genesis
│       └── bin
│           └── gaiad
└── data
    └── priv_validator_state.json

7 directories, 9 files

testnetのgenesis.jsonとaddrbook.jsonをDL

cosvi@deroris:~$ curl -slo ~/data/cosmoshub-testnet/config/genesis.json https://raw.githubusercontent.com/cosmos/testnets/refs/heads/master/interchain-security/provider/provider-genesis.json


cosvi@deroris:~$ head ~/data/cosmoshub-testnet/config/genesis.json
{
  "genesis_time": "2023-02-02T20:31:48.773794586Z",
  "chain_id": "provider",
  "initial_height": "1",
  "consensus_params": {
    "block": {
      "max_bytes": "22020096",
      "max_gas": "-1",
      "time_iota_ms": "1000"
    },


cosvi@deroris:~$ wget -qO ~/data/cosmoshub-testnet/config/addrbook.json https://snapshots.polkachu.com/testnet-addrbook/cosmos/addrbook.json
# thanks Polkachu

cosvi@deroris:~$ tree ~/data/cosmoshub-testnet/
/home/cosvi/data/cosmoshub-testnet/
├── config
│   ├── addrbook.json
│   ├── app.toml
│   ├── client.toml
│   ├── config.toml
│   ├── genesis.json
│   ├── node_key.json
│   └── priv_validator_key.json
├── cosmovisor
│   ├── config.toml
│   ├── current -> genesis
│   └── genesis
│       └── bin
│           └── gaiad
└── data
    └── priv_validator_state.json

7 directories, 10 files

config/app.tomlのminimum-gas-pricesを設定する。
minimum-gas-prices = "0.25uatom"

1からsyncするのはつらいのでPolkachuのスナップショットを利用
https://polkachu.com/testnets/cosmos/snapshots

解凍するとこんな感じになる。

cosvi@deroris:~/Downloads$ tree ~/data/cosmoshub-testnet/ -L2
/home/cosvi/data/cosmoshub-testnet/
├── config
│   ├── addrbook.json
│   ├── app.toml
│   ├── app.toml~
│   ├── client.toml
│   ├── config.toml
│   ├── genesis.json
│   ├── node_key.json
│   └── priv_validator_key.json
├── cosmovisor
│   ├── config.toml
│   ├── current -> genesis
│   └── genesis
├── data
│   ├── 08-light-client
│   ├── application.db
│   ├── blockstore.db
│   ├── cs.wal
│   ├── evidence.db
│   ├── priv_validator_state.json
│   ├── snapshots
│   ├── state.db
│   └── tx_index.db
└── wasm
    ├── cache
    ├── exclusive.lock
    ├── state
    └── wasm

18 directories, 11 files

とりあえず起動してみる。

cosvi@deroris:~/Downloads$ cosmovisor --cosmovisor-config ~/data/cosmoshub-testnet/cosmovisor/config.toml run start --home ~/data/cosmoshub-testnet/
6:11PM INF running app args=["start","--home","/home/cosvi/data/cosmoshub-testnet/"] module=cosmovisor path=/home/cosvi/data/cosmoshub-testnet/cosmovisor/genesis/bin/gaiad
6:11PM INF starting the batch watcher loop module=cosmovisor
6:11PM INF starting node with ABCI CometBFT in-process module=server
6:11PM INF service start impl=multiAppConn module=proxy msg="Starting multiAppConn service"
6:11PM INF service start connection=query impl=localClient module=abci-client msg="Starting localClient service"
6:11PM INF service start connection=snapshot impl=localClient module=abci-client msg="Starting localClient service"
6:11PM INF service start connection=mempool impl=localClient module=abci-client msg="Starting localClient service"
6:11PM INF service start connection=consensus impl=localClient module=abci-client msg="Starting localClient service"

OK

cosvi@deroris:~$ curl -s localhost:26657/status | jq
{
  "jsonrpc": "2.0",
  "id": -1,
  "result": {
    "node_info": {
      "protocol_version": {
        "p2p": "8",
        "block": "11",
        "app": "0"
      },
      "id": "177215901472ab18a55b3d22a2b361811039ab8a",
      "listen_addr": "tcp://0.0.0.0:26656",
      "network": "provider",
      "version": "0.38.17",
      "channels": "40202122233038606100",
      "moniker": "deroris-moniker",
      "other": {
        "tx_index": "on",
        "rpc_address": "tcp://127.0.0.1:26657"
      }
    },
    "sync_info": {
      "latest_block_hash": "55CAEE49846E7224A8EA008A138BCA604C886059BD2BF351B9092F1A1D2029FF",
      "latest_app_hash": "A79A766DEA78F78AF0D0AF0520E30E007F1D34CE7AD1A46D0B1D20ECF71FFD07",
      "latest_block_height": "13317004",
      "latest_block_time": "2025-08-20T07:46:34.00111111Z",
      "earliest_block_hash": "7107672F6596ABBE4CC0F8D44650202A11122D416E939F0414D0153CAC0820D8",
      "earliest_app_hash": "F133669F28C83E500AD3FDCB8CD33FE3ED6F97D6DBC5D8B710F5C5D66AA78D70",
      "earliest_block_height": "13293001",
      "earliest_block_time": "2025-08-18T17:32:19.328852675Z",
      "catching_up": true
    },
    "validator_info": {
      "address": "891B95241F42F261F3C3E3E8BB1029564E402437",
      "pub_key": {
        "type": "tendermint/PubKeyEd25519",
        "value": "+Xv5XrD3QUwzb4DxjfRMo6tYTSpMNqsUOslCWnBKb8I="
      },
      "voting_power": "0"
    }
  }
}

プロセス的にはcosmovisorとgaiadが動いている。

cosvi@deroris:~$ ps aux | grep cosmoshub
cosvi     561302  0.1  0.1 1290652 56608 pts/14  Sl+  18:11   0:00 cosmovisor --cosmovisor-config /home/cosvi/data/cosmoshub-testnet/cosmovisor/config.toml run start --home /home/cosvi/data/cosmoshub-testnet/
cosvi     561312  219  6.9 3521764 2264744 pts/14 Sl+ 18:11   2:31 /home/cosvi/data/cosmoshub-testnet/cosmovisor/genesis/bin/gaiad start --home /home/cosvi/data/cosmoshub-testnet/
cosvi     561463  0.0  0.0   4728  2460 pts/16   S+   18:12   0:00 grep --color=auto cosmoshub

cosmovisorはsystemdにしておいたほうが良いと思うので、下記のような感じでsystemdファイルを作成して、サービス登録しておく。

$ cat cosmovisor.service
[Unit]
Description=Cosmovisor daemon for cosmos provider testnet
After=network-online.target
[Service]
User=node
ExecStart=/home/cosvi/bin/cosmovisor --cosmovisor-config /home/cosvi/data/cosmoshub-testnet/cosmovisor/config.toml run start --home /home/cosvi/data/cosmoshub-testnet/
Restart=always
RestartSec=3
LimitNOFILE=infinity
LimitNPROC=infinity
[Install]
WantedBy=multi-user.target

アップグレード検知の仕組み

チェーンのdata/upgrade-info.jsonディレクトリをポーリングして、見つけたらそこに書いてあるバイナリをDLしておくようだ。data/upgrade-info.jsonはチェーン側でアップグレードが承認されると勝手にできるはず。

確実に検証するにはアップグレードを待つか自前でチェーンを用意しないといけないのでまた今度

Tips

何かあった時にどうするかを考えておく。

アップグレードを手動で設定するには?

自分でDLしたバイナリを指定heightで置き換えることができる。(Propsなしのアップグレードの場合などに使える。)

add-upgradeを利用

ファイルができているのが分かる。

cosvi@deroris:~$ tree ~/data/cosmoshub-testnet/cosmovisor/
/home/cosvi/data/cosmoshub-testnet/cosmovisor/
├── config.toml
├── current -> genesis
└── genesis
    └── bin
        └── gaiad

4 directories, 2 files

cosvi@deroris:~$ cosmovisor --cosmovisor-config ~/data/cosmoshub-testnet/cosmovisor/config.toml add-upgrade upgradename-hehehe ~/Downloads/gaiad-v25.1.0-upgradetest-linux-amd64 --upgrade-height 13318200
6:39PM INF Using /home/cosvi/Downloads/gaiad-v25.1.0-upgradetest-linux-amd64 for upgradename-hehehe upgrade module=cosmovisor
6:39PM INF Upgrade binary located at /home/cosvi/data/cosmoshub-testnet/cosmovisor/upgrades/upgradename-hehehe/bin/gaiad module=cosmovisor
6:39PM INF /home/cosvi/data/cosmoshub-testnet/data/upgrade-info.json created, upgradename-hehehe upgrade binary will switch at height 13318200 module=cosmovisor

cosvi@deroris:~$ tree ~/data/cosmoshub-testnet/cosmovisor/
/home/cosvi/data/cosmoshub-testnet/cosmovisor/
├── config.toml
├── current -> genesis
├── genesis
│   └── bin
│       └── gaiad
└── upgrades
    └── upgradename-hehehe
        └── bin
            └── gaiad

7 directories, 3 files

bhまで待つと。差し変わっていることが分かる。(今回は同じバイナリを名前を変えて利用)

6:40PM INF indexed block events height=13318200 module=txindex
6:40PM INF daemon shutting down in an attempt to restart module=cosmovisor                                                                                                                                                                     6:40PM INF starting to take backup of data directory backup start time=2025-08-20T18:40:58+09:00 module=cosmovisor
6:40PM INF backup completed backup completion time=2025-08-20T18:40:58+09:00 backup saved at=/home/cosvi/data/cosmoshub-testnet/data-backup-2025-8-20 module=cosmovisor time taken to complete backup=206.919878                               6:40PM INF pre-upgrade command does not exist. continuing the upgrade. module=cosmovisor                                                                                                                                                       6:40PM INF upgrade detected, relaunching app=gaiad module=cosmovisor                                                                                                                                                                           6:40PM INF running app args=["start","--home","/home/cosvi/data/cosmoshub-testnet/"] module=cosmovisor path=/home/cosvi/data/cosmoshub-testnet/cosmovisor/upgrades/upgradename-hehehe/bin/gaiad
6:40PM INF starting the batch watcher loop module=cosmovisor                                                                                                                                                                                   6:40PM INF starting node with ABCI CometBFT in-process module=server                                                                                                                                                                           6:40PM INF service start impl=multiAppConn module=proxy msg="Starting multiAppConn service"
6:40PM INF service start connection=query impl=localClient module=abci-client msg="Starting localClient service"                                                                                                                               6:40PM INF service start connection=snapshot impl=localClient module=abci-client msg="Starting localClient service"
6:40PM INF service start connection=mempool impl=localClient module=abci-client msg="Starting localClient service"                                                                                                                             6:40PM INF service start connection=consensus impl=localClient module=abci-client msg="Starting localClient service"
6:40PM INF service start impl=EventBus module=events msg="Starting EventBus service"                                                                                                                                                           6:40PM INF service start impl=PubSub module=pubsub msg="Starting PubSub service"                                                                                                                                                               6:40PM INF service start impl=IndexerService module=txindex msg="Starting IndexerService service"                                                                                                                                              6:40PM INF ABCI Handshake App Info hash=A2C9DDF5FA222D4A1F0BF78815D294F42287822E3F5A65CA81E1F39CEBBF684F height=13318200 module=consensus protocol-version=0 software-version=v25.1.0                                                          6:40PM INF ABCI Replay Blocks appHeight=13318200 module=consensus stateHeight=13318200 storeHeight=13318200                                                                                                                                    6:40PM INF Completed ABCI Handshake - CometBFT and App are synced appHash=A2C9DDF5FA222D4A1F0BF78815D294F42287822E3F5A65CA81E1F39CEBBF684F appHeight=13318200 module=consensus
6:40PM INF Version info abci=2.0.0 block=11 commit_hash= module=server p2p=8 tendermint_version=0.38.17                                                                                                                                        6:40PM INF This node is not a validator addr=891B95241F42F261F3C3E3E8BB1029564E402437 module=consensus pubKey=PubKeyEd25519{F97BF95EB0F7414C336F80F18DF44CA3AB584D2A4C36AB143AC9425A704A6FC2}
6:40PM INF P2P Node ID ID=177215901472ab18a55b3d22a2b361811039ab8a file=/home/cosvi/data/cosmoshub-testnet/config/node_key.json module=p2p
6:40PM INF Adding persistent peers addrs=[] module=p2p
6:40PM INF Adding unconditional peer ids ids=[] module=p2p
6:40PM INF Add our address to book addr=177215901472ab18a55b3d22a2b361811039ab8a@0.0.0.0:26656 book=/home/cosvi/data/cosmoshub-testnet/config/addrbook.json module=p2p
6:40PM INF service start impl=Node module=server msg="Starting Node service"
6:40PM INF service start impl="P2P Switch" module=p2p msg="Starting P2P Switch service"
6:40PM INF service start impl=Mempool module=mempool msg="Starting Mempool service"                                                                                                                                                            6:40PM INF service start impl=Reactor module=blocksync msg="Starting Reactor service"                                                                                                                                                          6:40PM INF service start impl=BlockPool module=blocksync msg="Starting BlockPool service"
6:40PM INF service start impl=ConsensusReactor module=consensus msg="Starting Consensus service"
6:40PM INF serve module=rpc-server msg="Starting RPC HTTP server on 127.0.0.1:26657"
6:40PM INF Reactor  module=consensus waitSync=true
6:40PM INF service start impl=Evidence module=evidence msg="Starting Evidence service"
6:40PM INF service start impl=StateSync module=statesync msg="Starting StateSync service"
6:40PM INF service start impl=PEX module=pex msg="Starting PEX service"
6:40PM INF service start book=/home/cosvi/data/cosmoshub-testnet/config/addrbook.json impl=AddrBook module=p2p msg="Starting AddrBook service"
6:40PM INF Saving AddrBook to file book=/home/cosvi/data/cosmoshub-testnet/config/addrbook.json module=p2p size=1397
6:40PM INF Ensure peers module=pex numDialing=0 numInPeers=0 numOutPeers=0 numToDial=10

cosvi@deroris:~$ tree ~/data/cosmoshub-testnet/cosmovisor/
/home/cosvi/data/cosmoshub-testnet/cosmovisor/
├── config.toml
├── current -> upgrades/upgradename-hehehe
├── genesis
│   └── bin
│       └── gaiad
└── upgrades
    └── upgradename-hehehe
        ├── bin
        │   └── gaiad
        └── upgrade-info.json

7 directories, 4 files

途中からcosmovisorを導入する場合

すでに動いているところにcomovisorを入れる場合には?
gaiadが動いているところでcosmovisor initまで行って最後に切り替えればよろし。
バックアップは忘れずに。
古いところに置いてあるgaiadは削除すること。(どれを使っているか分からなくならないように)

最後に

ちょっと長くなりましたので、その他検証はまた今度とします。simdというお試しバイナリがあるのでそちらを使うときに検証しようと思います。simappを使ったほうが検証しやすそうですね。
https://github.com/cosmos/cosmos-sdk/tree/main/tools/cosmovisor#example-simapp-upgrade

cosmovisorを過信しすぎないように注意してください。アクティベーション時にはちゃんと見ておくのが必要かと思います。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?