jpskill.com
🛠️ 開発・MCP コミュニティ

deploying-cloud-k8s

Deploys applications to cloud Kubernetes (AKS/GKE/DOKS) with CI/CD pipelines. Use when deploying to production, setting up GitHub Actions, troubleshooting deployments. Covers build-time vs runtime vars, architecture matching, and battle-tested debugging.

⚡ おすすめ: コマンド1行でインストール(60秒)

下記のコマンドをコピーしてターミナル(Mac/Linux)または PowerShell(Windows)に貼り付けてください。 ダウンロード → 解凍 → 配置まで全自動。

🍎 Mac / 🐧 Linux
mkdir -p ~/.claude/skills && cd ~/.claude/skills && curl -L -o deploying-cloud-k8s.zip https://jpskill.com/download/17297.zip && unzip -o deploying-cloud-k8s.zip && rm deploying-cloud-k8s.zip
🪟 Windows (PowerShell)
$d = "$env:USERPROFILE\.claude\skills"; ni -Force -ItemType Directory $d | Out-Null; iwr https://jpskill.com/download/17297.zip -OutFile "$d\deploying-cloud-k8s.zip"; Expand-Archive "$d\deploying-cloud-k8s.zip" -DestinationPath $d -Force; ri "$d\deploying-cloud-k8s.zip"

完了後、Claude Code を再起動 → 普通に「動画プロンプト作って」のように話しかけるだけで自動発動します。

💾 手動でダウンロードしたい(コマンドが難しい人向け)
  1. 1. 下の青いボタンを押して deploying-cloud-k8s.zip をダウンロード
  2. 2. ZIPファイルをダブルクリックで解凍 → deploying-cloud-k8s フォルダができる
  3. 3. そのフォルダを C:\Users\あなたの名前\.claude\skills\(Win)または ~/.claude/skills/(Mac)へ移動
  4. 4. Claude Code を再起動

⚠️ ダウンロード・利用は自己責任でお願いします。当サイトは内容・動作・安全性について責任を負いません。

🎯 このSkillでできること

下記の説明文を読むと、このSkillがあなたに何をしてくれるかが分かります。Claudeにこの分野の依頼をすると、自動で発動します。

📦 インストール方法 (3ステップ)

  1. 1. 上の「ダウンロード」ボタンを押して .skill ファイルを取得
  2. 2. ファイル名の拡張子を .skill から .zip に変えて展開(macは自動展開可)
  3. 3. 展開してできたフォルダを、ホームフォルダの .claude/skills/ に置く
    • · macOS / Linux: ~/.claude/skills/
    • · Windows: %USERPROFILE%\.claude\skills\

Claude Code を再起動すれば完了。「このSkillを使って…」と話しかけなくても、関連する依頼で自動的に呼び出されます。

詳しい使い方ガイドを見る →
最終更新
2026-05-18
取得日時
2026-05-18
同梱ファイル
3

📖 Skill本文(日本語訳)

※ 原文(英語/中国語)を Gemini で日本語化したものです。Claude 自身は原文を読みます。誤訳がある場合は原文をご確認ください。

Cloud K8s のデプロイ

クイックスタート

  1. クラスタのアーキテクチャを確認します: kubectl get nodes -o jsonpath='{.items[*].status.nodeInfo.architecture}'
  2. ビルドプラットフォームをクラスタに合わせます (arm64 vs amd64)
  3. パスフィルタを使用して GitHub Actions をセットアップします
  4. Helm でデプロイし、--set 経由でシークレットを渡します

重要: ビルド時変数 vs ランタイム変数

問題点

Next.js の NEXT_PUBLIC_* 変数は、ランタイムではなく、ビルド時に埋め込まれます:

# 間違い: ランタイムの ENV は NEXT_PUBLIC_* には何の影響も与えません
ENV NEXT_PUBLIC_API_URL=https://api.example.com

# 正しい: ビルド ARG でなければなりません
ARG NEXT_PUBLIC_API_URL=https://api.example.com
ENV NEXT_PUBLIC_API_URL=$NEXT_PUBLIC_API_URL

ビルド時 (Next.js)

変数 目的
NEXT_PUBLIC_SSO_URL ブラウザ OAuth 用の SSO エンドポイント
NEXT_PUBLIC_API_URL ブラウザ fetch 用の API エンドポイント
NEXT_PUBLIC_APP_URL リダイレクト用のアプリ URL

ランタイム (ConfigMaps/Secrets)

変数 ソース
DATABASE_URL Secret (Neon/managed DB)
SSO_URL ConfigMap (内部 K8s: http://sso:3001)
BETTER_AUTH_SECRET Secret

アーキテクチャのマッチング

デプロイの前に必ず、アーキテクチャを確認してください:

kubectl get nodes -o jsonpath='{.items[*].status.nodeInfo.architecture}'
# 出力: arm64 arm64  OR  amd64 amd64

Docker ビルド

- uses: docker/build-push-action@v5
  with:
    platforms: linux/arm64      # クラスタに合わせてください!
    provenance: false           # マニフェストの問題を回避
    no-cache: true              # デバッグ時

なぜ provenance: false なのか? Buildx の構成証明は、"no match for platform" エラーを引き起こす複雑なマニフェストリストを作成します。

GitHub Actions CI/CD

パスフィルタによる選択的ビルド

jobs:
  changes:
    runs-on: ubuntu-latest
    outputs:
      api: ${{ steps.filter.outputs.api }}
      web: ${{ steps.filter.outputs.web }}
    steps:
      - uses: dorny/paths-filter@v3
        id: filter
        with:
          filters: |
            api:
              - 'apps/api/**'
            web:
              - 'apps/web/**'

  build-api:
    needs: changes
    if: needs.changes.outputs.api == 'true'

Next.js ビルド引数

- name: Build and push (web)
  uses: docker/build-push-action@v5
  with:
    build-args: |
      NEXT_PUBLIC_SSO_URL=https://sso.${{ vars.DOMAIN }}
      NEXT_PUBLIC_API_URL=https://api.${{ vars.DOMAIN }}

Helm デプロイメント

- name: Deploy
  run: |
    helm upgrade --install myapp ./helm/myapp \
      --set global.imageTag=${{ github.sha }} \
      --set "secrets.databaseUrl=${{ secrets.DATABASE_URL }}" \
      --set "secrets.authSecret=${{ secrets.BETTER_AUTH_SECRET }}"

トラブルシューティングガイド

クイック診断フロー

Pod が実行されていませんか?
    │
    ├─► ImagePullBackOff
    │       ├─► "not found" ──► タグまたはレジストリが間違っています
    │       ├─► "unauthorized" ──► 認証/imagePullSecrets
    │       └─► "no match for platform" ──► アーキテクチャのミスマッチ
    │
    ├─► CrashLoopBackOff
    │       ├─► "exec format error" ──► CPU アーキテクチャが間違っています
    │       ├─► Exit code 1 ──► アプリの起動失敗
    │       └─► OOMKilled ──► メモリ制限が低すぎます
    │
    └─► Pending
            ├─► リソースが不足しています ──► クラスタをスケールします
            └─► 一致するノードがありません ──► nodeSelector を確認します

診断コマンド

kubectl get pods -n <namespace>
kubectl describe pod <pod-name> -n <namespace> | grep -E "(Image:|Failed|Error)"
kubectl get events -n <namespace> --sort-by='.lastTimestamp' | tail -20
kubectl logs <pod-name> -n <namespace> --tail=50

エラー: ImagePullBackOff "not found"

原因:

  • タグが存在しない (短い SHA vs 完全な SHA)
  • レジストリパスが間違っている
  • パスフィルタによってビルドがスキップされた

解決策: デプロイで使用されている正確なタグでイメージがプッシュされたことを確認します

エラー: "no match for platform in manifest"

原因: イメージが間違ったアーキテクチャでビルドされた、または buildx の構成証明の問題

解決策:

platforms: linux/arm64  # クラスタに合わせてください!
provenance: false       # シンプルなマニフェスト
no-cache: true          # 強制的にリビルド

エラー: "exec format error"

原因: バイナリのアーキテクチャがノードと一致しません

解決策: 正しいプラットフォームでリビルドし、no-cache: true を使用します

エラー: Helm のカンマ解析

failed parsing --set data: key "com" has no value

原因: Helm はカンマを配列の区切り文字として解釈します

解決策: heredoc 値ファイルを使用します:

- name: Deploy
  run: |
    cat > /tmp/overrides.yaml << EOF
    sso:
      env:
        ALLOWED_ORIGINS: "https://a.com,https://b.com"
    EOF
    helm upgrade --install app ./chart --values /tmp/overrides.yaml

エラー: パスワード認証に失敗しました

原因: 特殊文字を含むパスワード (base64 +/=)

解決策: 16進数のパスワードを使用します:

# 間違い
openssl rand -base64 16  # +/= を含む可能性があります

# 正しい
openssl rand -hex 16     # 英数字のみ

エラー: ログアウトが 0.0.0.0 にリダイレクトされる

原因: request.url がコンテナのバインドアドレスを返します

解決策:

const APP_URL = process.env.NEXT_PUBLIC_APP_URL || "http://localhost:3000";
const response = NextResponse.redirect(new URL("/", APP_URL));

デプロイ前チェックリスト

アーキテクチャ

  • [ ] クラスタノードのアーキテクチャを確認しました
  • [ ] ビルドプラットフォームがクラスタと一致します

Docker ビルド

  • [ ] provenance: false が設定されています
  • [ ] platforms: linux/<arch> がクラスタと一致します
  • [ ] イメージタグがビルドとデプロイの間で一貫しています

CI/CD

  • [ ] すべての NEXT_PUBLIC_* がビルド引数として設定されています
  • [ ] シークレットが --set 経由で渡されます (values.yaml にはありません)
  • [ ] パスフィルタが構成されています

Helm

  • [ ] --set の値にカンマはありません
  • [ ] サービス間通信には内部 K8s サービス名を使用します
  • [ ] パスワードは values.yaml で単一の信頼できる情報源です

本番環境のデバッグ

リクエストパスのトレース

(原文がここで切り詰められています)
📜 原文 SKILL.md(Claudeが読む英語/中国語)を展開

Deploying Cloud K8s

Quick Start

  1. Check cluster architecture: kubectl get nodes -o jsonpath='{.items[*].status.nodeInfo.architecture}'
  2. Match build platform to cluster (arm64 vs amd64)
  3. Set up GitHub Actions with path filters
  4. Deploy with Helm, passing secrets via --set

Critical: Build-Time vs Runtime Variables

The Problem

Next.js NEXT_PUBLIC_* variables are embedded at build time, not runtime:

# WRONG: Runtime ENV does nothing for NEXT_PUBLIC_*
ENV NEXT_PUBLIC_API_URL=https://api.example.com

# RIGHT: Must be build ARG
ARG NEXT_PUBLIC_API_URL=https://api.example.com
ENV NEXT_PUBLIC_API_URL=$NEXT_PUBLIC_API_URL

Build-Time (Next.js)

Variable Purpose
NEXT_PUBLIC_SSO_URL SSO endpoint for browser OAuth
NEXT_PUBLIC_API_URL API endpoint for browser fetch
NEXT_PUBLIC_APP_URL App URL for redirects

Runtime (ConfigMaps/Secrets)

Variable Source
DATABASE_URL Secret (Neon/managed DB)
SSO_URL ConfigMap (internal K8s: http://sso:3001)
BETTER_AUTH_SECRET Secret

Architecture Matching

BEFORE ANY DEPLOYMENT, check architecture:

kubectl get nodes -o jsonpath='{.items[*].status.nodeInfo.architecture}'
# Output: arm64 arm64  OR  amd64 amd64

Docker Build

- uses: docker/build-push-action@v5
  with:
    platforms: linux/arm64      # MATCH YOUR CLUSTER!
    provenance: false           # Avoid manifest issues
    no-cache: true              # When debugging

Why provenance: false? Buildx attestation creates complex manifest lists that cause "no match for platform" errors.

GitHub Actions CI/CD

Selective Builds with Path Filters

jobs:
  changes:
    runs-on: ubuntu-latest
    outputs:
      api: ${{ steps.filter.outputs.api }}
      web: ${{ steps.filter.outputs.web }}
    steps:
      - uses: dorny/paths-filter@v3
        id: filter
        with:
          filters: |
            api:
              - 'apps/api/**'
            web:
              - 'apps/web/**'

  build-api:
    needs: changes
    if: needs.changes.outputs.api == 'true'

Next.js Build Args

- name: Build and push (web)
  uses: docker/build-push-action@v5
  with:
    build-args: |
      NEXT_PUBLIC_SSO_URL=https://sso.${{ vars.DOMAIN }}
      NEXT_PUBLIC_API_URL=https://api.${{ vars.DOMAIN }}

Helm Deployment

- name: Deploy
  run: |
    helm upgrade --install myapp ./helm/myapp \
      --set global.imageTag=${{ github.sha }} \
      --set "secrets.databaseUrl=${{ secrets.DATABASE_URL }}" \
      --set "secrets.authSecret=${{ secrets.BETTER_AUTH_SECRET }}"

Troubleshooting Guide

Quick Diagnosis Flow

Pod not running?
    │
    ├─► ImagePullBackOff
    │       ├─► "not found" ──► Wrong tag or registry
    │       ├─► "unauthorized" ──► Auth/imagePullSecrets
    │       └─► "no match for platform" ──► Architecture mismatch
    │
    ├─► CrashLoopBackOff
    │       ├─► "exec format error" ──► Wrong CPU architecture
    │       ├─► Exit code 1 ──► App startup failure
    │       └─► OOMKilled ──► Memory limits too low
    │
    └─► Pending
            ├─► Insufficient resources ──► Scale cluster
            └─► No matching node ──► Check nodeSelector

Diagnostic Commands

kubectl get pods -n <namespace>
kubectl describe pod <pod-name> -n <namespace> | grep -E "(Image:|Failed|Error)"
kubectl get events -n <namespace> --sort-by='.lastTimestamp' | tail -20
kubectl logs <pod-name> -n <namespace> --tail=50

Error: ImagePullBackOff "not found"

Causes:

  • Tag doesn't exist (short vs full SHA)
  • Wrong registry path
  • Builds skipped by path filters

Fix: Verify image was pushed with exact tag used in deployment

Error: "no match for platform in manifest"

Cause: Image built for wrong architecture OR buildx provenance issue

Fix:

platforms: linux/arm64  # Match cluster!
provenance: false       # Simple manifest
no-cache: true          # Force rebuild

Error: "exec format error"

Cause: Binary architecture doesn't match node

Fix: Rebuild with correct platform, use no-cache: true

Error: Helm comma parsing

failed parsing --set data: key "com" has no value

Cause: Helm interprets commas as array separators

Fix: Use heredoc values file:

- name: Deploy
  run: |
    cat > /tmp/overrides.yaml << EOF
    sso:
      env:
        ALLOWED_ORIGINS: "https://a.com,https://b.com"
    EOF
    helm upgrade --install app ./chart --values /tmp/overrides.yaml

Error: Password authentication failed

Cause: Password with special characters (base64 +/=)

Fix: Use hex passwords:

# Wrong
openssl rand -base64 16  # Can have +/=

# Right
openssl rand -hex 16     # Alphanumeric only

Error: Logout redirects to 0.0.0.0

Cause: request.url returns container bind address

Fix:

const APP_URL = process.env.NEXT_PUBLIC_APP_URL || "http://localhost:3000";
const response = NextResponse.redirect(new URL("/", APP_URL));

Pre-Deployment Checklist

Architecture

  • [ ] Checked cluster node architecture
  • [ ] Build platform matches cluster

Docker Build

  • [ ] provenance: false set
  • [ ] platforms: linux/<arch> matches cluster
  • [ ] Image tags consistent between build and deploy

CI/CD

  • [ ] All NEXT_PUBLIC_* as build args
  • [ ] Secrets passed via --set (not in values.yaml)
  • [ ] Path filters configured

Helm

  • [ ] No commas in --set values
  • [ ] Internal K8s service names for inter-service communication
  • [ ] Password single source of truth in values.yaml

Production Debugging

Trace Request Path

# 1. Frontend logs
kubectl logs deploy/web -n myapp --tail=50

# 2. API logs
kubectl logs deploy/api -n myapp --tail=100 | grep -i error

# 3. Sidecar logs (Dapr, etc.)
kubectl logs deploy/api -n myapp -c daprd --tail=50

Common Bug Patterns

Error Likely Cause
AttributeError: no attribute 'X' Model/schema mismatch
404 Not Found on internal call Wrong endpoint URL
Times off by hours Timezone handling bug
greenlet_spawn not called Async SQLAlchemy pattern

GitOps with ArgoCD

apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: myapp
  namespace: argocd
spec:
  source:
    repoURL: https://github.com/org/repo.git
    path: k8s/overlays/production
  destination:
    server: https://kubernetes.default.svc
    namespace: myapp
  syncPolicy:
    automated:
      prune: true      # Delete resources not in Git
      selfHeal: true   # Fix drift automatically

Observability

# ServiceMonitor for Prometheus
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
  name: myapp
spec:
  selector:
    matchLabels:
      app: myapp
  endpoints:
    - port: metrics
      interval: 30s

Security

# Pod Security Context
securityContext:
  runAsNonRoot: true
  runAsUser: 1000
  allowPrivilegeEscalation: false
  readOnlyRootFilesystem: true
  capabilities:
    drop: ["ALL"]

Resilience

# HPA + PDB
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
spec:
  minReplicas: 2
  maxReplicas: 10
  metrics:
    - type: Resource
      resource:
        name: cpu
        target:
          type: Utilization
          averageUtilization: 70
---
apiVersion: policy/v1
kind: PodDisruptionBudget
spec:
  minAvailable: 1

See references/production-patterns.md for full GitOps, observability, security, and resilience patterns.

Verification

Run: python scripts/verify.py

Related Skills

  • containerizing-applications - Docker and Helm charts
  • operating-k8s-local - Local Kubernetes with Minikube
  • building-nextjs-apps - Next.js patterns

References

同梱ファイル

※ ZIPに含まれるファイル一覧。`SKILL.md` 本体に加え、参考資料・サンプル・スクリプトが入っている場合があります。