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
– アプリ本体
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" の衝撃
FROM scratch
COPY app /
FROM scratch
(=何もない状態)からスタートし、COPY
でコードだけを入れた構成。
つまり、Node.js すら入っていません。
これはどういう意味かというと、ランタイム(Node.js)は別のコンテナから提供し、
このイメージはただの「コード置き場」として使う、という使い方です。
📏 そのサイズ、なんとたったの 134バイト
この3つのファイルだけで構成された OCI イメージのサイズは、なんと 134バイト!
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
のベースイメージに脆弱性パッチがリリースされた場合は…
- 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 を再起動するだけで最新のパッチが取り込まれます。
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 の世界をすぐに試してみたいあなたのために、一発で動く検証スクリプトも用意しました。
✅ 検証スクリプト全文はこちら:
#!/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 のコード配布 (例: node:22.15.1 ) |
アプリコードをベースに組み込んで再ビルド | コードだけを別イメージにし、マウントするだけ |
Pythonライブラリの共有 (例: python:3.11-slim ) |
各アプリごとにビルド | 共通環境をベースイメージに固定、アプリは別管理 |
AIモデルや証明書の展開 | 巨大イメージに全部詰め込み | モデルや証明書だけを Image Volume 化して共有 |
✅ まとめ:これはもう、未来のデファクトになります
- “コードだけ” イメージで ビルド時間短縮&キャッシュヒット向上
- ベースイメージの更新で パッチ即反映
- CI/CD もスリムに、セキュリティも向上
「イメージをマウントする」って今までちょっとピンとこなかった人も、
この仕組みが 次世代のベストプラクティス になっていくのを今から体験してみてください。