複数のマシンを使って動作検証をしていると、ログインやコマンド入力の操作が煩雑になる。 また、複数のマシンに共通で必要な操作があったりすると手数もかさむ。 今回は、そういった問題を緩和できる ClusterShell について扱う。 ClusterShell を使うと、マシンをグループ化して SSH で並列に操作できる。
今回は、次のようなマシンの構成を扱う。
client
には ClusterShell をインストールして、他のマシンを操作する。
master
と worker[01]
は名前通り異なる役割のマシンを想定して用意した。
- client
- 192.168.56.10
- master
- 192.168.56.20
- worker1
- 192.168.56.31
- worker2
- 192.168.56.32
上記のマシンは、あらかじめ Ubuntu 20.04 LTS を使って構築してある。 一応、末尾にはおまけとして Vagrant + VirtualBoxを使って仮想マシンを構築するための設定ファイルを用意した。
$ lsb_release -a No LSB modules are available. Distributor ID: Ubuntu Description: Ubuntu 20.04.3 LTS Release: 20.04 Codename: focal $ uname -srm Linux 5.4.0-91-generic x86_64
ClusterShell のバージョンは次のとおり。
$ clush --version clush 1.8.3
もくじ
下準備
client
には、まず ClusterShell をインストールする。
sshpass と openssh-client は SSH のために入れておく。
$ sudo apt-get update
$ sudo apt-get -y install sshpass openssh-client clustershell
これで clush
コマンドが使えるようになる。
$ clush --version clush 1.8.3
次に、ホスト名を使って操作したいので /etc/hosts
に IP アドレスとの対応関係を書き込んでおく。
$ cat << 'EOF' | sudo tee -a /etc/hosts >/dev/null 192.168.56.10 client 192.168.56.20 master 192.168.56.31 worker1 192.168.56.32 worker2 EOF
次に SSH でログインするための公開鍵を作成する。
$ ssh-keygen -t rsa -P '' -f $HOME/.ssh/id_rsa
client
から、その他のホストに公開鍵を使ってログインできるように登録する。
ここの作業は環境構築に使ったツールやイメージなどによって少し変わる。
たとえばパスワード認証が無効になっているイメージだと、この操作では登録できない。
また、Vagrant で作った環境なのでパスワードが vagrant
になっている。
$ sshpass -p "vagrant" \ ssh-copy-id -i $HOME/.ssh/id_rsa.pub -o "StrictHostKeyChecking no" master $ sshpass -p "vagrant" \ ssh-copy-id -i $HOME/.ssh/id_rsa.pub -o "StrictHostKeyChecking no" worker1 $ sshpass -p "vagrant" \ ssh-copy-id -i $HOME/.ssh/id_rsa.pub -o "StrictHostKeyChecking no" worker2
次に、ClusterShell にホスト名とグループの対応関係を登録する。
対応関係は /etc/clustershell/
以下の設定ファイルで指定する。
設定ファイルは <group-name>: <hostname>,...
というフォーマットになっている。
以下では all
というグループに、操作対象となるすべてのホストを登録している。
そして、グループ m
に master
を、グループ w
に worker1
と worker2
を登録している。
$ sudo cp /etc/clustershell/groups.d/local.cfg{,.orig} $ cat << 'EOF' | sudo tee /etc/clustershell/groups.d/local.cfg >/dev/null all: master,worker1,worker2 m: master w: worker1,worker2 EOF
これで ClusterShell を使い始める準備ができた。
個別のホストを指定して操作する
特定のホストを指定してコマンドを実行したいときは -w
オプションを使う。
ここでは、それぞれのホストにホスト名を設定した。
$ clush -w master "sudo hostnamectl set-hostname master" $ clush -w worker1 "sudo hostnamectl set-hostname worker1" $ clush -w worker2 "sudo hostnamectl set-hostname worker2"
グループを指定して操作する
先ほどの例であれば、別に ssh(1) を直接使って操作しても変わらなかった。
ClusterShell の本領はグループを指定して操作できることにある。
グループを指定するには -g
オプションでグループ名を指定すれば良い。
また、-L
オプションを指定すると、結果をホスト名のアルファベット順でソートできる。
試しに all
グループに対して hostname コマンドを実行してみよう。
$ clush -g all -L hostname master: master worker1: worker1 worker2: worker2
上記から、操作対象のすべてのホストに hostname コマンドが実行されたことがわかる。
また、-g all
はよく使うので -a
オプションがエイリアスとして用意されている。
$ clush -a -L hostname master: master worker1: worker1 worker2: worker2
同じように、特定のグループを指定してコマンドを実行してみよう。
以下ではグループ m
と w
を、それぞれ指定している。
$ clush -g m -L hostname master: master $ clush -g w -L hostname worker1: worker1 worker2: worker2
ちゃんとグループに所属しているホストに対してコマンドが実行されていることがわかる。
グループはカンマ区切りで複数指定することもできる。
以下ではグループ m
と w
に対して実行している。
$ clush -g m,w -L hostname master: master worker1: worker1 worker2: worker2
複数のホストにファイルをコピーする
ClusterShell では、複数のホストにファイルを scp(1) できる。
ファイルをコピーするには -c
オプションでコピーしたいファイルを指定して、コピー先のディレクトリを --dest
オプションで指定する。
以下では greet.txt
というファイルを、すべてのホストに対して /tmp
以下にコピーしている。
$ echo "Hello, World" > greet.txt $ clush -g all -c greet.txt --dest /tmp
コピーされたはずのパスを cat(1) すると、ちゃんとファイルがコピーされていることがわかる。
$ clush -g all -L "cat /tmp/greet.txt" master: Hello, World worker1: Hello, World worker2: Hello, World
書き込みに特権が必要なファイルをコピーするときは、少し工夫が必要になる。
具体的には、一度特権が不要なディレクトリにコピーした上で、あらためて特権ユーザでファイルを移動するというもの。
たとえば /etc/hosts
をコピーしてみよう。
$ clush -g all -c /etc/hosts --dest /var/tmp $ clush -g all -L "sudo cp /var/tmp/hosts /etc/hosts"
たとえば master
の内容を確認すると、ちゃんとコピーされたことがわかる。
$ clush -w master "cat /etc/hosts" master: 127.0.0.1 localhost master: 127.0.1.1 vagrant master: master: # The following lines are desirable for IPv6 capable hosts master: ::1 ip6-localhost ip6-loopback master: fe00::0 ip6-localnet master: ff00::0 ip6-mcastprefix master: ff02::1 ip6-allnodes master: ff02::2 ip6-allrouters master: 192.168.56.10 client master: 192.168.56.20 master master: 192.168.56.31 worker1 master: 192.168.56.32 worker2
まとめ
今回は ClusterShell を使うことで、複数のマシンを SSH で並列に操作する方法を扱った。
おまけ: 環境構築に使った Vagrantfile
今回の環境を作るのに使った Vagrantfile を以下に示す。
# -*- mode: ruby -*- # vi: set ft=ruby : # Vagrantfile API/syntax version. Don't touch unless you know what you're doing! VAGRANTFILE_API_VERSION = "2" Vagrant.configure(VAGRANTFILE_API_VERSION) do |config| machines = { "client" => "192.168.56.10", "master" => "192.168.56.20", "worker1" => "192.168.56.31", "worker2" => "192.168.56.32", } machines.each do |key, value| config.vm.define key do |machine| machine.vm.box = "bento/ubuntu-20.04" machine.vm.network "private_network", ip: value machine.vm.provider "virtualbox" do |vb| vb.cpus = "2" vb.memory = "1024" end end end end
あとは以下で環境が用意できる。
$ vagrant up $ vagrant ssh client
いじょう。