メインコンテンツに移動

Amazon EC2 Nested Virtualization と Amazon EKS で実現するセキュアなマルチテナントビルド基盤

2026-09-02 | Author : 大山 隆介 ( GMOペパボ株式会社), 鈴木 祥太

Missing alt text value

はじめに

GMOペパボは「ロリポップ!レンタルサーバー byGMOペパボ」をはじめとするホスティングサービスを 20 年以上運営してきました。2026 年 7 月には、Web アプリケーションをコマンド一つで公開できる新サービス「ロリポップ!デプロイナウ byGMOペパボ」の提供を開始しました。

本サービスの中核には、「利用者から預かったソースコードを、当社の環境でビルドする」という工程があります。これは言い換えれば、不特定多数の書いたコードを日常的に実行し続ける環境を運用するということです。

本記事では、この課題に対して Amazon Elastic Kubernetes Service(Amazon EKS)、Tekton、Kata Containers を組み合わせ、Amazon Elastic Compute Cloud (Amazon EC2) の Nested Virtualization の機能によって実現したセキュアなマルチテナントビルド環境について、アーキテクチャと実装、導入効果を紹介します。
 

X ポスト » | Facebook シェア » | はてブ »

builders.flash メールメンバー登録

builders.flash メールメンバー登録で、毎月の最新アップデート情報とともに、AWS を無料でお試しいただけるクレジットコードを受け取ることができます。

今すぐ登録 »

1. 「ロリポップ!デプロイナウ byGMOペパボ」とは

「ロリポップ!デプロイナウ byGMOペパボ」は、 Web ホスティングサービスです。利用者は手元のソースコードから CLI を一回実行するだけで、ビルドから公開までを数分で完了できます。CI/CD パイプラインの構築は不要です。

「ロリポップ!デプロイナウ byGMOペパボ」の基盤では、アップロードされたソースコードを当社のビルド環境でビルドしてコンテナイメージ化し、AWS Lambda 上で稼働させ、Amazon CloudFront から配信します。サービス利用者の体験は「ソースコードを渡すだけでそのプログラムが公開できる」だけですが、その裏側では「サービス利用者のソースコードをビルドする」ビルド環境が存在しています。本記事の主題はこのビルド環境です。 

2. 「ロリポップ!デプロイナウ byGMOペパボ」のビルド環境における課題

2-1. 利用者コードのビルドは任意コード実行である

「ソースコードを渡すだけでそのプログラムが公開できる」という体験を提供する以上、ソースコードのビルドはサービス側で引き受けることになります。ビルドと聞くと静的な変換処理を想像するかもしれませんが、実際には利用者の書いた任意のコードを実行する工程です。たとえば npm run build は利用者が package.json に書いたスクリプトをそのまま実行しますし、ビルドは利用者の設定ファイルやビルド時コードを Node.js プロセスとして実行します。依存パッケージ取得時の lifecycle script は無効化することでコード実行を制御できますが、ビルドそのものの実行は無効化できません。

2-2. マルチテナント環境での分離要件とコンテナベースの分離の限界

「ロリポップ!デプロイナウ byGMOペパボ」のビルド環境は多数の利用者で共有されるマルチテナント型のため、この環境を分離には 2 つの方向があります。利用者同士の分離 (あるビルドが他の利用者のビルドやその成果物に干渉できないこと) と、利用者とビルド環境の分離 (ビルド中のコードがデプロイナウの認証情報や内部ネットワークに到達できないこと) です。悪意ある利用者だけでなく、正規の利用者が使う依存パッケージが侵害されるサプライチェーン攻撃も同じく脅威になります。

環境分離における選択肢として考えられる Kubernetes 標準のコンテナランタイム (runc) による分離はホストカーネルの分離機構に依存します。コンテナ同士がカーネルを共有するこの構成には、2 つの弱点があります。

1 つはエスケープです。カーネルの脆弱性一件で境界が破れ、ホストや他のコンテナに到達される可能性があります。

もう 1 つは共倒れです。コンテナの内側から発行できるシステムコールがカーネル側の欠陥を踏んでカーネルパニックを引き起こすと、同じノードで動く他の利用者のビルドがまとめて止まります。

NULL ポインタ参照のような、エスケープには至らないもののカーネルを停止させ得る脆弱性は継続的に報告されており、前節のとおりビルドは任意のコードを実行する工程であるため、こうした欠陥を意図的に狙うコードも想定に入れる必要があります。自社のワークロードだけを動かすクラスターであれば管理可能なリスクですが、不特定多数のコードを実行し続けるビルド環境では受け入れられないものでした。

2-3. ビルド環境のクリーンさと再現性

ビルドのたびに環境が使い捨てられることも要件になります。前のビルドの残骸 (キャッシュ、一時ファイル、生き残ったプロセス) が次のビルドの結果に影響してはならず、仮にあるビルドで環境が侵害されても、それが後続のビルドへ持ち越されてはなりません。「同じソースコードなら同じ環境で同じようにビルドされる」ことを、後片付けの運用ではなく、毎回新たな環境が用意される構造で保証したいと考えました。

2-4. コストとスケーラビリティの両立

ここまでの要件は「ビルドごとに使い捨ての VM で分離する」ことで実現できることを示唆しますが、素直な実現手段はどれも別の要件と衝突します。

ビルドごとに EC2 インスタンスを直接起動すれば分離は満たせますが、ビルドのたびにインスタンスの起動を待機することになり、かといって EC2 インスタンスを使い回せば、ビルドごとに環境を使い捨てるという前提が崩れます。VM レベルの分離を Kubernetes 上で実現する Kata Containers であれば、ワーカーノードを共有したままビルドごとに軽量な VM を起動して使い捨てられますが、ハードウェア仮想化支援 (KVM) が必要となり、KVM のようなハードウェア仮想化支援の実行は Amazon EC2 では従来ベアメタルタイプのインスタンスに限られていました。しかし、ベアメタルタイプのインスタンスは最小でも 48 vCPU とインスタンスサイズが大きく、確保する vCPU リソースの単位を細かく制御することが困難です。

一方で、ビルドという負荷は短時間に集中しアイドル時間が長いのが特徴です。新規サービスとして小さく始め、需要に応じて細かい粒度でスケールできることがサービスの原価構造の成立条件でした。「ビルドごとの VM 分離」「使い捨ての速さ」「確保する vCPU リソースの単位の細かな制御」の 3 つを同時に満たす手段が課題として残りましたが、これを解いたのが Amazon EC2 Nested Virtualization でした。

3. Amazon EC2 Nested Virtualization とは

前章では、「ロリポップ!デプロイナウ byGMOペパボ」のビルド環境における課題について紹介しました。本章では、これらの課題を解決するために活用した Amazon EC2 Nested Virtualization の機能概要について解説します。

3-1. Amazon EC2 Nested Virtualization の概要

ユーザーが作成したコードをサーバー側でビルドするサービスでは、実行されるコードの内容を事前に把握できません。こうしたワークロードに対して、コンテナよりも強固な分離境界を求める場合、従来はハードウェア仮想化を利用できるベアメタルインスタンスを選択する必要がありました。Amazon EC2 Nested Virtualization は、この制約を解消するために 2026 年 2 月に一般提供が開始された機能です。

Nested Virtualization は、ベアメタル以外の通常の EC2 インスタンス内での Hyper-V や KVM などのハイパーバイザーの実行を可能にします。この機能は、EC2 インスタンスにプロセッサレベルの仮想化サポートを追加することで仮想化の柔軟性を高め、インスタンス内で実行されているハイパーバイザーが仮想マシンを作成して管理できるようになります。

これまでは、ベアメタル EC2 インスタンス内でのみハイパーバイザーによる仮想マシンの作成と管理が可能でした。Nested Virtualization の登場により、特定のパフォーマンス要件と料金要件を満たす標準的なインスタンスタイプを選択しながら、ハードウェア仮想化による分離境界を利用できるようになりました。また、Nested Virtualization の使用に追加料金はかかりません。

3-2. アーキテクチャ

仮想 EC2 インスタンスは、Nitro Hypervisor を使用する物理ホストで実行されます。ネストされた仮想化をサポートするため、AWS Nitro System はプロセッサ拡張機能 (Intel VT-x など) をインスタンスに渡して、ネストされた仮想マシンの実行を円滑化します。

ネストされた仮想化のアーキテクチャは、次の 3 つのレイヤーで構成されています。

  • L0 : 物理的な AWS インフラストラクチャと Nitro Hypervisor です。AWS が管理するレイヤーで、EC2 インスタンス間の分離境界を提供します。
  • L1 : ハイパーバイザーを実行する EC2 インスタンスです。お客様が KVM や Hyper-V を導入し、その上の仮想マシンを管理します。現在サポートされている L1 ハイパーバイザーは、KVM と Hyper-V です。
  • L2 : L1 のインスタンス内で作成された 1 つ、または複数の仮想マシンです。ゲスト OS やアプリケーションが動作する、実際のワークロードの実行環境となります。

3-3. 利用にあたっての考慮事項

設計に入る前に押さえておきたい点を整理します。なお、以下は本記事の執筆時点の情報となるため、最新の情報は公式ドキュメントをご確認ください。

  • サポートされているインスタンスタイプ : 現在、C8i、M8i、R8i、C8id、R8id、M8id、C8i-flex、R8i-flex、M8i-flex、X8i、C7i、R7i、M7i、C7i-flex、M7i-flex、I7i インスタンスでサポートされています。
  • サポートされるハイパーバイザー : L1 のハイパーバイザーとしてサポートされるのは、KVM と Hyper-V です。
  • Windows インスタンス : Windows インスタンスでネストされた仮想化を有効化した場合、Virtual Secure Mode (VSM) が自動的に無効化されます。また、インスタンスの hibernate と resume はサポートされず、CPU 数が 192 個を超える Windows インスタンス (m8i.96xl など) ではサポートされません。
  • パフォーマンス : ハードウェア仮想化機能を必要とし、パフォーマンス依存、厳しいレイテンシー要件を持つワークロードなどの実行する場合、ベアメタルインスタンスの利用を検討することをお勧めしています。Nested Virtualization はベアメタルインスタンスを常に置き換えるものではなく、要件に応じて各選択肢を使い分けることが大事になります。

3-4. 想定されるユースケース

開発ワークフローにおける Docker Desktop、Windows Subsystem for Linux 2 (WSL2)、Android Studio エミュレータ、QEMU といった開発ツールの実行をする際に役立つ機能として、AWS が公式ドキュメントや What's New といった主要記事で紹介しています。また、モバイルアプリケーションのエミュレーターの実行、自動車の車載ハードウェアのシミュレーション、Windows ワークステーション上での Windows Subsystem for Linux の実行といったユースケースも挙げられています。

Amazon EC2 Nested Virtualization の詳細については、Amazon EC2 ユーザーガイド や AWS What's New もあわせてご参照ください。

4. Amazon EC2 Nested Virtualization + Amazon EKS + Tekton による課題解決とアーキテクチャ

4-1. Amazon EC2 Nested Virtualization の採用判断

構成の検討で一貫して優先したのは 2 点です。1 つはコスト効率です。ビルドごとに専用のインスタンスを確保するのではなく、共有ノードに使い捨ての実行環境を高密度に集約することで、低価格なホスティングサービスとして成立する原価に抑えます。もう 1 つは、小規模なチームで維持し続けられることです。分離やスケールのコア機構を自前実装せず、広く使われている部品の組み合わせに留めます。

ビルドの実行だけを切り出せば、マネージドな CI/CD サービスに任せる選択肢もあります。それでもビルド環境を自分たちで組んだのは、本サービスにとってビルドの実行環境が製品の一部だからです。どの工程に何の権限を与えるか、各種ログや脆弱性スキャン結果を利用者へどう返すか、分離をどう強制するかといった細部が利用者の体験とセキュリティをそのまま決めるため、ランタイムからポリシーまでを宣言的に制御できる必要がありました。

この 2 点を貫くと、ここまでの課題に対する解の形はおのずと絞り込まれます。コア機構を自前実装しない以上、VM 分離は VM オーケストレーションの自作ではなく、Kata Containers への Kubernetes のランタイム差し替えとして実現することになります。しかし、ベアメタルインスタンスを採用し Kata Containers が要求する KVM の利用環境を実現すると、2-4 章で述べた通り確保する vCPU リソースが最低でも 48 コアと大きくなってしまい、今度は実行環境の集約によるコスト効率が崩れます。つまり、私たちの設計思想は「仮想 EC2 インスタンスのまま KVM が使えること」を要求しており、Amazon EC2 Nested Virtualization はこの欠けていた最後のピースにちょうどはまりました。

対応をまとめると次の通りです。

  • 分離要件 : Kata Containers (kata-qemu) により、ビルド Pod を 1 Pod = 1 QEMU/KVM micro-VM として実行する。テナント間の境界を VM とし、VM 内では コンテナ境界で権限を絞る
  • クリーンさと再現性 : 1 ビルド = 1 Pod = 1 VM とし、ビルド終了とともに VM ごと破棄する
  • コストとスケーラビリティ : Amazon EC2 Nested Virtualization により仮想 EC2 インスタンスで KVM を利用し、ベアメタルインスタンスを利用せず Cluster Autoscaler でオンデマンドスケールを行う

4-2. 全体アーキテクチャ

デプロイの流れは次のとおりです。

デプロイの流れ

「ロリポップ!デプロイナウ byGMOペパボ」のコントロールプレーンは、受け付けたデプロイ要求をビルドジョブとしてキューイングします。その後、ビルド専用の Amazon EKS クラスタにジョブを Kubernetes のリソースとして実行する CI/CD フレームワークである Tekton の TaskRun を作成します。この TaskRun は Tekton において一連のコンテナ順次実行を定義した「Task」リソースをインスタンス化し、実際に定義した順序実行処理を Pod として Kubernetes クラスタ上で実行・追跡するためのカスタムリソースとなります。ビルドが完了するとコンテナイメージが Amazon Elastic Container Registry  (Amazon ECR ) に push され、コントロールプレーンが AWS Lambda の関数を更新して WEB サイトの公開が完了します。

本記事で扱うビルドを実行する専用の Amazon EKS クラスター (ビルドクラスタ) は、コントロールプレーンとは別 VPC に配置し、コントロールプレーンとビルドクラスターそれぞれの VPC 間で VPC ピアリングは設定せず、機能の結合は AWS の API とビルドクラスターの Kubernetes API (IAM 認証を利用) だけに絞って利用し実施しています。VPC ピアリングを利用せず Amazon EKS のパブリックエンドポイント経由で Kubernetes API にアクセスをすることで、ビルドクラスターからはコントロールプレーンに対するネットワーク到達性を完全に無くす一方で、コントロールプレーンからはビルドクラスターにアクセスすることができるという片方向のみのネットワーク経路を実現しました。これにより、ビルドクラスターへ何かしらの攻撃や侵害があった際にその影響範囲を最小に留めることができます。このように、信頼できないコードが実行されるコンポーネントであるビルドクラスターと秘匿情報を保持するコントロールプレーンをネットワークレベルで分離し、信頼できないコード実行などによるコントロールプレーンへの侵害リスクを減らしています。なお、ビルドクラスターがパブリックエンドポイントを保持する点については、接続元 CIDR 許可リストの設定や Amazon EKS の Access Entry での権限制御を行いセキュリティリスクを最小化しています。

4-3. Kata Containers による Pod 単位の VM 分離

ビルドクラスタには Kata Containers ランタイムを kata-deploy でインストールし、RuntimeClass kata-qemu として登録しています。kata-deploy は、Kata Containers のバイナリ一式を DaemonSet で全ノードに配布し、containerd/CRI-O と RuntimeClass まで自動設定してくれる公式インストーラです。これにより、TaskRun 作成時に spec.podTemplate で RuntimeClass を指定すると、ビルド Pod は kata-qemu shim によって独立した QEMU/KVM micro-VM として起動できます。

kata-deploy
xml
spec:
  podTemplate:
    runtimeClassName: kata-qemu
    tolerations:
      - key: runtime
        operator: Equal
        value: kata
        effect: NoSchedule

これによって起動されるゲスト VM は専用のゲストカーネルを持ち、ホストカーネルを共有しません。

また、この手法による環境分離の境界は 2 層あります。第 1 の境界はコンテナ境界で、利用者コードはビルド処理に必要な最低限の操作のみが実行可能 (詳細は 5-2 章で解説)、かつ Kubernetes の Service Account Token や AWS IAM に関する Token といった認証情報を持たないコンテナの中で実行されます。第 2 の境界がこの micro-VM です。仮に第一の境界が破られても到達できるのはその VM の内側までとなり、ホストカーネルや他の利用者のビルドには届きません。ゲストカーネルがパニックしても、その VM が終了するだけで、同一ノード上の他のビルドを巻き込む共倒れには至りません。また VM の起動と破棄は Pod のライフサイクルに一致するため、ビルド間で状態が持ち越されることもありません。

ビルドノード内の信頼境界と責任分界

ビルドノード内の信頼境界と責任分界を図にすると、次のようになります。

Missing alt text value

4-4. Amazon EC2 Nested Virtualization を有効化したノードグループ

kata-qemu が要求する KVM を利用するために 採用するのが Amazon EC2 Nested Virtualization です。ビルドクラスタに Kata 専用のノードグループを設定し、そのノードグループの起動テンプレートの cpu_options を設定することで本機能を有効化しています。

bash
cpu_options {
  nested_virtualization = "enabled"
}

このノードグループは self-managed 型ノードグループとして構成しています。マネージドノードグループや Amazon EKS Auto Mode では実装時点では機能テンプレートで上記設定を利用できないためです (なお、OSS として公開されている Karpenter では記事執筆時点で cpuOptions のサポートが 追加されています)。ビルドノードには runtime=kata のラベルと taint を付け、ビルド用 Pod 以外のワークロードが実行されないようにしています。

5. 実装のポイントと工夫

5-1. ValidatingAdmissionPolicy による分離の強制

「TaskRun の生成側が RuntimeClass を正しく指定する」ことに依存すると、実装のミスで分離が失われます。そこで ValidatingAdmissionPolicy (Kubernetes 1.30+ の CEL ベース標準機能) をビルド用 namespace に適用し、runtimeClassName: kata-qemu でない Pod の作成と、ServiceAccount トークンの自動マウントを admission の段階で拒否しています。分離の前提をアプリケーション実装ではなく、クラスタ側の不変条件として強制する構成です。

5-2. ビルドパイプラインの step 分割と最小権限

1 回のビルドは 1 つの TaskRun で完結し、ソースの取得からスキャン結果の提示までの各工程を、役割ごとに独立した step (TaskRunによって起動されたPodの中で処理が順次実行されるひとつひとつのコンテナに相当し、特定のコマンドやスクリプトを実行する最小の処理単位) が順に実行します。VM の内側では、この step ごとのコンテナ境界で権限を分けています。

利用者コードを実行するのは、依存パッケージの取得とアプリケーションのビルドの 2 つの step だけです。この 2 つは非 root ユーザーで実行および Linux capabilities をすべて drop した上で、RuntimeDefault seccomp プロファイルを適用し、通常のビルドに不要なシステムコールを制限しています。ただし、ビルドに必要なファイル操作、プロセス生成、メモリ管理などのシステムコールは許可する必要があるため、ゲストカーネルへの攻撃面を完全には排除できません。このリスクに対する最終的な受け皿が VM 境界です。

5-3. Cluster Autoscaler によるオンデマンドスケール

ビルドを実行するKata 用ノードグループは Cluster Autoscaler の管理対象とし、スケジュールできないビルド Pod が発生するとノードを追加し、ビルドが捌けてアイドルになったノードは自動で縮退させます。Nested Virtualization は仮想 EC2 インスタンスで利用できるため、ノードの単位を小さく保ったまま、需要に応じて柔軟にスケールします。

6. 導入効果

6-1. 分離環境をほとんど自前開発せずに実現

このビルド環境を構成する部品は、活発にメンテナンスされている OSS (Tekton、Kata Containers、Cluster Autoscaler、buildah、Trivy)、Kubernetes の標準機能 (RuntimeClass、ValidatingAdmissionPolicy)、そして AWS のマネージドサービスです。当社が自前で実装したのは、ビルドジョブを受け取って TaskRun を作成する薄いコントロールプレーンとビルド手順の定義だけです。Pod 単位の VM 分離、スケジューリング、オートスケール、ポリシー強制といったコア機構のコードは一行も書いていません。

これが成立した理由は、Kubernetes がコンテナランタイムを RuntimeClass という抽象化で選択できるようにしているためです。分離強度を上げるという変更が「ランタイムの差し替え」で済み、Scheduler、Cluster Autoscaler、Admission Control といったエコシステムの部品は差し替え後もそのまま機能します。結果として、セキュリティが成立条件となる新規サービスを、小規模なチームのまま立ち上げられました。

6-2. ベアメタルインスタンス不要によるコスト構造とスケール粒度

Amazon EC2 Nested Virtualization の登場以前は、Kata Containers の実行には数十 vCPU 級のベアメタルインスタンスの確保が必要でした。現在は数 vCPU の仮想 EC2 インスタンスでノードを構成し、そこに複数のビルド VM を集約できるため、確保する vCPU の単位が一桁以上小さくなっています。ビルドの負荷はバースト的でアイドル時間が長いため、最小構成を小さく保ち、需要のあるときだけ従量的にノードを増やせるこの粒度が、そのまま原価の低減につながります。ノード追加が必要になった場合でも、Pending になったビルドがスケジュールされるまでの待ち時間は検証環境の実測でおよそ 1.5 ~ 5 分でした (ノードの起動と Kata ランタイムの展開を含む)。

6-3. VM 分離のオーバーヘッドの実測

kata-qemu の micro-VM 起動が Pod の起動に加わることによるオーバーヘッドを実測しました。Pod がノードに割り当てられてから最初のコンテナが実行を開始するまでの時間は、中央値 26 秒でした。同一クラスタ上で runc により起動する Pod では数秒であり、差し引き 20 秒強が 1 ビルドにおける VM 分離によって増加した時間となります。

6-4. 脅威モデルの単純化

カーネル共有を前提とした多層防御の精緻化に運用を割く代わりに、「テナント境界は VM 境界である」という単純な前提でセキュリティレビューを進められるようになりました。利用者コードの侵害を想定した議論が「使い捨て VM の内側で何ができるか」に限定されるため、レビューの範囲も説明も短くなります。

まとめ

本記事では、GMOペパボが提供する「ロリポップ!デプロイナウ byGMOペパボ」における Amazon EC2 Nested Virtualization の活用事例を紹介しました。

ユーザーが作成したコードをサーバー側でビルドするサービスでは、そのコードの内容を事前に把握することが難しいという前提に立つ必要があります。加えて、多数のユーザーのビルドが同一基盤上で同時に実行されるマルチテナント環境では、あるユーザーのビルドが他のユーザーや基盤そのものに影響を与えない仕組みが求められます。デプロイナウでは、Nested Virtualization によってビルドごとに独立した仮想マシンを起動し、ハードウェア仮想化による境界の内側でビルドを実行して、完了後に破棄するというアプローチを採用しました。ビルドジョブのオーケストレーションを Amazon EKS が、パイプラインの定義と実行を Tekton が担い、Nested Virtualization が分離境界を提供するという役割分担によって、セキュリティとコスト・スケーラビリティの両立を実現しています。

ユーザーやサードパーティのコードを自社の基盤上で実行する必要があり、コンテナによる分離だけではセキュリティ要件を満たせないという課題を感じている方にとって、本記事が設計や技術選定の参考になれば幸いです。

「ロリポップ!デプロイナウ byGMOペパボ」の開発秘話 (前編 / 後編) も併せてご覧ください。

筆者プロフィール

Missing alt text value

大山 隆介

GMOペパボ株式会社
ロリポップ・ムームードメイン事業部
第二事業開発チーム エンジニア

「ロリポップ!デプロイナウ byGMOペパボ」のインフラアーキテクチャ全般 (AWS、Kubernetes、ビルド環境、監視) の設計・構築・運用を担当。

Missing alt text value

鈴木 祥太

アマゾン ウェブ サービス ジャパン合同会社.
ソリューションアーキテクト

普段は Web 業界のお客様を中心にアーキテクチャ設計や構築をサポートしています。好きな AWS サービスは Amazon Elastic Kubernetes Service (Amazon EKS) です。