LabHub

ブログ

systemd v261 — PID 1に来た段階的ロールアウト、クラウドIMDSの取り込み、そしてdlopen移行の完成

한국어English日本語中文

はじめに — 3か月に一度、今回はfleetの番

systemdは最近ほぼ四半期ごとにメジャーリリースを出しています。raw NEWSファイルのリリースフッターをそのまま拾うと、v258が2025-09-17、v259が2025-12-17、v260が2026-03-17、そしてv261が2026-06-19です。本稿執筆時点で、Arch Linuxのcoreリポジトリはすでに261.1を配布しており、Ubuntuは26.10開発ブランチ(stonking)に261.1が入り、26.04 LTSは259.5に留まっています。つまりローリングリリース系のユーザーは今出会い、LTSユーザーはおそらく来年出会います。

バージョン番号だけ見ればまた一つの四半期リリースですが、NEWSを最初から最後まで読むと、今回のリリースには一つのはっきりした方向性が見えます。PID 1が単一マシンのinitを超えてfleet運用のプリミティブを吸収し始めたということです。ユニットをfleetの一定割合でしか有効にしないConditionFraction=、マシンをリングにまとめるタグシステム、クラウドのインスタンスメタデータ(IMDS)を起動プロセスに統合する新しいサブシステムが、すべてこの一つのリリースに入りました。その傍らでは、2024年から続く依存関係の隔離作業 — 外部ライブラリのdlopen()移行 — がついに完結し、v258のcgroup v1廃止から始まった「削除の弧」も続いています。

本稿はセールスポイントの順ではなく、運用者の視点での重要度順に進みます。各項目が何であり、どこで使えて、そして — 同じくらい重要な — 何ではないかを見分けることに重点を置きます。systemdのユニットや条件式自体が初めてなら、systemdサービス管理・ユニットファイル設定・トラブルシューティングを先に読むほうがいいでしょう。

ConditionFraction= — ユニットファイルに来た段階的ロールアウト

v261で最も興味深い新機能です。v261タグのsystemd.unit manソースを基準に整理するとこうなります。

ConditionFraction=は、ユニットを「fleetの安定した疑似ランダム部分集合」でのみ有効化します。同じユニット(またはドロップイン)をfleet全体に配布しつつ、設定した割合のマシンでのみ条件が真になるようにするものです。判定は完全にローカルで行われます — マシンIDをタグ文字列と一緒にハッシュして32ビット整数を作り、その値が2^32の指定パーセントより小さければ真になります(NEWSの説明による)。中央の調整役はなく、ネットワーク呼び出しもなく、同じマシンは常に同じ判定を受けます。

文法はパーセント一つ、またはタグとパーセントの組み合わせです。パーセントは小数点第2位まで許容されます。

# /etc/systemd/system/telemetry-v2.service.d/rollout.conf
# fleetの約10%でのみこのユニットが有効になる
[Unit]
ConditionFraction=telemetry-v2 10%

感嘆符を前に付けると補集合になります — manページの例をそのまま持ってくると、!myrollout 30%は残りの約70%のマシンで真になります。新旧バージョンを排他的に分けて運用するのにそのまま使えます。

# 旧バージョン側のユニット: 同じタグの補集合でのみ有効になる
[Unit]
ConditionFraction=!telemetry-v2 10%

ここでタグが果たす役割が重要です。タグはハッシュの導出に混ぜ込まれる任意の文字列(空白不可)であり、タグが異なれば互いに独立な部分集合が選ばれます。逆に言えば、タグなしのConditionFraction=条件はすべて同じマシン集合を選びます — タグなしで10%ロールアウトを2つ走らせると、2つの実験はまったく同じマシンに重なります。無関係なロールアウトには必ず異なるタグを使い、複数のユニットを同じマシン集合に結びつけたいときだけタグを共有せよ、というのがmanページの指針です。マシンIDが読めない場合、条件は失敗(偽)になります。

デプロイ前に特定のマシンで判定を事前確認することもできます。systemd-analyze conditionコマンドは条件文字列をその場で評価してくれます。

systemd-analyze condition 'ConditionFraction=telemetry-v2 10%'

これはカナリアデプロイシステムではない

ここで正直になっておく部分です。「PID 1にカナリアロールアウトが来た」という文は半分だけ正しいです。ConditionFraction=が提供するのは母集団選択だけであり、カナリアデプロイをカナリアデプロイたらしめる残りの部分 — 観測、判定、中断 — はまったく提供しません。

では、どこで使うために作られたのでしょうか。manページが明示する用途そのまま、同じアーティファクトをfleet全体に配布するイメージベースシステムの段階的な露出です。OSTreeやUKIイメージのように、マシンごとに異なるファイルを配布できない(したくない)環境では、「全員に配布しつつ一部でだけ有効にする」が事実上唯一のロールアウト手段です。中央の調整なしに決定論的に動くという性質は、この環境では欠点ではなく要件です。逆にKubernetesや構成管理ツールでマシンごとのデプロイ制御がすでにできている環境なら、この機能が新しく開く扉はほとんどありません。

意図的なリング分けが必要なら、ランダムな割合の代わりに新しく入ったタグシステムを使います。v261からマシンは/etc/machine-infoTAGS=フィールドにタグの一覧を持てるようになり、hostnamectl manソース基準でhostnamectl tagsで照会・置換します(タグは1〜255文字のASCII英数字、ハイフン、ドット)。ユニット側ではConditionMachineTag=がシェルのglobパターンでタグを検査します。

# ring0タグが付いたマシン(社内dogfoodリング)でのみ有効になる
[Unit]
ConditionMachineTag=ring0

AssertMachineTag=も一緒に追加され、NEWSによればsystemd-firstbootがコマンドライン引数やcredentialでプロビジョニング時にタグを埋め込めます。まとめるとこうなります — 明示的なリングはタグで、リング内のランダムな割合はfractionで。観測と判定はあなたのモニタリングで。この分業が設計意図に最も近い読み方です。

IMDSサブシステム — systemdがcloud-initの庭に入ってきた

v261はクラウドインスタンスメタデータサービス(IMDS)を扱うサブシステム一式を新しく搭載しました。構成要素はかなり多くあります。

運用者が注意すべき部分はネットワークロックです。カーネルコマンドラインsystemd.imds.network=はoff、locked、unlockedの3つの値を取り、lockedモードではIMDSエンドポイントへのprohibitルートが敷かれ、非特権プロセスによる直接アクセスが遮断され、すべてのアクセスがsystemd-imdsdを経由する必要があります。IMDS credential窃取がクラウド侵害の常套手段だったことを考えれば、方向性自体は妥当です。問題はNEWS自身が書き残している一文です — このロックはセキュリティ上推奨されるものの、IMDSへの直接アクセスを前提とするcloud-initのような従来型クライアントと「typically conflicts」、つまり大抵は衝突します。

デフォルトが何かという問いには、文書が食い違った答えをします。meson_options.txtimds-networkオプションは明示的なデフォルトなしにchoicesがunlocked、lockedの順であり、アップストリームのソース基準ではデフォルトはunlockedになります(mesonのcomboオプションは最初の項目がデフォルト)が、manページのカーネルスイッチの説明にはlockedがデフォルトだと書かれています。実際のあなたのシステムでのデフォルトはディストリビューションがビルド時に何を選んだかに依存するので、cloud-initと一緒に使うイメージなら、ディストリビューションのパッケージのビルドオプションを確認するのが安全です。

一つはっきりさせておく必要があります。これはcloud-initの代替物ではありません — 少なくとも今のところは。systemd-imdsがすることはメタデータフィールドをcredentialとして取り込むところまでで、cloud-configの解釈、パッケージのインストール、ユーザー作成といったプロビジョニングロジックは範囲外です(NEWSもmanページもそういう主張はしていません)。ただ、hostname、SSH鍵、user-dataがcredential体系に入り始めたということは、単純なプロビジョニング要求ならsystemdの純正部品だけで処理される未来への第一手として読むのが自然です。cloud-init側がこのロックモードとどう共存するかは、今後見守るべき問題です。

dlopen移行の完成 — そしてrsyslogが壊れた経緯

2024年3月のxz-utilsバックドア(CVE-2024-3094)は、ディストリビューションがsshdにlibsystemdをリンクしていたことを通り道にしました — liblzmaがlibsystemdの推移的依存としてsshdプロセスに乗り込んだのです。3か月後の2024年6月に出たv256から、systemdはまさにそのliblzmaを含む5つのライブラリ(liblz4、libzstd、liblzma、libkmod、libgcrypt)を通常のリンクからdlopen()ベースに変え始め、リリースのたびに対象を広げてきました。

v261がこの作業の終着点です。今回libgnutls、libmicrohttpd、libcurl、libcrypto、libssl、libfdisk、libcryptsetupまで変換され、NEWSは枠で囲んで宣言しています — 外部ライブラリへの直接リンクはこれで全部dlopen()に置き換わり、唯一の例外はlibcだと("with the sole exception of libc")。どのdlopen依存があるかは各バイナリに埋め込まれるELF dlopen metadataノートで宣言されるので、パッケージングツールがオプション依存を機械的に把握できます。

この方向の利点は明らかです — プロセスに乗るコードが減り、最小イメージから外せるライブラリが増え、xz事件のような推移的依存の攻撃面が狭まります。ところがこの移行は逆方向の落とし穴も作ります。libsystemdがこれまで他者の代わりに引き込んでくれていたライブラリが消えるということです。

v261のNEWSに載った実際の事例が正確にこれです。libsystemdがlibm(数学ライブラリ)にリンクされるという保証が消えると、libmのシンボルを使っていながらlibm自体をリンクしていなかったlibfastjsonの問題が露呈し、その結果rsyslogが起動時にクラッシュします。これまではlibsystemdがlibmを引き込んでくれていたおかげで隠れていたバグです。NEWSは根本修正(libfastjsonがlibmを直接リンクする)がされるまでの暫定的な回避策としてリンカーフラグを提示しています。

-Wl,--push-state,--no-as-needed,-lm,--pop-state

教訓はrsyslogに限りません。libsystemdにリンクするソフトウェアをビルドまたはパッケージングしているなら、これまで「たまたまリンクされていた」推移的依存に頼っていなかったか確認する時です。使うシンボルは直接リンクせよという原則が、いま文字どおり強制され始めています。

アップグレード前チェックリスト — 静かに嚙みつくもの

NEWSの非互換な変更のリストから、実際の運用に触れるものだけを拾いました。

文脈を一つ補うと、このリストはv258から始まった削除の流れの続きです。v258(2025-09)がcgroup v1とSystem Vの状態制御(runlevel、telinit、init 3)を廃止し、v260(2026-03)がSystem Vサービススクリプトのサポート(systemd-sysv-generator、rc-local.service)をさらに廃止しました。まだSysVスクリプトで配布されている社内デーモンがあるなら、すでにv260系のディストリビューションでは起動時に上がってきません。

その他注目すべき点

紙幅の都合で短くまとめますが、環境によっては上記より重要になりうる項目です。

それで誰がいつ気にすべきか

まとめると対象別にこうなります。

今すぐ — confidential computingでRTMR/PCRベースのattestationを検証している側(測定値が変わります)、libsystemdにリンクするソフトウェアのパッケージャー(推移的依存の整理)、rsyslogを自前ビルドしている側。ローリングリリース系ならすでにv261が届いています。

設計に反映すべき時点 — イメージベースのfleetを運用しているチーム。ConditionFraction=とマシンタグは、これまで外部ツールで模倣していた段階的な露出をユニットファイルの文法に落とし込みます。ただし前述のとおり、観測・判定・ロールバックは依然としてあなたの仕事だという前提で設計してください。IMDSサブシステムは、cloud-init依存を減らしたかったミニマルイメージ陣営にとって、実質的な選択肢になり始めています。

まだ余裕がある — LTSディストリビューションに留まる大半のサーバー運用者。Ubuntu 26.04はv259で、大半のエンタープライズディストリビューションはそれよりさらに後ろにいます。ただしv258以降の削除の流れ(cgroup v1、SysVスクリプト、udev DB v0)は次のメジャーアップグレードでまとめて届くので、レガシー依存があるなら、リストだけでも先に作っておくといいでしょう。

おわりに

v261を一文に縮めるとこうなります — systemdはもはや一台のマシンを起動するソフトウェアではなく、fleetの最小単位を自任するソフトウェアになりました。ConditionFraction=はロールアウトの母集団選択を、タグはリング区分を、IMDSサブシステムはクラウドコンテキストの取り込みを、それぞれPID 1の文法にしました。どれも既存のオーケストレーションを置き換えるわけではありませんが、3つとも「これまで必ず外部ツールが必要だったこと」のリストを少しずつ減らします。

同時にこのリリースは、systemdが自分自身にも同じ原則を適用していることを示しています。dlopen移行の完成は、xz事件が露わにした推移的依存の問題への2年がかりの答えであり、rsyslogの事例はその答えがエコシステムに請求するコストです。アップグレード自体はいつもの四半期リリースのように無難でしょうが、attestationの期待値と推移的依存 — この2つだけは、リリースノートを読まなかったチームを正確に嚙む種類の変更です。この記事がそのリストの代わりになっていれば幸いです。

参考資料

コメント

まだコメントはありません。

ログインするとコメントできます