エラーの概要

Kubernetes APIサーバーへのリクエストが不正な形式や内容であることを示すHTTP 400エラーです。マニフェストファイルの構文エラーAPI仕様に違反するフィールド値、または不完全なリクエストボディが原因となります。このエラーはクラスタとの通信に成功した後、サーバー側でリクエストの妥当性検証に失敗したときに発生する重要な診断シグナルです。

実際のエラーメッセージ例

{
  "kind": "Status",
  "apiVersion": "v1",
  "metadata": {},
  "status": "Failure",
  "message": "error validating data: ValidationError(Pod.spec.containers[0].resources.limits): invalid type for io.k8s.api.core.v1.ResourceList: got \"string\", expected \"object\"",
  "reason": "BadRequest",
  "code": 400
}
error: error validating "deployment.yaml": error validating data: 
[ValidationError(Deployment.spec.template.spec.containers[0].ports[0].containerPort): 
invalid type for io.k8s.api.core.v1.ContainerPort: got "string", expected "integer", 
ValidationError(Deployment.spec.template.spec.containers[0].image): string length must be non-empty]

よくある原因と解決手順

原因1: YAML構文エラーまたはフィールド型の不一致

なぜ発生するか: Kubernetesマニフェストファイルで、数値型フィールドを文字列で指定したり、オブジェクトフィールドにスカラー値を渡したりするときに発生します。特にポート番号やリソース制限でこの問題が頻発します。

Before(エラーが起きるコード):

apiVersion: v1
kind: Pod
metadata:
  name: nginx-pod
spec:
  containers:
  - name: nginx
    image: nginx:latest
    ports:
    - containerPort: "8080"  # 文字列型で指定
    resources:
      limits:
        memory: 512Mi          # オブジェクト型だが不正
        cpu: "1"              # 数値型だが文字列

After(修正後):

apiVersion: v1
kind: Pod
metadata:
  name: nginx-pod
spec:
  containers:
  - name: nginx
    image: nginx:latest
    ports:
    - containerPort: 8080      # 整数型で指定
    resources:
      limits:
        memory: 512Mi
        cpu: "1"               # CPU値は文字列でも有効
      requests:
        memory: 256Mi
        cpu: "500m"

原因2: 必須フィールドの欠落

なぜ発生するか: Kubernetesリソースの必須フィールド(例:metadata.nameコンテナimage)が定義されていない場合に発生します。APIサーバーは最小限のリソース定義すら受け付けません。

Before(エラーが起きるコード):

apiVersion: apps/v1
kind: Deployment
metadata:
  name: web-app
spec:
  replicas: 3
  selector:
    matchLabels:
      app: web
  template:
    metadata:
      labels:
        app: web
    spec:
      containers:
      - name: web-container
        # imageフィールドが欠落
        ports:
        - containerPort: 80

After(修正後):

apiVersion: apps/v1
kind: Deployment
metadata:
  name: web-app
spec:
  replicas: 3
  selector:
    matchLabels:
      app: web
  template:
    metadata:
      labels:
        app: web
    spec:
      containers:
      - name: web-container
        image: nginx:1.21      # 必須フィールドを追加
        ports:
        - containerPort: 80

原因3: APIバージョンまたはリソース種別の不一致

なぜ発生するか: 廃止されたAPIバージョンを使用したり、クラスタにインストールされていないカスタムリソース定義(CRD)にアクセスしたりするときに発生します。Kubernetes 1.16以降でv1beta1 extensionsが廃止されるなど、バージョン間での互換性問題が頻繁に起きます。

Before(エラーが起きるコード):

kubectl apply -f - <<EOF
apiVersion: extensions/v1beta1  # Kubernetes 1.16+で廃止
kind: Deployment
metadata:
  name: old-deployment
spec:
  replicas: 2
  template:
    metadata:
      labels:
        app: myapp
    spec:
      containers:
      - name: myapp
        image: myapp:1.0
EOF

After(修正後):

kubectl apply -f - <<EOF
apiVersion: apps/v1  # 現在サポートされているバージョン
kind: Deployment
metadata:
  name: old-deployment
spec:
  replicas: 2
  selector:
    matchLabels:
      app: myapp
  template:
    metadata:
      labels:
        app: myapp
    spec:
      containers:
      - name: myapp
        image: myapp:1.0
EOF

原因4: セレクタラベルの不一致

なぜ発生するか: Deployment、Service、StatefulSetなどで定義したselectorのラベルが、Pod テンプレートのlabelsと一致していない場合に発生します。これにより、リソースが自身が管理すべきポッドを識別できず、検証エラーが発生します。

Before(エラーが起きるコード):

apiVersion: apps/v1
kind: Deployment
metadata:
  name: app-deploy
spec:
  selector:
    matchLabels:
      app: myapp
      environment: production
  template:
    metadata:
      labels:
        app: myapp
        # environmentラベルが欠落
        version: v1

After(修正後):

apiVersion: apps/v1
kind: Deployment
metadata:
  name: app-deploy
spec:
  selector:
    matchLabels:
      app: myapp
      environment: production
  template:
    metadata:
      labels:
        app: myapp
        environment: production  # セレクタと一致させる
        version: v1

Kubernetes固有の注意点

ServiceAccountとRBAC設定

400エラー認可エラー(403)ではなく検証エラーですが、ServiceAccountが適切に設定されていない場合、リソース作成時に引き続き400が発生することがあります。kubectl auth can-iコマンドで権限確認を併せて実施してください。

kubectl auth can-i create deployments --as=system:serviceaccount:default:my-sa -n default

Namespace指定の欠落

リソース定義でmetadata.namespaceを明示しない場合、デフォルトNamespaceに作成されます。別のNamespaceに配置する場合は、明示的に指定するか、-nフラグを使用してください。

kubectl apply -f deployment.yaml -n production

CRD(CustomResourceDefinition)のバージョン不一致

インストール済みのCRDのバージョンと、マニフェストファイルのAPIバージョンが一致していない場合、400エラーが発生します。kubectl api-resourcesで確認可能です。

kubectl api-resources | grep customresource

環境変数置換の不完全性

テンプレート化されたマニフェストファイルで、プレースホルダーが置換されないまま送信された場合、不正なYAML値として認識されます。envsubstやkustomizeを使用する際は、置換前のファイルをバイパスしないよう注意してください。

それでも解決しない場合

ログ確認とデバッグコマンド

APIサーバーログを直接確認して、より詳細なエラーメッセージを取得してください。

# クラスタログの確認(マネージドKubernetesの場合はプロバイダーのコンソール使用)
kubectl logs -n kube-system deployment/kube-apiserver --tail=100

# リクエストの詳細を確認
kubectl apply -f deployment.yaml -v=8  # 最高レベルのverbosity

# マニフェストの検証(サーバーに送信前にドライラン)
kubectl apply -f deployment.yaml --dry-run=client -o yaml

公式ドキュメントへの参照

コミュニティリソース

問題が解決しない場合は、以下で検索してください。


免責事項:本記事の内容は、執筆時点の公開情報をもとに作成したものです。ソフトウェアの仕様は予告なく変更されることがあります。最新の情報は各ツールの公式サポートページをご確認ください。本記事の情報を利用した結果生じたいかなる損害についても、著者および運営者は責任を負いかねます。