x86 アーキテクチャに対応した Lambda MicroVMs を試してみた

x86 アーキテクチャに対応した Lambda MicroVMs を試してみた

AWS Lambda MicroVMs は、ベースイメージのバージョン 3 以降でイメージ作成時に X86_64 を指定すると x86 で動きます。東京リージョンの単価は、x86 が Arm より約 15% 高くなりました。
2026.11.13

はじめに

2026年11月11日に、Lambda MicroVMs で x86 アーキテクチャのサポートが発表されました。

https://aws.amazon.com/jp/about-aws/whats-new/2026/11/aws-lambda-microvms-x86-architecture/

2026年6月の GA 時、サポートアーキテクチャは Arm(AWS Graviton)のみでした。今回のアップデートで、Arm と x86 のどちらかを選べるようになりました。

https://dev.classmethod.jp/articles/aws-lambda-microvms-flask-suspend-resume/

この記事では、東京リージョンで x86 の Lambda MicroVMs を試した結果を紹介します。

x86 の指定

対応バージョンの照会

x86 は、マネージドベースイメージのバージョン 3 以降でサポートされています。list-managed-microvm-image-versions で、バージョンごとの supportedCpuConfigurations を確認できます。

aws lambda-microvms list-managed-microvm-image-versions --image-identifier arn:aws:lambda:ap-northeast-1:aws:microvm-image:al2023-1 --region ap-northeast-1
バージョン 作成日(JST) supportedCpuConfigurations
3 2026-10-24 ARM_64, X86_64
2 2026-09-30 ARM_64
1 2026-07-17 ARM_64
0 2026-06-18 ARM_64

イメージの作成と起動

マルチアーキテクチャの node:24-alpine をベースにした Dockerfile を使いました。

Dockerfile
FROM node:24-alpine
WORKDIR /app
COPY app.js .
EXPOSE 8080
CMD ["node", "app.js"]

create-microvm-image に --cpu-configurations architecture=X86_64 を付けて、x86 のイメージを作りました。AWS CLI のバージョンは 2.40.2 です。

aws lambda-microvms create-microvm-image --name devio-x86-test-x86 --code-artifact uri=s3://amzn-s3-demo-bucket/app.zip --base-image-arn arn:aws:lambda:ap-northeast-1:aws:microvm-image:al2023-1 --build-role-arn arn:aws:iam::123456789012:role/MicroVMBuildRole --cpu-configurations architecture=X86_64

応答に含まれる cpuConfigurations は X86_64 でした。ベースイメージのバージョンを指定しなかったため、baseImageVersion は 3.1 になりました。

    "cpuConfigurations": [
        {
            "architecture": "X86_64"
        }
    ],

このイメージから起動した MicroVM の /arch を呼んだ結果です。EX と TOKEN_x86 は、MicroVM のエンドポイントと認証トークンです。

$ curl -sS -m 30 "https://$EX/arch" -H "X-aws-proxy-auth: $TOKEN_x86"
{"uname_m":"x86_64","process_arch":"x64"}

参考として、--cpu-configurations を付けずに同じ Dockerfile から作ると、Arm のイメージになります。

aws lambda-microvms create-microvm-image --name devio-x86-test-default --code-artifact uri=s3://amzn-s3-demo-bucket/app.zip --base-image-arn arn:aws:lambda:ap-northeast-1:aws:microvm-image:al2023-1 --build-role-arn arn:aws:iam::123456789012:role/MicroVMBuildRole

応答の cpuConfigurations は ARM_64 で、baseImageVersion は x86 と同じ 3.1 でした。

    "cpuConfigurations": [
        {
            "architecture": "ARM_64"
        }
    ],

この Arm のイメージから起動した MicroVM の /arch を呼んだ結果です。EA と TOKEN_default は、その MicroVM のエンドポイントと認証トークンです。

$ curl -sS -m 30 "https://$EA/arch" -H "X-aws-proxy-auth: $TOKEN_default"
{"uname_m":"aarch64","process_arch":"arm64"}

検証に使ったアプリの全文です。

app.js
app.js
// 検証用: アーキテクチャと実行環境の CPU・メモリを返す HTTP サーバー(ポート 8080)。
// 読むのは固定のファイルと固定の API だけ。リクエストの内容はパスの分岐にしか使わない。
// 環境変数と /proc/self/environ は読まない。ホスト名は返さない。
const http = require('http');
const os = require('os');
const fs = require('fs');
const { execFileSync } = require('child_process');

const read = (p) => {
  try { return fs.readFileSync(p, 'utf8'); } catch (e) { return `ERROR: ${e.code}`; }
};

// /proc/cpuinfo は先頭 1 コアのブロックと、コア数だけ返す。
const CPU_KEYS_X86 = ['vendor_id', 'cpu family', 'model', 'model name', 'stepping', 'microcode', 'cpu MHz', 'cache size', 'flags'];
const CPU_KEYS_ARM = ['BogoMIPS', 'Features', 'CPU implementer', 'CPU architecture', 'CPU variant', 'CPU part', 'CPU revision'];
const cpuinfo = () => {
  const text = read('/proc/cpuinfo');
  const blocks = text.split(/\n\s*\n/).filter((b) => b.trim());
  const first = {};
  for (const line of (blocks[0] || '').split('\n')) {
    const i = line.indexOf(':');
    if (i < 0) continue;
    const k = line.slice(0, i).trim();
    const v = line.slice(i + 1).trim();
    if (CPU_KEYS_X86.includes(k) || CPU_KEYS_ARM.includes(k)) first[k] = v;
  }
  const flags = (first.flags || '').split(/\s+/).filter(Boolean);
  const feats = (first.Features || '').split(/\s+/).filter(Boolean);
  return {
    processorBlocks: blocks.length,
    first,
    x86FlagCount: flags.length,
    x86Flags: flags.filter((f) => /^(avx|avx2|avx512.*|sse4_2|amx.*|vnni|avx_vnni|bmi2|sha_ni|vaes|vpclmulqdq|gfni|rdrand|rdseed|adx|fma|erms|fsrm|serialize|tsxldtrk|ibrs|ibpb|stibp|ssbd|md_clear|hypervisor)$/.test(f)),
    armFeatureCount: feats.length,
  };
};

const meminfo = () => {
  const out = {};
  for (const line of read('/proc/meminfo').split('\n')) {
    const m = line.match(/^(MemTotal|MemFree|MemAvailable|SwapTotal|SwapFree):\s+(\d+) kB/);
    if (m) out[m[1]] = `${m[2]} kB`;
  }
  return out;
};

const status = () => {
  const out = {};
  for (const line of read('/proc/self/status').split('\n')) {
    const m = line.match(/^(Cpus_allowed_list|Cpus_allowed|Mems_allowed_list):\s+(.*)$/);
    if (m) out[m[1]] = m[2];
  }
  return out;
};

const osRelease = () => {
  const out = {};
  for (const line of read('/etc/os-release').split('\n')) {
    const m = line.match(/^(PRETTY_NAME|NAME|VERSION|VERSION_ID|ID)=(.*)$/);
    if (m) out[m[1]] = m[2].replace(/^"|"$/g, '');
  }
  return out;
};

const report = () => {
  const cpus = os.cpus();
  return {
    uname_m: execFileSync('uname', ['-m']).toString().trim(),
    node: { version: process.version, arch: process.arch, platform: process.platform },
    os: { release: os.release(), version: os.version(), type: os.type(), machine: os.machine() },
    procVersion: read('/proc/version').trim(),
    osRelease: osRelease(),
    vcpu: {
      availableParallelism: os.availableParallelism(),
      osCpusLength: cpus.length,
      osCpusModel: cpus.length ? cpus[0].model : null,
      osCpusSpeedMHz: cpus.length ? cpus[0].speed : null,
      ...status(),
    },
    cpuinfo: cpuinfo(),
    memory: { ...meminfo(), osTotalmemBytes: os.totalmem(), osFreememBytes: os.freemem() },
  };
};

const server = http.createServer((req, res) => {
  res.writeHead(200, { 'Content-Type': 'application/json' });
  if (req.url === '/arch') {
    res.end(JSON.stringify({ uname_m: execFileSync('uname', ['-m']).toString().trim(), process_arch: process.arch }) + '\n');
  } else if (req.url === '/env-report') {
    res.end(JSON.stringify(report(), null, 2) + '\n');
  } else {
    res.end(JSON.stringify({ status: 'ok' }) + '\n');
  }
});

server.listen(8080, () => {
  console.log('Listening on port 8080');
});

CPU とメモリの確認

MicroVM の CPU とメモリの情報を、アプリの /env-report から取得しました。値の取得元は /proc/cpuinfo、/proc/meminfo、/proc/self/status、Node.js の os モジュールです。

CPU

vCPU は Arm と x86 のどちらも 4 でした。Node.js の availableParallelism と /proc/cpuinfo のプロセッサ数は 4、Cpus_allowed_list は 0-3 です。

x86 を指定したイメージのビルド情報(get-microvm-image-build)では、chipset が INTEL でした。ビルドは 2 つあり、chipsetGeneration は icelake と sapphirerapids でした。同じイメージから x86 の MicroVM を 4 台起動したところ、CPU も 2 種類に 2 台ずつ分かれました。

世代 model stepping model name cache size 世代に特有の命令 台数
Sapphire Rapids 143 8 Intel(R) Xeon(R) Processor 107520 KB AMX、avx_vnni、avx512_fp16 あり 2
Ice Lake 106 6 Intel(R) Xeon(R) Processor @ 2.90GHz 55296 KB AMX、avx_vnni、avx512_fp16 なし 2

MicroVM の model name では型番が伏せられています。そこで、DevelopersIO の M6i と M7i の実測記事に載っている /proc/cpuinfo の値と突き合わせました。

https://dev.classmethod.jp/articles/amazon-ec2-m6i-instances/

https://dev.classmethod.jp/articles/ec2-m7i-m7iflex-tokyo/

model 106 の MicroVM は、M6i の記事と model、stepping、キャッシュサイズ(55296 KB)が一致し、AMX 系の命令を持たない点も同じでした。model 143 の MicroVM は、M7i の記事と model、stepping、キャッシュサイズ(107520 KB)が一致しました。AMX、avx_vnni、avx512_fp16 を持つ点も同じでした。

メモリ

既定のベースラインは 2 GB / 1 vCPU です。既定サイズで起動した今回の MicroVM では、Arm と x86 のどちらでも、4 vCPU と約 8 GB のメモリが見えました。スワップ(SwapTotal)はどちらも 0 です。

項目 Arm x86
MemTotal 8209056 kB 8222748 kB
os.totalmem() 8406073344 バイト 8420093952 バイト

料金ページには、ピークはベースラインの最大 4 倍と書かれています。見えた 4 vCPU はこの上限(1 vCPU × 4)と同じで、約 8 GB のメモリも上限(2 GB × 4)に近い値です。課金されるのは、ベースライン分と、ベースラインを超えて実際に使った分です。

料金

Arm と x86 で単価が異なるのは、vCPU 秒とメモリ GB 秒です。東京リージョンの単価は次のとおりです。

項目 Arm(USD) x86(USD) 差
vCPU 秒 0.0000322421 0.0000371569 +15.24%
メモリ GB 秒 0.0000042688 0.0000049195 +15.24%

バージニア北部リージョンでは、vCPU 秒もメモリ GB 秒も x86 が 17.91% 高くなっています。

まとめ

Lambda MicroVMs は、ベースイメージのバージョン 3 以降で x86 に対応しました。

x86 のバイナリやライブラリを使いたい場合や、開発環境が x86 で、Arm 向けのクロスコンパイルにビルド時間がかかっていた場合は、x86 のイメージをお試しください。

ただし、実行単価は Arm より東京リージョンで約 15%、バージニア北部で約 18% 高くなります。また、割り当てられる CPU の世代が混在することも確認しました。

CPU アーキテクチャに依存しないワークロードであれば、既定の Arm のまま使うことをおすすめします。

この記事をシェアする

AWSのお困り事はクラスメソッドへ

関連記事