🚀 Kubernetes v1.33 の Image Volume β が激アツ！“コードだけ”イメージで世界が変わる！


Kubernetes v1.33 でついに **Image Volume** が **β** になりました！（※デフォルト無効）
OCI イメージをそのまま **読み取り専用ボリューム** としてマウントできるこの機能、 **革命的** じゃないですか？

## 🧠 Image Volume ってなにがスゴいの？

これまでの「すべてを 1 つのコンテナに詰め込む」やり方をやめて、

* アプリコード
* ランタイム
* ライブラリ

などを **イメージごとに分割してマウント**できる時代が来ました。

**特にスクリプト言語勢（Node.js / Python等）にはめちゃくちゃ効く！**
例：アプリ本体が入った “コードだけ” イメージをマウントし、Node.js を `node:22.15.1` で動かす。

## 🧱 “コードだけ”の超軽量イメージを実際に構築してみる

Image Volume の魅力は、**コードや設定ファイルだけを含んだ超軽量な OCI イメージ**を作れること。
その例として、Node.js のアプリケーションコードだけを収めたシンプルなイメージを作ってみましょう。

---

### 📁 `index.js` – アプリ本体

```js
const http = require('http');
http.createServer((_, res) => res.end('Hello from OCI volume!\n'))
    .listen(process.env.PORT || 80);
```

Node.js で「Hello from OCI volume!」を返すだけの HTTP サーバー。

---

### 🐳 `Dockerfile` – "FROM scratch" の衝撃

```Dockerfile
FROM scratch
COPY app /
```

`FROM scratch`（＝何もない状態）からスタートし、`COPY` でコードだけを入れた構成。
つまり、**Node.js すら入っていません。**

これはどういう意味かというと、**ランタイム（Node.js）は別のコンテナから提供**し、
このイメージはただの「コード置き場」として使う、という使い方です。

---

### 📏 そのサイズ、なんとたったの **134バイト**

この3つのファイルだけで構成された OCI イメージのサイズは、なんと **134バイト**！

```bash
docker images | grep hello-app
localhost:5001/hello-app                                                799466d0                 c4bd064f6fff   About a minute ago   134B
```

* ビルドは一瞬 ✅
* レジストリにプッシュしてもほぼ瞬間 ✅
* CI/CD の負荷も最小限 ✅

コードが変わらない限りはこのイメージを再利用可能で、**キャッシュのヒット率も向上**します。

---

このように、「アプリケーションのコードだけをイメージ化する」という発想は、
従来の「全部入りコンテナ」とは完全に異なる世界観をもたらしてくれます。

Image Volume があることで、
**アプリコードのライフサイクル**と**ランタイムのライフサイクル**を**完全に分離**できるようになります。

## 📦 ベースイメージのパッチも即対応！実際の差分で見る

ImageVolume を使っていると、ベースイメージの脆弱性修正に対しても驚くほど簡単に追従できます。

### ✅ パターン①：タグを固定して手動で更新

たとえば、`node:22.15.0` のベースイメージに脆弱性パッチがリリースされた場合は…

```diff
-    image: mirror.gcr.io/node:22.15.0
+    image: mirror.gcr.io/node:22.15.1
```

このように `Pod` の `image` を修正して再デプロイするだけで対応完了。
**“アプリ本体”のコードイメージは何も変更不要！**
CI も再ビルド不要。**Yaml を 1 行変更するだけ**で、即座にセキュリティパッチが反映されます。

---

### 🔄 パターン②：タグを浮動 (`node:22`) にして自動追従

もっと“完全自動”に近づけたい場合は、タグをマイナーバージョンではなくメジャー (`node:22`) にして、
さらに `imagePullPolicy: Always` を設定すれば、**Pod を再起動するだけで最新のパッチが取り込まれます。**

```yaml
image: node:22
imagePullPolicy: Always
```

これにより、`22.15.0 → 22.15.1` → `22.16.0` へのアップデートも、**Pod の再起動のみで自動反映**されます。

\:::caution ⚠️ 注意点
この方法は **常に最新のパッチを取り込める**反面、
リグレッション（＝新しいバージョンにバグが含まれる）を**即時に踏むリスクもある**ため、
**安定性が最優先の本番環境では慎重な判断が必要です。**

**特に本番では明示的なタグの運用が安心です。**
\:::

---

### 💡まとめ

| 戦略                             | メリット            | 注意点                 |
| ------------------------------ | --------------- | ------------------- |
| 固定タグ (`node:22.15.1`)          | 安定・予測可能な動作      | 手動で更新が必要            |
| 浮動タグ + Pull Always (`node:22`) | 常に最新パッチが自動反映される | 意図しないバージョンに上がる可能性あり |

状況や環境に応じて、**リスクと自動化のバランスをとったタグ戦略**を選びましょう。

## 🧪 実際に動かす！全自動スクリプト付き

Image Volume の世界をすぐに試してみたいあなたのために、**一発で動く検証スクリプト**も用意しました。

### ✅ 検証スクリプト全文はこちら：

```bash
#!/usr/bin/env bash
set -euox pipefail

# Create a temporary file for the upstream script
TMP_SCRIPT=$(mktemp)
echo "Downloading upstream kind-with-registry.sh to $TMP_SCRIPT"

# Download the upstream script
curl -fsSL https://kind.sigs.k8s.io/examples/kind-with-registry.sh -o "$TMP_SCRIPT"

# Patch and execute the script
# This adds the ImageVolume feature gate after the apiVersion line
echo "Patching and executing the script with ImageVolume feature gate enabled"
awk '
  /^apiVersion: kind.x-k8s.io\/v1alpha4/ {
    print
    print "featureGates:\n  ImageVolume: true"
    next
  }
  {print}
' "$TMP_SCRIPT" | bash -s

##############################################################################
# 2. "コードだけ" OCI イメージをビルド & push
##############################################################################
WORK=$(mktemp -d)
echo "Workdir: $WORK"
mkdir -p "$WORK/app"

cat > "$WORK/app/index.js" <<'JS'
const http = require('http');
http.createServer((_, res) => res.end('Hello from OCI volume!\n'))
    .listen(process.env.PORT || 80);
JS

cat > "$WORK/Dockerfile" <<'DOCKER'
FROM scratch
COPY app /
DOCKER

RAND_TAG=$(openssl rand -hex 4)
FULL_IMAGE="localhost:5001/hello-app:${RAND_TAG}"

docker build -f "$WORK/Dockerfile" -t "${FULL_IMAGE}" "$WORK"
docker push "${FULL_IMAGE}"

##############################################################################
# 4. Pod マニフェストを適用 (ImageVolume 参照)
##############################################################################
cat > "$WORK/node-demo.yaml" <<EOF
apiVersion: v1
kind: Pod
metadata:
  name: node-demo
spec:
  containers:
  - name: runtime
    image: mirror.gcr.io/node:22-slim
    command: ["node", "/usr/src/app/index.js"]
    workingDir: /usr/src/app
    ports: [{containerPort: 80}]
    volumeMounts:
    - mountPath: /usr/src/app
      name: app-src
  volumes:
  - name: app-src
    image:
      reference: ${FULL_IMAGE}
      pullPolicy: IfNotPresent
EOF

sleep 10
kubectl apply -f "$WORK/node-demo.yaml"
kubectl wait --for=condition=Ready pod/node-demo --timeout=120s

##############################################################################
# 5. 動作確認
##############################################################################
kubectl port-forward pod/node-demo 3000:80 >/dev/null &
PF=$!
sleep 2
echo -n "curl → "
curl http://localhost:3000
kill $PF

cat <<EOM

✅ 完了！ ImageVolume でコードをマウントした Node.js が起動しました。

後片付け:
  kind delete cluster
  rm -rf ${WORK}
EOM
```

このスクリプトをコピペして実行するだけで、あなたのローカル環境で **Image Volume を使った Node.js アプリの立ち上げが完了**します！

## 🎯 使い所：こんなケースで効いてくる

| ユースケース                                        | 従来方法                 | Image Volumeなら                |
| --------------------------------------------- | -------------------- | ----------------------------- |
| **Node.js のコード配布**<br>(例: `node:22.15.1`)     | アプリコードをベースに組み込んで再ビルド | コードだけを別イメージにし、マウントするだけ        |
| **Pythonライブラリの共有**<br>(例: `python:3.11-slim`) | 各アプリごとにビルド           | 共通環境をベースイメージに固定、アプリは別管理       |
| **AIモデルや証明書の展開**                              | 巨大イメージに全部詰め込み        | モデルや証明書だけを Image Volume 化して共有 |

## ✅ まとめ：これはもう、未来のデファクトになります

* “コードだけ” イメージで **ビルド時間短縮**＆**キャッシュヒット向上**
* ベースイメージの更新で **パッチ即反映**
* **CI/CD もスリムに、セキュリティも向上**

「イメージをマウントする」って今までちょっとピンとこなかった人も、
この仕組みが **次世代のベストプラクティス** になっていくのを今から体験してみてください。