デプロイメント失敗のデバッグ:よくあるYAMLと設定エラーの特定

Kubernetesデプロイメントの失敗をデバッグするには、イベント、YAML構造、イメージプル、プローブ、リソース、スケジューリングルールを確認します。

デプロイメント失敗のデバッグ:よくあるYAMLと設定エラーの特定

Kubernetesのデプロイメント失敗は、通常、PodがPendingImagePullBackOffCrashLoopBackOff状態でスタックしたり、利用可能なレプリカがゼロになったりすることで現れます。原因はイベントで確認できることが多いですが、Deployment、ReplicaSet、Podを正しい順序で調査する必要があります。

このガイドでは、YAMLのミス、イメージプルの問題、不適切なプローブ、リソース制約、スケジューリングルールなど、デプロイメントが正常にならない原因を特定するためのチェック手順を説明します。

最初のステップ:デプロイメントステータスとイベントの確認

デプロイメントが失敗した場合、最初の診断ステップとして、常にプライマリリソース自体と、それに関連する管理対象のReplicaSetおよびPodのイベントを確認する必要があります。これにより、Kubernetesが何を試みていて、なぜ失敗しているのか、最も高いレベルでの概要が得られます。

1. デプロイメントの健全性の確認

kubectl get deploymentsを使用して全体的なステータスを確認します。特にREADYUP-TO-DATEAVAILABLE列に注目してください。これらの値に不一致がある場合は、基盤となるPodに問題があることを示しています。

kubectl get deployments <deployment-name>

デプロイメントステータスで準備完了レプリカが少ないかゼロの場合は、ReplicaSetを確認します。

2. ReplicaSetとPodのイベントの確認

ReplicaSetは必要な数のPodを管理します。デプロイメントが失敗した場合、通常はReplicaSetがエラーの連鎖の原因です。通常<deployment-name>-<hash>という名前のReplicaSetに対してdescribeコマンドを使用します:

kubectl describe rs <replicaset-name>

重要なのは、出力の下部にあるEventsセクションを調べることです。このセクションには、スケジューリング試行、イメージプル失敗、ボリュームマウントの問題など、最近のアクションが詳細に記載されています。これらのイベントが決定的な証拠となることがよくあります。

最後に、Pod自体を確認します。Podは即時の失敗を報告します:

kubectl get pods -l app=<your-app-label>
kubectl describe pod <pod-name>

Podの説明でStateフィールドとReasonフィールドを探します。一般的な理由には、ImagePullBackOffErrImagePullCrashLoopBackOffPendingなどがあります。

YAMLマニフェストにおける一般的な設定エラー

YAMLファイルの設定ミスは、デプロイメント失敗の最も頻繁な原因です。これらのエラーは、単純なインデントミスから複雑な構造上の問題まで多岐にわたります。

1. YAMLの構文と構造エラー

Kubernetes APIは、正しいYAML構文(インデント、スペース、データ型)に非常に敏感です。YAMLが無効な場合、kubectl applyは多くの場合すぐに失敗し、ファイルを解析できないと表示します。

ベストプラクティス:リンターを使用する 適用する前に必ずYAML構文を検証してください。yamllintなどのツールや統合IDEサポートを使用すると、基本的な構文エラーをすぐにキャッチできます。

よくある構造エラーの例: マッピングまたはインデントの誤り。

# 誤り:containersはspec.template.specの下に属し、spec.templateの直下ではない
apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-app
spec:
  template:
    metadata:
      labels:
        app: my-app
    containers:
      - name: my-app
        image: myregistry/myapp:v1

正しい配置:

spec:
  template:
    metadata:
      labels:
        app: my-app
    spec:
      containers:
        - name: my-app
          image: myregistry/myapp:v1
          ports:
            - containerPort: 8080

2. イメージ参照とプルエラー

PodがImagePullBackOffまたはErrImagePull状態になった場合、問題はコンテナイメージへのアクセスに関連しています。

  • イメージ名/タグのタイプミス: イメージリポジトリ、名前、タグのスペルを再確認してください。
  • プライベートレジストリ認証: プライベートレジストリからプルする場合は、イメージプルシークレットを作成し、Pod仕様でimagePullSecretsとして参照していることを確認してください。
# ImagePullSecretの使用例
spec:
  imagePullSecrets:
    - name: my-registry-secret
  containers:
    - name: my-app
      image: private.example.com/my-app:v1

3. リソース要求と制限の違反

PodがPendingステータスのままで、イベントにリソース不足が記載されている場合、クラスターノードがYAMLで定義されたCPUまたはメモリ要件を満たせないことを意味します。

デプロイメントマニフェストで指定された制限を確認します:

resources:
  requests:
    memory: "512Mi"
    cpu: "500m"
  limits:
    memory: "1Gi"
    cpu: "1"

トラブルシューティング手順:

  1. kubectl describe nodesを使用して利用可能な容量を確認します。
  2. 0/3 nodes are available: 3 Insufficient cpuのようなイベントが表示された場合は、YAMLのrequestsを減らすか、クラスターにノードを追加する必要があります。

高度な設定の問題

基本的な構文やイメージプル以外にも、ネットワーキング、ストレージ、スケジューリングを含む複雑な設定が、診断が難しい失敗を引き起こす可能性があります。

1. プローブの設定ミス(LivenessとReadiness)

PodがCrashLoopBackOffに移行する場合、多くの場合、コンテナは起動するがすぐにチェックに失敗するか、起動してもReadinessプローブに繰り返し失敗することを意味します。

  • Liveness Probe: これが繰り返し失敗すると、Kubernetesはコンテナを再起動します。kubectl describe pod <pod-name>でプローブ失敗イベントを確認し、再起動後にkubectl logs <pod-name> --previousを確認します。
  • Readiness Probe: これが失敗すると、Podは実行を続けますが、Serviceのエンドポイントから除外されます。パス、ポート、期待される応答コードが、アプリケーションが実際に提供しているものと一致していることを確認してください。

よくあるReadiness Probeエラーの例: 間違ったポートをターゲットにしている、またはアプリがTCPのみを公開しているのにHTTPを期待している。

2. ボリュームとPersistentVolumeClaim(PVC)の失敗

ボリュームの問題でPodがPending状態になっている場合は、PVCのステータスを確認します:

kubectl get pvc <pvc-name>

PVCのステータスがPendingの場合、クラスターが一致するStorageClassまたは適切なPersistentVolumeを見つけられなかったことを意味します。PVCのイベントで特定のバインドエラーを確認します。

3. AffinityとAnti-Affinityルール

nodeAffinitypodAntiAffinityなどの複雑なスケジューリングルールは、すべての基準を満たすノードがない場合、意図せずPodのスケジューリングを妨げる可能性があります。PodがPendingのままで、イベントにスケジューリング制限が記載されている場合は、これらのルールを確認します。

たとえば、特定のラベル(nodeSelector)を持つノードでPodを実行する必要があるが、そのラベルを持つノードが存在しない場合、Podはスケジューリングされません。

# 例:'disktype: ssd'というラベルが付いたノードにデプロイメントを制限する
spec:
  nodeSelector:
    disktype: ssd
  containers:
  # ...

トラブルシューティングのヒント: 制限的なnodeSelectorまたはaffinityルールを一時的にコメントアウトします。Podが正常にスケジューリングされた場合、問題は選択基準にあることがわかります。

デバッグのワークフロー

デプロイメントの失敗に直面した場合は、次の構造化されたパスに従います:

  1. デプロイメントステータス: kubectl get deployments -> レプリカは準備完了を報告していますか?
  2. Podイベント: kubectl describe pod <failing-pod> -> Eventsセクションで即時のエラー(ImagePull、OOMKilled、Volumeの問題)を確認します。
  3. コンテナログ: kubectl logs <failing-pod> -> コンテナが起動してもクラッシュする場合(CrashLoopBackOff)、アプリケーションロジックまたはlivenessプローブが疑わしいです。
  4. リソースチェック: PodがPendingの場合は、リソース制約(Insufficient cpu/memory)または失敗したボリュームバインディング(PVCステータス)を確認します。
  5. 設定の検証: YAMLのインデント、正しいフィールド名、有効なリソース値(requests/limits)を確認します。

推測するのではなく、クラスターの証拠から作業を開始します。ステータス、イベント、ログ、リソース、マニフェスト構造をこの順序で確認し、見つけたエラーに一致する最小限のYAML変更を行います。