VPN経由でしか到達しないサーバーにとって、無人更新は妥当な方針である。同時に、それは自分で作り出す単一障害点でもある。パッケージ操作がサービスを再起動し、トンネルが落ち、使っていた管理経路もそれと一緒に消える。復旧モデルは二つあり、どちらを選ぶかは一つの条件で決まる。更新対象を通らない 入口の経路を持っているかどうか.

二つの復旧モデルと一つの決定的条件

第一のモデルは更新を信頼し、後で再接続できると仮定する。VPNがホストへの複数の到達手段の一つであり、トンネルの障害が診断能力を奪わない場合に機能する。第二のモデルは独立した経路、通常はホスティング事業者のコンソールをあらかじめ用意し、トンネルを保守で最も壊れやすいものとして扱う。どちらのモデルも擁護できるが、事前の作業を要するのは片方だけである。

決定的条件は口にするのは簡単で、飛ばすのも簡単だ。マシンへの管理経路がすべて更新対象のサービスを通るなら、復旧モデルは存在せず、期待だけがある。変更レビューでそれを声に出して言おう。

その条件の確認には十分かかり、最初の無人更新の前に済ませる必要がある。障害の最中ではない。すべてが動いているうちにコンソールを開き、資格情報が有効であることを確かめ、また閉じる。コンソールが想定どおりのホストに開くことを確認する。次に、午前3時に実際に使うログインが今も機能することを確認する。

最後の部分は聞こえ以上に重要だ。半年前にパスワードを変えたきり一度も検証していないコンソールアカウントは復旧経路ではない。それは経路を説明した文書にすぎない。

バックアップが復元しないもの

設定アーカイブはファイルの記録であり、更新はファイル以上のものを変える。パッケージ状態、カーネルモジュール、有効化されたユニットのリンク、別のツールで適用したファイアウォール規則はどれも設定ディレクトリの外にあり、それらを無視した復元は、設定済みに見えて転送しないマシンを生む。

What changedRestored by a configuration backupNeeds its own action
Service unit or startup orderingPartly, if the unit file was includedPackage state and enabled links
Kernel module or interface supportNoKernel or module rollback, or a boot-time decision
Peer or device authorizationOnly if the backup predates the revocationA deliberate decision about which peers return
Firewall rules applied outside the configOnly if they were capturedReplaying and verifying each rule

認可には独立した行が必要だ。侵害された端末を外す前に取ったバックアップは、その端末のアクセスを喜んで復元する。障害時にそこへ戻すことが、一つのインシデントを二つにする道であり、復元の判断はファイルについてと同じくらい明示的にピアについて下すべきだ。

ロールバックの仕組みも重要だ。パッケージ管理下のファイルに古い実行ファイルを上書きするのは、パッケージ変更の正式な取り消しではなく、パッケージデータベースにファイルシステムと合わない状態を説明させ続ける。パッケージマネージャー自身のダウングレード経路か、事業者が提供するスナップショットを使う。パッケージデータベースが記録するダウングレードなら繰り返せる。

これはどれもバックアップに反対する話ではない。部分復元の故障の仕方が元の障害より分かりにくいので、成果物ごとにどの層を覆うかを知っておくべきだという話である。ランブックの各バックアップの隣に層を書く。

チェックポイント、更新、そして外側からの検証

変更前の状態を、後で比較できる形で記録する。インストール済みのバージョン、関係するサービスユニット、待ち受けているソケット、現在のピア一覧である。Linuxホストなら四つのコマンドでその大半を押さえられる。

systemctl list-units --type=service | grep -E 'openvpn|wg-quick'
ss -lunp | grep -E ':51820|:1194'
journalctl -u wg-quick@wg0 --since '-10 min'

一つ目はどのユニットが存在し実行中かを示し、二つ目は待ち受けが実際に束縛されていることを確かめ、三つ目は直近数分についてサービス自身の説明を与える。どれもクライアントが接続できることを証明しない。だから次の手順はホストの外から行う。それらの読み取りを比較の基準として残す。

トンネルを使わないネットワークから検証する。許可されたクライアントを一つ認証し、名前を解決し、目的のアプリケーションに一つ到達する。インターフェースが上がっているというローカルの状態行はインターフェースについての記述であり、経路、鍵、ピアを許可する方針についてではない。

次に再接続の経路を意図的に試す。サービスを一度再起動し、手作業なしでトンネルが戻ることを確認する。起動時にしか正しく開始しないサービスは、最悪の瞬間に驚かせるサービスだからだ。

失敗したら、テストした経路を使う

復旧の順序は地味だが機能する。独立した経路でホストに到達し、サービス自身のログを読み、障害に対応する特定のチェックポイントを復元し、試行ごとに一つだけ変える。そうすれば次のログの読み取りが意味を持つ。

接続を取り戻すために記録しない変更をいくつも重ねたい衝動に抗う。五つの同時編集で直したマシンは後から説明できない。次の更新は、実際に荷重を支えていた変更をまた持ち込むだろう。

そして証拠をもって恒久的な方針を決める。更新が誰も文書化していない依存を露呈したなら、直すのは文書とテストであり、更新を止めることではない。きれいに再起動できないサービスを露呈したなら、直すのはユニットであり、スケジュールではない。

条件に名前が付いた時点で比較はきれいに片づく。独立した経路があれば無人更新は管理可能なリスクになる。それがなければ同じ方針は復旧時間不明の計画停止になり、どれだけ自動化してもその算術は変わらない。

関連記事