Re: 若者がパッケージ管理について思うこと

「パッケージ」を

  • あまり入れ替えしないし、入れ替えたくもないもの
  • 好きに入れ替えしたいもの

の2つに分類して、ここ数年自分がどう管理してきたかを書いてみたいと思います。主に構成管理の切り口の話になります。

あまり入れ替えしないし、入れ替えたくもないもの

具体的には、

  • 基本的なソフトウエア
    • coreutilsとかtarとかそういった類のもの

です。

これらは最初の最初にサーバーをセットアップするときに、ディストリのバイナリパッケージを入れて基本的にはそれでおしまいです。

バージョン管理、依存関係の管理はディストリのパッケージシステムにお任せです。

セットアップ後はよっぽどのことがない限り、アンインストール、ダウングレードは基本的にしません。アップグレードも本当に本当に影響のあるセキュリティ修正のみ。追加インストールは後から必要なものが出てきたらディストリのパッケージシステムを使って適宜入れます。

ディストリのパッケージシステムは時間が経つとその寿命、期限切れが問題になりますが、自分はUbuntu LTSのserverの方(リリースから5年サポート)を使うようにしていました。


さて、サーバーが複数台ある場合はどうしているかですが、まるっと全部コピーして終わりです。

あとで追加でパッケージを入れる際は、各サーバーでシコシコバイナリパッケージをインストールするのではなく、起点サーバーにだけインストールしてあとは(パッケージの管理情報も含め)まるっとコピーするだけです。

「まるっとコピー」には、以下のようなrsync -avRを(root権限で)実行するスクリプトを書いて使っていました。

  • オプションによって同期コピーするディレクトリやサーバーを切り替えられるように
  • いくつかのファイルは同期コピーから除外するように (rsync --filter='. -'で標準入力から取捨選択のフィルタ定義を読む感じ)
    • /var/ 下のいくつか
      • ただし /var/lib/dpkg/ などパッケージシステムの管理情報は除外しない
    • /etc/ 下のld.so.cache, adjtime, mtab とか
    • /tmp/, /proc/, /dev/ とか
    • /service/とdaemontoolsのlog/main/
    • メールキュー
    • lost+found/
    • LOCAL/
      • ローカルルールで、他サーバーに同期コピーされたくないものは LOCAL/ という名のディレクトリ配下に置くことにしていました。

そもそも新しいサーバーをセットアップするときはkickstart等は使わず、このまるっとコピースクリプトを使って生きてるサーバーからまるまんまコピーして終わりで、ファイル/ディレクトリのオーナー、グループ、パーミッション、mtimeまですっかりまったく同じサーバーができあがります。


この同期コピーの対象(コピー先)となるサーバーは、ディスクブートしている全てのサーバーです。

「全部のサーバーの内容が同じだと、役割(Webサーバーとかメールサーバーとかとか)分けはどうしてるの?」という疑問が出てくると思いますが、これは、「自分が何者であるか?(どういう役割を割り当てられているか)」情報を管理・参照する仕組みと、それに基づいて適宜、

  • 設定ファイルの生成、symlink張りなど
  • その他もろもろの調整
  • サーバープロセスの起動

をするrcスクリプトを用意して実現していました。


以上2点、「まるっとコピー」と「自律的に役割をまとうしくみ」のおかげで、「あまり入れ替えしないし、入れ替えたくもない」類のパッケージの管理コストはほぼゼロにしていました。


この「まるっとコピー」作戦の前提として、

  • ハードウエアのアーキテクチャが混在していない (i386, x86_64)
    • ハードウエアの混在は大丈夫なようにしていました。ロードするkernel modeuleの差異などは、ハードウエア情報を参照して、いい塩梅にinsmodするようにしていました。
  • ディストリとそのバージョンが混在していない

である必要があります。

アーキテクチャの違いを許容すると、とたんに面倒くさい問題が噴出するので、今ならx86_64に統一しない理由はないと思います。(レキシテキジジョウがある場合もありますが。。。)

ディストリとバージョンを固定化すると、「ライブラリのバージョンが古くて(自前ビルドの)XXXがインストールできない」という問題が出てきます。影響範囲の確認作業が大変ですが新しいのに入れ替えちゃうか、既存のライブラリに影響しないように新しいライブラリを入れるかして対応してきました。libcをlibc5からglibcに入れ替えたとき以外は、ここで苦労した記憶はあまりありません。(運がいいだけかもしれませんが)

好きに入れ替えしたいもの

具体的には、

  • kernel と kernel module
  • サーバーの役割に直結するミドルウェア
    • ApcheとかNginxとかMySQLとか
  • Webアプリの開発言語まわり
    • Perl本体とCPANモジュールとか

です。

kernel と kernel module

kernelはディストリ付属のだとベンダーパッチが当たっててよくわからんのが気持ち悪いので、kernel.org配布のvanilla kernelをビルドして使っていました。

make-kpkg等のディストリ付属の支援ツールも、あまり恩恵が感じられなかったので使っていませんでした。

自前ビルドなので、「ディストリ付属のkernelが古くて、このハードウエアのドライバがない〜」とかいうこともありません。

サーバーの役割に直結するミドルウェア

「新しいバージョンが使いたい」「ちょっとパッチ当てて使いたい」ということが多々あるので、Apache等のミドルウェアはディストリのパッケージは使わず自前ビルドで入れていました。

インストールディレクトリ、バージョン管理などは、

に書いた通りです。

複数サーバーの場合は、前述の「まるっとコピー」スクリプトを使って同期コピーするだけで終わりです。rpm化、deb化などは全く微塵もイチミクロンも必要性を感じたことがないので一切したことがありません。

Webアプリの開発言語まわり

Perlの場合ですが、perl本体とモジュールはWebサービスごとに完全に分離して管理していました。

これにより、「system perlじゃなくてナウいバージョンのperlが使いたい!」「となりのWebサービスがモジュールのバージョン上げたせいで誤動作した!!」といった問題ともおさらばです。

管理といってもインフラ担当者はほぼほぼノータッチで、アプリ開発者が自由に、

  • perl本体は perlbrew
  • Perlモジュールは extlib (cpanm -l extlib)

で、perl本体もextlibもまるまるごっそり git に入れて世代管理していました。

ほかサーバーへの展開は「まるっとコピー」で一発です。

むすびに

今回紹介したのはあくまで「オレはこうしてきた」というお話ですので、ほかにもいろいろな手法、考えがあると思います。

パッケージ管理に限りませんが、効率的で手間のかからない 運用について是非、意見交換したいですね。