ホットプラグ(CPU・メモリ)とオフライン化の機構
クラウドのCPU/メモリ増減や障害コア切り離しが、なぜ稼働中に無停止でできるのかが腑に落ちます。オンライン/オフラインの状態遷移とタスク退避、メモリのセクション管理を原理から押さえられます。
- 1.CPUオフラインはコールバックチェーンを逆順に降りる多段の状態遷移で、最後にstop_machineで全タスクとタイマ・割り込みを生存CPUへ退避してから論理的に外す。
- 2.メモリホットプラグはセクション(既定128MiB)単位でstruct pageを起こしてオンライン化し、オフライン時はそのページ範囲を回収・マイグレーションして無使用にできて初めて外せる。
- 3.仮想化/クラウドではこの機構が垂直スケーリングと障害隔離の土台で、ZONE_MOVABLEやballooningがオフライン成功率を左右する。
なぜ稼働中にCPUやメモリを着脱できるのか
ホットプラグとは、システムを停止せずにCPUコアやメモリを論理的に追加・削除する機構です。物理的な抜き差し(大型サーバーのCPU/メモリボード交換)だけでなく、現代では仮想化での意味が主役になりました。クラウドのVMに後からvCPUを足す、過剰割当を返す、障害が検知されたコアを切り離す——これらはすべてゲストOSのホットプラグ経路を通ります。
無停止で着脱できるのは、OSがハードウェア構成を起動時に固定せず、CPUやメモリ範囲を後から増減できる動的な内部状態として持っているからです。鍵は「論理的なオンライン/オフライン」と「物理的な存在(present)」を分離している点にあります。コアが物理的に存在していても、OSがそれを使わない(offline)状態に置けば、スケジューラはそのコアにタスクを置かず、割り込みも振り向けません。逆にオンライン化は、そのコアを使える状態へ段階的に引き上げる手続きです。
LinuxはCPUを3つのマスクで管理します。possibleは起動時に確定する「将来あり得る最大集合」、presentは「現在物理的に挿さっている集合」、onlineは「いま実際にスケジューリング対象な集合」です。ホットプラグはpresentの範囲内でonlineを増減する操作で、possibleはper-CPU領域を確保するための上限として効きます。/sys/devices/system/cpu/cpuN/onlineに1/0を書くのがユーザー空間からの起点です。
CPUオフライン:状態機械を逆順に降りる
CPUのオンライン/オフラインは、単なるフラグ反転ではなく多段の状態遷移です。Linuxは各サブシステムが「このCPUが立ち上がるとき・落ちるときに何をするか」をコールバックとして登録し、それらを一列の**状態(state)**として並べます。オンライン化はこの列を下から上へ昇り、オフライン化は逆順に降ります。各段が前段の成立を前提にするため、順序の正しさが整合性を保証します。
オフラインで最も重要なのは、そのCPU上に残っているものをすべて他のCPUへ退避してから論理的に外す点です。具体的には次を生存CPUへ移します。
オフライン化で退避するもの:
- 実行可能タスク(runqueue上のタスクを他CPUへマイグレート)
- 高精度タイマ・タイマホイール上のタイマ
- そのCPUを宛先にしていた割り込み(IRQアフィニティの付け替え)
- per-CPUのワークキュー項目
最後に: stop_machine で全CPUを一時停止し、対象CPUを論理的にオフラインへ
退避の総仕上げが stop_machine です。これは全CPUで他の実行を止め、安全点を作って対象CPUを最終的にラインから外す仕組みで、この瞬間だけは系全体が短時間ストールします。タスクの移動はランキューを跨ぐマイグレーションそのものなので、退避先の選定にはロードバランサとCPUアフィニティ/ロードバランシングの仕組みがそのまま効きます。なお、外そうとするCPUにアフィニティでピン留めされたタスクがあると、退避先が無く移動に失敗しうる——これがオフラインが止まる典型原因です。
多くのx86システムでCPU0(ブートストラッププロセッサ)はオフラインにできません。一部の割り込み配送やレガシーなタイマ経路がCPU0に固定的に紐づくためで、CONFIG_BOOTPARAM_HOTPLUG_CPU0 などの条件が揃わない限りオフライン要求は拒否されます。「最後の1コアは外せない」という直感とは別に、「特定の0番が外せない」という制約がある点に注意します。
オンライン化と、タスク・割り込みの引き戻し
オンライン化は逆向きの昇りです。対象CPUを起こし(ハードウェア的にはIPIで叩き起こす)、per-CPU領域・タイマ・ランキューを初期化し、最後にスケジューラのオンラインマスクへ加えます。マスクに入った瞬間からロードバランサがそのCPUを均し先として認識し、過密な他CPUからタスクが流れ込んで負荷が再分配されます。割り込みも、明示的に固定していなければirqbalance等が新CPUを宛先候補に含め始めます。
ここで効くのがコールバック順序の対称性です。オンラインで段Aの後に段Bを実行するなら、オフラインではBを巻き戻してからAを巻き戻す。各サブシステムがこの規律で登録するため、途中で失敗してもそこまでの段だけを正しく逆順に巻き戻せます。状態遷移としてのスケジューラの捉え方はスケジューラの状態機械とも地続きで、ランキューへの出入りという同じ語彙で説明できます。
メモリホットプラグ:セクション単位の管理
メモリはCPUより粒度の問題が重くなります。Linuxは物理メモリをセクションという固定単位(多くのアーキテクチャで既定128MiB)に区切り、sparsememモデルでセクションごとに「存在するか」「オンラインか」を管理します。ホットプラグの最小単位は基本的にこのセクション、運用上はそれを束ねたメモリブロック(/sys/devices/system/memory/memoryN)です。
物理ページを管理するには、各ページに対応する struct page メタデータ(ページごとに数十バイト)が必要です。追加メモリをオンライン化するとは、このメタデータ配列をまず用意してから、対象ページ範囲をアロケータ(buddyのフリーリスト)へ投入することを指します。順序は「物理範囲の登録 → struct pageの確保と初期化 → ゾーンへ編入してオンライン → アロケータへ解放」です。
メモリオンライン化の流れ:
1. 新セクションの物理範囲を登録(present扱いにする)
2. その範囲の struct page を確保・初期化(mem_map を起こす)
3. ページを所属ゾーン(Normal / Movable)へ編入し online 化
4. buddyアロケータのフリーリストへ投入 → 割当可能になる
struct pageの巨大な配列をどこに確保するかは設計上の難所です。新たに足したメモリをオンライン化する前にメタデータ領域が要るという鶏卵問題があるため、vmemmapでは追加メモリ自身の一部をstruct page置き場として使う方式(memmap_on_memory)が用意されています。これにより別ノードの既存メモリを食わずに大容量を編入でき、NUMA配置の偏りも避けられます。
メモリオフライン:回収とマイグレーションが要
メモリのオフラインはCPUよりはるかに難しく、成功が保証されません。理由は単純で、外したい物理ページが現在使用中かもしれないからです。外すには対象セクション内の全ページを無使用にする必要があり、カーネルは2つの手段を併用します。1つは回収(reclaim)——ページキャッシュや無名ページをスワップ/書き戻して空ける。もう1つはマイグレーション——使用中ページの中身を、オフライン対象外の別ページへコピーして付け替える。
決定的なのは、**移動できないページ(unmovable)**が1つでも範囲内にあると、その範囲はオフラインにできないことです。カーネル自身のスラブ、ページテーブル、固定(pin)されたDMAバッファなどは物理アドレスを動かせません。だからメモリホットプラグを前提にするなら、抜く可能性のある範囲には移動可能ページしか置かない設計が要ります。それを担うのが ZONE_MOVABLE です。
| 観点 | ZONE_NORMAL | ZONE_MOVABLE |
|---|---|---|
| 置けるページ | カーネルの移動不可ページを含む全種 | 移動可能なユーザーページ等に限定 |
| オフライン可否 | unmovableが混ざると不可になりやすい | 原則すべて退避でき外しやすい |
| 用途 | 通常の割当先・カーネル作業領域 | ホットプラグで抜く前提の領域 |
| 代償 | — | カーネルが使えずメモリ効率は下がる |
unmovableページが範囲に紛れる遠因は断片化です。空きはあっても移動不可ページが点在すると連続範囲を空けきれません。連続領域を作り直す仕組みはメモリコンパクションと断片化で扱うとおりで、ホットプラグのオフライン成功率はこの断片化対策と表裏一体です。
1ページでも退避先が見つからない、あるいはpinされて動かせないと、オフライン処理はそのページを諦めきれずリトライを続け、実質的にハングしたように見えることがあります。本番でメモリを抜く運用は、対象を最初からZONE_MOVABLEに寄せる・巨大なhugepageやDMA固定を範囲外に置く、といった事前設計が無いと安定しません。「いつでも抜ける」前提でメモリホットプラグを使うのは危険です。
仮想化・クラウドでの用途
ホットプラグが日常的に効くのは仮想化です。ゲストから見れば物理的な抜き差しと同じ経路を、ハイパーバイザがエミュレートされたACPIイベントとして通知します。vCPU追加ならKVM/QEMUの構成でvCPUスレッドを1本起こし、ゲストへホットプラグ割り込みを上げ、ゲスト側が前述の昇り遷移でオンライン化する——という二段構えで完結します。
メモリ側はさらに踏み込んだ最適化があります。balloonドライバは、ゲスト内に「膨らんだ風船」としてページを確保してホストへ返すことで、物理的なメモリ抜き差し無しに実効割当を絞ります。さらに virtio-mem は、デバイスが提供する大きな範囲の中をブロック単位でオンライン/オフラインし、ホットプラグそのものを細粒度・高頻度な操作として実用化しました。いずれも、これまで見たセクション管理・ZONE_MOVABLE・マイグレーションという土台の上に成り立っています。
押さえどころは4点です。(1) CPUオフラインは逆順の状態遷移+stop_machineで、ピン留めタスクがあると失敗しうる。(2) CPU0は外せないことがある。(3) メモリはセクション単位でstruct pageを起こして編入し、(4) オフラインは全ページ退避が条件のため、ZONE_MOVABLEとunmovableページの有無が成否を分ける。「CPUは比較的安全に外せるが、メモリは保証されない」という非対称が頻出の急所です。
まとめ
- ホットプラグはハードウェア構成を起動時に固定せず、論理的なオンライン/オフラインと物理的存在を分離することで無停止の着脱を実現する。
- CPUオフラインはコールバックチェーンを逆順に降り、タスク・タイマ・割り込みを生存CPUへ退避し、最後にstop_machineで論理的に外す。CPU0やピン留めタスクが制約になる。
- メモリはセクション(既定128MiB)単位でstruct pageを起こして編入し、オフラインは全ページの回収・マイグレーション成功が条件——unmovableページがあると外せない。
- 仮想化/クラウドの垂直スケーリングと障害隔離はこの機構が土台で、ZONE_MOVABLE・balloon・virtio-memがオフライン成功率と粒度を支える。
OS Article
ホットプラグ(CPU・メモリ)とオフライン化の機構を実務で読む
TL;DRは入口です。実際に選ぶ・使う段階では、何を解決するか、何と比較するか、導入後にどこで詰まるかまで見る必要があります。
解決すること
ホットプラグ
比較で見る軸
難易度: advanced / カテゴリ: OS / タグ数: 6
導入後に効く点
メモリホットプラグはセクション(既定128MiB)単位でstruct pageを起こしてオンライン化し、オフライン時はそのページ範囲を回収・マイグレーションして無使用にできて初めて外せる。
先に潰すリスク
用語だけ覚えても、設計・実装・運用でどこに効くかを確認しないと判断を誤る。
- 難易度
- advanced
- カテゴリ
- OS
- タグ数
- 6
判断チェックリスト
- 自社の用途が「ホットプラグ / CPU」に近いか確認する。
- 強みである「CPUオフラインはコールバックチェーンを逆順に降りる多段の状態遷移で、最後にstop_machineで全タスクとタイマ・割り込みを生存CPUへ退避してから論理的に外す。」が本当に評価軸になるか確認する。
- 注意点の「用語だけ覚えても、設計・実装・運用でどこに効くかを確認しないと判断を誤る。」を運用で吸収できるか確認する。
- 公開値や仕様値は、対象プラン・対象機種・対象リージョンまで確認する。
- 既存システム、ID、ネットワーク、監視、バックアップとの接続方法を先に洗い出す。
- 小さく試してから、本番移行、権限設計、障害時手順、コスト監視を決める。