情報系の研究室は往々にして内部にサーバを抱えがちである。 数値計算用のGPUサーバはもちろん、NFSやWiki、Webページなどほしいものは多い。 普通こういうものは計算ノードを除いてAWSとかを使えば良いものだが、 校費(少ない)や科研費(研究に直接必要なもの以外使えない)予算制度(繰越とかサブスク関連とかなんか複雑)とかの事情があったり、伝統によって自前で持っていたりする。
私の所属する研究室は主に後者の理由から✝メールサーバ✝や✝DNS✝が存在する。 他の研究室がどうやって運用しているか意外と知る機会がないと思われるので書き残しておく。
運用中のサービス一覧は以下の通り。
メールサーバ DNS NFS PukiWiki Webサーバ SSH踏み台 LDAP RADIUS アーキテクチャ 実行基盤とかそういうの。 他の研究室の事例を読んだ感じだと仮想マシンやk8sを使う構成が多いが、 私はsystemdとdockerとtraefikだけで構築している。
まず仮想マシンはディスクをやたら食う割にDockerに比べて明確な優位点が無いと思う。 分離という点ではDockerのIsolationは全然信用出来ない(DockerからホストにRCEするのはCTFの定番だったりする)が、運用の観点でいうとそもそもコンテナ内でRCEされるてる時点で負けている。 ネットワークスタックの複雑化も結構辛い。
k8sに関しては少なくとも研究室では採用すべきではない。k8s本体はまだ良いとして、 CNIとか絶妙なバグに遭遇しがちになる。開発が活発なのは裏を返すとバグが仕込まれるのも活発ということで、修正されても新機能がバグってるみたいなことになる(一敗)。 カーネルビルド設定との兼ね合いがあるし、やたらとオプションが多いので学生が研究の片手間で差分を精査して更新するのは非現実的だと思っている。 そもそもk8sはLoadBalancerやAPIサーバ間の冗長化に対してノータッチなのでAPIサーバはKube VIPを使い、ロードバランサはiBGPかProxy ARPを使うことになる。 ネットワークスペシャリスト試験かな。
またリリースサイクルと大学の相性も悪い。大学には一年に一回全学停電というイベントがある。 k8sの更新をこのタイミングでやってしまいたいが、k8sは9ヶ月がサポート期間だ。絶妙。 とはいえAPIサーバの更新は無停止で出来るので致命的ではない。が、厄介なのは起動手順になる。 k8sはmanifestで色々書けてしまう分散システムである分Rook Cephとかでいとも簡単に循環依存を作れてしまう。注意すれば良いが、そもそもこういう循環依存を作らない設計にしたほうがいい。 障害発生時に依存順序を把握して修正するのはかなり面倒くさい(面倒くさかった)。
あとそもそもk8sで冗長化しなくても負荷に耐えるのは簡単。
とはいえ密結合したリバースプロキシの設定ファイルを書いたり大量のcertbot hookを書くのは管理に困るのでtraefikを導入した。 traefikはエントリポイントさえ作っておけばDocker labelと動的設定ファイルだけで無停止で ルーティング情報を更新し、ACME管理下の証明書を作れる。 traefik-certs-dumperを動かしてhookを書くことでRADIUSやLDAPS、 メールといったTLSを必要とするサービスも普通に動かせる。 traefikはdocker-composeで動かす構成が多いが、systemdでdockerをそのまま叩いた方が シンプルになるのでおすすめ。
デプロイはAnsibleのみ。 なるべくAnsibleに寄せることで管理対象下のリソースが明瞭になるし、 デプロイの再現性も確保できる。
メールサーバ そのメールサーバ?ってやつやめたら?学生の本分は研究でしょ?
古典的なPostfix+Dovecot構成。 現代的な選択肢としてはStalwart とか色々あるが、 既存のMaildirがやたらデカいので移行が結構難しい。 またデータ復旧やバックアップはファイルシステム上に構築されたMaildirが一番簡単。 あと細かい設定をPostfixの方が移行しやすいというのもある。
とにかくメールサーバは細かい設定がかなり必要になってくるのと安定性が重要なので なんだかんだでPostfix以外の選択肢が無いように感じる。 最初から構築するのなら新しめのプロダクトを使うのもアリかもしれないが。
DKIMかSPFは設定しないとGmailに弾かれるので設定必須。 OpenDKIMとpostsrsdを導入し、SPFとDMARCを設定すればgmailに弾かれないし迷惑メール扱いもあんまりされない。
メールサーバを運用する上で難しいのがバックアップだが、 Maildirは要はただのファイルシステムに過ぎないのでbtrfs subvolumeのスナップショットとrsyncでどうにかなる。頑張ってスクリプトを書きましょう。
DNS CoreDNSをDockerに入れてZonefileだけで動かしている。 使うの簡単だしzonefileだけなら特にセキュリティホールとかもない。 内部のリゾルバはKnot Resolverを入れたがこれは完全に好み。
研究室内部のサーバ間の名前解決をDNSでやらないようにするのが結構重要。 NFSのマウントに失敗して連鎖障害が発生する。 最近のsystemd-resolvedは/etc/hostsを読むので外部のフルリゾルバと/etc/hostsにだけ依存するようにすれば安定する。
Webページ 元々Wordpressのstatic exportプラグインを使っていたがAstroJSに全部書き換えた。 デプロイはアセット入りのnginxコンテナをghcrに上げてsystemdで動かしている。 色々考えたが多分これが一番楽。Webコンテンツの変更をPRで管理できるので複数人で編集しやすいのもかなり良い。
LDAP 厳しい。理屈はわかる。 確かに昔はSQLはあくまでビジネス向けでしか無いと思われていたし、 ディレクトリサービスは最適化もしやすく現実の組織構造にもマッチする便利ツールだったとは思う。 ファイルシステムが主要なDBだった時代ではその高機能版というのも自然な発想だろう。 バックエンドのBerkleyDBやLMDBも当時は十分にモダンだしシンプルで高性能。 とはいえ、現代はSQL全盛期だしLDAPほどの柔軟性はもはや必要ない。 自分はLMDBのことをAre You Sure You Want to Use MMAP in Your Database Management System?で知った。別にLDAPが悪いわけじゃないがあんまりメンテしたくない。ldapmodifyも微妙だ。宣言的なようで宣言的じゃないちょっとだけ宣言的なツール。 k8sのmanifestは偉いね。
kanidmへの移行を準備している。OIDC、RADIUS、LDAP(Readonly)、UNIX認証をこれ一つで提供する。めっちゃ便利。バックエンドもSQLiteだし自動バックアップ機能も内蔵されているので運用がやりやすい。認証自体もTOTPとWebAuthnをサポートしておりかなりモダンで嬉しい。
NFS Cephへの移行を計画しているがこれは結構ロマン枠だと思う。 無難なのはRAID10でNFSだろうか。 個人的に研究で使った大量のデータを保存できる場所がほしいのでCephを組みたかった。 最近はcephadmがあるのでなんとかなるだろうという見切り発車になっている。 モダンな運用ではRook-Cephが使われることが多いが、 Rookの中のコードはかなりad-hocなものが多くバージョン追従をしっかりやる組織力があり、 かつ大量のストレージノードがあるような環境でのみ使うべきだろう。研究室には不要。
まとめ 全体としてはk8sを避けてsystemdに寄せた。 dockerのみを使い、抽象化をなるべく減らすこと、ファイルシステムとSQLに統一すること、 サービス間の依存をなるべく減らすことが重要。特に相互依存によるBootstrapの難化や 連鎖障害は結構辛い結果をもたらす。 そして冗長構成はあんまり要らない。 突発的なHW故障による障害よりも停電で全ノード止まることのほうが遥かに多く、 あまり実利はない。