morimorihogeです。今年も暮れですね、一年が早い。
みなさん、SSH使ってますか?昨今のモダンなインフラ環境になると、ECSやKubernetes使っていてそもそもシェルで対話ターミナルを立ち上げるの自体時代遅れだ!みたいな界隈もあるのかなと思いますが、RailsやPHPでシュッと立ち上げる小規模なサーバーアプリケーションであれば運用時のメンテナビリティの面で今でもまだまだSSHは現役なのではないでしょうか。
流石に古いOpenSSH&昔作ったssh-rsa鍵を使い続けていて、モダンなクライアントから接続するときに ~/.ssh/config
に
HostKeyAlgorithms=+ssh-rsa
PubkeyAcceptedAlgorithms=+ssh-rsa
を書かないといけないようなサーバーはいくらなんでも滅ぼすかアップグレードした方が良いとは思いますが、過去のツール・資産群を活用できるという点でもSSHが現場レベルで完全にオワコンになるのはまだまだ先でしょう。シェルを使わないとしても、 DynamicForward
を使ってブラウザからSOCKS Proxyとしてイントラネットへの踏み台経由アクセスにも使えますしね。
やりたいこと
昨今では流石にバックエンドサーバー1台構成で構築する機会は減り、最低でも2台以上の冗長系・バッチ系などの環境を用意することが常識化しました。
そんな環境で監視設定を追加したりちょっとログを見たくなった時には 全てのサーバーで全く同じコマンドを実行して結果を見たい というオペレーションがちょくちょく発生します。
インストール・設定ファイルの更新で2~3台程度であればまだ手順をメモって1台ずつやってもいいかなという気もしますが、本番・ステージング・開発環境それぞれで複数台のホストがあるような環境になってくると急に手間が爆発します。
そして、単純作業ほど何度もやっている内にケアレスミスをしてしまって一部のサーバーだけうまく動かないといった泥沼にハマりがちです。特に単純作業だと人間が一番信用できない。
作業の内容によってはスクリプトを作っておいて全環境でまとめて流したり、Ansibleなどで管理しているのであればこちらも同じコマンド群を実行させる分にはそれで事足りるのですが、世の中には対話コンソールでやりたい作業というのもあります。
具体的には 設定変更時の疎通チェック、top
や sar
などを使ったオンデマンドな今現在の負荷状況確認、CloudWatch LogsやFluentdなどに流していないサービスのログ閲覧 などが対話シェルが欲しい作業になるでしょう。
ここではCluster SSH(cssh)を使うことで複数のホストへSSH同時接続し、同期的にターミナルを確認しながら作業する方法を紹介します。
Cluster SSHのインストール
本稿での環境はWindows 11 + WSL2上のUbuntu 22.04環境を使っていますが、Mac環境でもHomebrewなどを使えばサクッとインストールできるはずです(少なくとも昔は普通に使えた)。
インストール方法は何の変哲もなく、root権限で
apt-get update
apt-get install -y clusterssh
で大丈夫です。
実行方法
こちらも何の変哲もなく、
cssh USERNAME1@HOST1 USERNAME2@HOST2 USERNAME3@HOST3 ...
とすれば良いです。よく接続するホスト群があるのであればCluster SSH自体の設定を色々とカスタマイズすることで簡単に実行したりできるようですが、自分の用途では流石にそこまでしょっちゅうは使わないので都度ホストのリストを入力しています。
ただ、SSHトンネルして接続しているホストなどは単一のホスト名でアクセスできるようにSSHクライアントの設定(~/.ssh/config
)はしておいた方がよいでしょう。
実行すると下図の様に接続先ごとのターミナルウィンドウとCSSHのコントロール用ウィンドウが開きます。
WSL2からはX11なアプリケーションは特に何もがんばらずに実行できるようになっています。便利な世の中になりましたね。
WSL1時代やVirtualBoxを使っていた頃は、VcXsrvなどのX ServerアプリをWindows側で立ち上げてX11転送してがんばっていた記憶がありますが、令和のエンジニアはこういったことに悩む必要がないようです。
あとは、以下のCSSHのウィンドウにフォーカスを当てて入力したキー内容がそれぞれのターミナルウィンドウに送信され、それぞれの結果を見ることができます。ホストが多い場合は大きな画面が欲しいですね。
ちょっとしたテクニック
Cluster SSHでは全てのキー入力を全ホストにコピーして転送してしまうため、ホストによってちょっとだけ違う設定というのがそのままだとやりづらいことがあります。
例えば、本番・ステージング・開発環境でそれぞれロードバランサーのアドレスが異なるなど、ちょっとずつ環境設定の詳細が違うことはままありますね。
CSSHで開いたターミナルには、それぞれ個別にウィンドウのフォーカスを当てると個別のターミナルだけの操作を行うこともできます。
というわけで、サーバー別に設定する値を分けつつ同じ名前の環境変数をインスタントに設定することで設定したい値を抽象化してやるとうまくやれることがあるでしょう。
利用上の注意とか
CSSHを利用する場合はコマンド実行時に 各ホストごとのターミナルウィンドウの状態を確認する ことが大事です。
どういうことかというと、
- シェルのヒストリからコマンド実行をしようとしたら、一部のホストだけhistoryの内容が微妙に異なり、同じコマンドが実行されない
- 何らかの理由により一部のホストだけ入力のレスポンスが遅くなり、コマンドが細切れになり正常に実行されていない
- 過去の個別作業を行ったときの細かい差違(コンフィグファイルの空行のある・なしなど)があり、vimなどでの編集結果がずれる
- 負荷調査などで入った場合、一部のコマンドがリソース不足で失敗する
といったことが起こります。
特に、高負荷時の調査などではリソース空きのあるホストでは正常に動作するコマンドが、空きのないホストでグリッチしてしまうといったこともあるので、普段よりさらに注意して作業する必要があるでしょう。
まとめ
Cluster SSHによる作業はAnsibleやコンテナdeployに比べると泥臭く、再現性の低い作業になってしまうので普段から通常のオペレーションとして使いたいものではありませんが、臨時のオペレーションをするときの道具として知っておくと便利です。
たまにSSH作業をすると「うーんこいつも早くコンテナ化してしまいたいなあ」と思う昨今ではありますが、まだまだSSHシェル作業が世の中から滅びる世界は先だと思いますので、それまでだましだまし付き合っていきましょう。
ではでは。