Agent-almanac deploy-to-kubernetes
git clone https://github.com/pjt222/agent-almanac
T=$(mktemp -d) && git clone --depth=1 https://github.com/pjt222/agent-almanac "$T" && mkdir -p ~/.claude/skills && cp -r "$T/i18n/ja/skills/deploy-to-kubernetes" ~/.claude/skills/pjt222-agent-almanac-deploy-to-kubernetes-d9e237 && rm -rf "$T"
i18n/ja/skills/deploy-to-kubernetes/SKILL.mdKubernetesへのデプロイ
ヘルスチェック、リソース管理、自動ロールアウトを含む本番対応設定でコンテナ化アプリケーションをKubernetesにデプロイします。
使用タイミング
- KubernetesクラスターへのアプリケーションのデプロイWhen(EKS、GKE、AKS、セルフホスト)
- Docker Composeまたは従来のVMからコンテナオーケストレーションへの移行
- ゼロダウンタイムローリングアップデートとロールバックの実装
- Kubernetesでのアプリケーション設定とシークレットの管理
- マルチ環境デプロイメントのセットアップ(dev、staging、production)
- アプリケーション配布向け再利用可能Helmチャートの作成
入力
- 必須: Kubernetesクラスターアクセス(
)kubectl cluster-info - 必須: レジストリにプッシュ済みのコンテナイメージ(Docker Hub、ECR、GCR、Harbor)
- 必須: アプリケーション要件(ポート、環境変数、ボリューム)
- 任意: HTTPSイングレス向けTLS証明書
- 任意: 永続ストレージ要件(StatefulSets、PVC)
- 任意: チャートベースデプロイメント向けHelm CLI
手順
完全な設定ファイルとテンプレートは拡張サンプルを参照してください。
ステップ1: NamespaceとResourceQuotaの作成
アプリケーションをリソース制限とRBACを持つNamespaceに整理します。
# Create namespace kubectl create namespace myapp-prod # Apply resource quota cat <<EOF | kubectl apply -f - apiVersion: v1 kind: ResourceQuota metadata: name: compute-quota namespace: myapp-prod spec: hard: requests.cpu: "10" requests.memory: "20Gi" limits.cpu: "20" limits.memory: "40Gi" persistentvolumeclaims: "5" services.loadbalancers: "2" --- apiVersion: v1 kind: LimitRange metadata: name: default-limits namespace: myapp-prod spec: limits: - default: cpu: "500m" memory: "512Mi" defaultRequest: cpu: "100m" memory: "128Mi" type: Container EOF # Create service account cat <<EOF | kubectl apply -f - apiVersion: v1 kind: ServiceAccount metadata: name: myapp namespace: myapp-prod --- apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: name: myapp-role namespace: myapp-prod rules: - apiGroups: [""] resources: ["configmaps", "secrets"] verbs: ["get", "list", "watch"] --- apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: name: myapp-rolebinding namespace: myapp-prod subjects: - kind: ServiceAccount name: myapp namespace: myapp-prod roleRef: kind: Role name: myapp-role apiGroup: rbac.authorization.k8s.io EOF # Verify namespace setup kubectl get resourcequota -n myapp-prod kubectl get limitrange -n myapp-prod kubectl get sa -n myapp-prod
期待結果: コンピュートとストレージを制限するResourceQuotaを持つNamespaceが作成されます。LimitRangeがデフォルトのCPU・メモリリクエストと制限を設定します。ServiceAccountが最小権限RBACで設定されます。
失敗時: クォータエラーの場合、
kubectl describe nodes でクラスターに十分なリソースがあることを確認します。RBACエラーの場合、kubectl auth can-i create role --namespace myapp-prod でクラスター管理者権限を確認します。拒否されたリソースに kubectl describe を使用してクォータ・制限違反を確認します。
ステップ2: アプリケーションシークレットとConfigMapの設定
ConfigMapとSecretを使用して設定と機密データを外部化します。
# Create ConfigMap from literal values kubectl create configmap myapp-config \ --namespace=myapp-prod \ --from-literal=LOG_LEVEL=info \ --from-literal=API_TIMEOUT=30s \ --from-literal=FEATURE_FLAGS='{"newUI":true,"betaAPI":false}' # Create ConfigMap from file cat > app.properties <<EOF database.pool.size=20 cache.ttl=3600 retry.attempts=3 EOF kubectl create configmap myapp-properties \ --namespace=myapp-prod \ --from-file=app.properties # Create Secret for database credentials kubectl create secret generic myapp-db-secret \ --namespace=myapp-prod \ --from-literal=username=appuser \ --from-literal=password='sup3rs3cr3t!' \ --from-literal=connection-string='postgresql://db.example.com:5432/myapp' # Create TLS secret for ingress kubectl create secret tls myapp-tls \ --namespace=myapp-prod \ --cert=path/to/tls.crt \ --key=path/to/tls.key # Verify secrets/configmaps kubectl get configmap -n myapp-prod kubectl get secret -n myapp-prod kubectl describe configmap myapp-config -n myapp-prod
より複雑な設定にはYAMLマニフェストを使用します:
# configmap.yaml apiVersion: v1 kind: ConfigMap metadata: name: myapp-config namespace: myapp-prod data: nginx.conf: | server { listen 8080; location / { proxy_pass http://backend:3000; proxy_set_header Host $host; } } app-config.json: | { "logLevel": "info", "features": { "authentication": true, "metrics": true } } --- # secret.yaml apiVersion: v1 kind: Secret metadata: name: myapp-secret namespace: myapp-prod type: Opaque stringData: # Automatically base64 encoded api-key: "sk-1234567890abcdef" jwt-secret: "my-jwt-signing-key"
期待結果: ConfigMapが非機密設定を、Secretが認証情報・キーを保存します。値が環境変数またはボリュームマウント経由でPodからアクセス可能です。TLSシークレットがIngressリソース向けに適切にフォーマットされています。
失敗時: エンコードの問題には、YAMLで
data の代わりに stringData を使用します。TLSシークレットエラーの場合、openssl x509 -in tls.crt -text -noout で証明書とキーのフォーマットを確認します。アクセス問題の場合、ServiceAccount RBACパーミッションを確認します。kubectl get secret myapp-secret -o jsonpath='{.data.api-key}' | base64 -d でデコードされたシークレットを表示します。
ステップ3: ヘルスチェックとリソース制限を含むDeploymentの作成
プローブとリソース管理を含む本番対応設定でアプリケーションをデプロイします。
# deployment.yaml apiVersion: apps/v1 kind: Deployment metadata: name: myapp namespace: myapp-prod labels: app: myapp version: v1.0.0 spec: replicas: 3 strategy: type: RollingUpdate rollingUpdate: maxSurge: 1 maxUnavailable: 0 # Zero-downtime updates selector: matchLabels: app: myapp template: metadata: labels: app: myapp version: v1.0.0 annotations: prometheus.io/scrape: "true" prometheus.io/port: "8080" prometheus.io/path: "/metrics" spec: serviceAccountName: myapp securityContext: runAsNonRoot: true runAsUser: 1000 fsGroup: 1000 containers: - name: myapp image: myregistry.io/myapp:v1.0.0 imagePullPolicy: IfNotPresent ports: - name: http containerPort: 8080 protocol: TCP env: - name: LOG_LEVEL valueFrom: configMapKeyRef: name: myapp-config key: LOG_LEVEL - name: DB_USERNAME valueFrom: secretKeyRef: name: myapp-db-secret key: username - name: DB_PASSWORD valueFrom: secretKeyRef: name: myapp-db-secret key: password - name: POD_NAME valueFrom: fieldRef: fieldPath: metadata.name - name: POD_NAMESPACE valueFrom: fieldRef: fieldPath: metadata.namespace resources: requests: cpu: 250m memory: 256Mi limits: cpu: 500m memory: 512Mi livenessProbe: httpGet: path: /healthz port: http initialDelaySeconds: 30 periodSeconds: 10 timeoutSeconds: 5 failureThreshold: 3 readinessProbe: httpGet: path: /ready port: http initialDelaySeconds: 5 periodSeconds: 5 timeoutSeconds: 3 failureThreshold: 2 startupProbe: httpGet: path: /healthz port: http initialDelaySeconds: 0 periodSeconds: 10 timeoutSeconds: 3 failureThreshold: 30 # 5 minutes for slow startup volumeMounts: - name: config mountPath: /etc/myapp readOnly: true - name: cache mountPath: /var/cache/myapp volumes: - name: config configMap: name: myapp-properties - name: cache emptyDir: {} imagePullSecrets: - name: registry-credentials
デプロイと監視:
# Apply deployment kubectl apply -f deployment.yaml # Watch rollout status kubectl rollout status deployment/myapp -n myapp-prod # Check pod status kubectl get pods -n myapp-prod -l app=myapp # View pod logs kubectl logs -n myapp-prod -l app=myapp --tail=50 -f # Describe deployment for events kubectl describe deployment myapp -n myapp-prod # Check resource usage kubectl top pods -n myapp-prod -l app=myapp
期待結果: Deploymentがローリングアップデート戦略で3つのレプリカを作成します。Podがトラフィックを受信する前にReadinessプローブをパスします。Livenessプローブが異常なPodを再起動します。リソースリクエスト・制限がOOMキルを防ぎます。ログが正常なアプリケーション起動を示します。
失敗時: ImagePullBackOffの場合、
kubectl get secret registry-credentials -o yaml でイメージが存在しimagePullSecretが有効であることを確認します。CrashLoopBackOffの場合、kubectl logs pod-name --previous でログを確認します。プローブ失敗の場合、kubectl port-forward と curl localhost:8080/healthz でエンドポイントを手動テストします。OOMKilledされたPodの場合、メモリ制限を増やすかメモリリークを調査します。
ステップ4: ServiceとLoad Balancerでアプリケーションを公開
Serviceリソースでアプリケーションを内部および外部に公開します。
# service.yaml apiVersion: v1 kind: Service metadata: name: myapp namespace: myapp-prod # ... (see EXAMPLES.md for complete configuration)
Serviceの適用とテスト:
# Apply services kubectl apply -f service.yaml # Get service details kubectl get svc -n myapp-prod # ... (see EXAMPLES.md for complete configuration)
期待結果: LoadBalancer ServiceがパブリックIP・ホスト名を持つ外部LBをプロビジョニングします。ClusterIP Serviceが安定した内部DNSを提供します。EndpointsリストがヘルシーなPod IPを表示します。curlリクエストが期待されるレスポンスで成功します。
失敗時: LoadBalancerが保留中の場合、クラウドプロバイダーの統合とクォータを確認します。エンドポイントがない場合、
kubectl get pods --show-labels でPodラベルがServiceセレクターと一致することを確認します。接続が拒否される場合、targetPortがコンテナポートと一致することを確認します。デバッグ用にServiceレイヤーをバイパスするために kubectl port-forward を使用します。
ステップ5: Horizontal Pod Autoscalingの設定
CPU・メモリまたはカスタムメトリクスに基づく自動スケーリングを実装します。
# hpa.yaml apiVersion: autoscaling/v2 kind: HorizontalPodAutoscaler metadata: name: myapp-hpa namespace: myapp-prod # ... (see EXAMPLES.md for complete configuration)
metrics-serverがない場合のインストール:
# Install metrics-server kubectl apply -f https://github.com/kubernetes-sigs/metrics-server/releases/latest/download/components.yaml # Verify metrics-server kubectl get deployment metrics-server -n kube-system kubectl top nodes # ... (see EXAMPLES.md for complete configuration)
期待結果: HPAがCPU・メモリメトリクスを監視します。閾値を超えると、レプリカがmaxReplicasまでスケールアップします。負荷が減少すると、レプリカが徐々にスケールダウンします(安定化ウィンドウがフラッピングを防ぎます)。
kubectl top でメトリクスが表示されます。
失敗時: メトリクスが「unknown」の場合、metrics-serverが実行中でPodにリソースリクエストが定義されていることを確認します。スケーリングがない場合、
kubectl top pods で現在の使用率が実際にターゲットを超えていることを確認します。フラッピングの場合、stabilizationWindowSecondsを増やします。スケールアップが遅い場合、scaleUpポリシーのperiodSecondsを減らします。
ステップ6: HelmチャートでアプリケーションをパッケージNG
マルチ環境デプロイメント向けの再利用可能なHelmチャートを作成します。
# Create Helm chart structure helm create myapp-chart cd myapp-chart # Edit Chart.yaml cat > Chart.yaml <<EOF # ... (see EXAMPLES.md for complete configuration)
期待結果: Helmチャートがテンプレート化された値を持つすべてのKubernetesリソースをパッケージングします。ドライランがレンダリングされたマニフェストを表示します。インストールが正しい順序ですべてのリソースをデプロイします。アップグレードがローリングアップデートを実行します。ロールバックが以前のリビジョンに戻ります。
失敗時: テンプレートエラーの場合、インストールなしにローカルでレンダリングするために
helm template . を実行します。依存関係の問題には helm dependency update を実行します。値オーバーライド失敗の場合、YAMLパスがvalues.yamlに存在することを確認します。helm get manifest myapp -n myapp-prod で実際にデプロイされたリソースを確認します。
バリデーション
- PodがすべてのコンテナがReadyになった状態でRunning
- Serviceエンドポイントに追加される前にReadinessプローブがパスする
- Livenessプローブが異常なコンテナを自動的に再起動する
- リソースリクエストと制限がOOMキルとノードのオーバーコミットを防ぐ
- SecretとConfigMapが期待値で正しくマウントされている
- ServiceがDNS(cluster.local)経由で他のPodから解決される
- LoadBalancer・Ingressが外部ネットワークからアクセス可能
- HPAが負荷下でレプリカをスケールアップし、アイドル時にスケールダウンする
- ローリングアップデートがゼロダウンタイムで完了する
- ログがkubectl logsまたは集中ロギングで収集・アクセス可能
よくある落とし穴
-
Readinessプローブの欠如: Podが完全に起動する前にトラフィックを受信します。アプリケーションの依存関係を検証するReadinessプローブを常に実装してください。
-
起動時間の不足: 高速なLivenessプローブが起動の遅いアプリを終了させます。初期化に十分なfailureThresholdを持つstartupProbeを使用してください。
-
リソース制限なし: Podが無制限のCPU・メモリを消費し、ノードの不安定化を引き起こします。リクエストと制限を常に設定してください。
-
ハードコードされた設定: マニフェスト内の環境固有の値が再利用を妨げます。ConfigMap、Secret、Helm値を使用してください。
-
デフォルトのServiceAccount: Podに不必要なクラスター権限があります。最小限のRBACを持つ専用ServiceAccountを作成してください。
-
ローリングアップデート戦略なし: Deploymentがすべてのドを同時に再作成し、ダウンタイムを引き起こします。maxUnavailable: 0でRollingUpdateを使用してください。
-
バージョン管理されたシークレット: Gitにコミットされた機密データ。sealed-secrets、external-secrets-operator、またはvaultを使用してください。
-
PodDisruptionBudgetなし: クラスターメンテナンスがノードをドレインしサービスを破壊します。最小利用可能レプリカを確保するためにPodDisruptionBudgetを作成してください。
関連スキル
- Kubernetes前のコンテナオーケストレーションの基礎setup-docker-compose
- デプロイ向けコンテナイメージの作成containerize-mcp-server
- 高度なHelmチャート開発write-helm-chart
- SealedSecretsとexternal-secrets-operatormanage-kubernetes-secrets
- NGINX IngressとCert-Managerのセットアップconfigure-ingress-networking
- 宣言型デプロイメント向けArgoCD/Fluximplement-gitops-workflow
- イメージレジストリ統合setup-container-registry