エラー内容
error: unable to recognize "deploy.yaml": no matches for kind "Ingress" in version "extensions/v1beta1"
Kubernetes 1.22以降のクラスターに対して kubectl apply -f を実行したところ、YAMLファイルの構文は問題ないにもかかわらずエラーが発生しました。原因は構文ではありません。そのファイルに記載されているAPIバージョンが、クラスター上にもはや存在しないことが問題です。
根本原因
Kubernetes 1.22では extensions/v1beta1 APIグループが完全に削除されました。非推奨になったのではなく、削除されたのです。APIサーバーはそのグループ配下の Ingress が何を意味するか認識できないため、「no matches for kind」というエラーが表示されます。
Ingress APIはこの変更に至るまで3世代の変遷をたどりました:
- ≤ 1.13:
extensions/v1beta1のみ利用可能 - 1.14:
networking.k8s.io/v1beta1が導入され、extensions/v1beta1は非推奨に - 1.19:
networking.k8s.io/v1が安定版に昇格 - 1.22: 両ベータ版が廃止 — このバージョンからエラーが発生し始める
補足として、extensions/v1beta1 配下の Deployment、DaemonSet、ReplicaSet はすでに1.16で削除されています。複数のリソースタイプが同時に失敗する場合、マニフェストがKubernetes 1.14以前から引き継がれている可能性が高いです。
修正方法:マニフェストの更新
apiVersion の行を変更するだけでは不十分です。networking.k8s.io/v1 のIngressスペックではバックエンドフィールドの構造が変わり、pathType が必須になりました。3つの点を変更する必要があります。
旧形式(extensions/v1beta1 — 1.22以降では動作しない)
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: my-ingress
annotations:
kubernetes.io/ingress.class: nginx
spec:
rules:
- host: example.com
http:
paths:
- path: /
backend:
serviceName: my-service
servicePort: 80
新形式(networking.k8s.io/v1 — 1.19以降で動作する)
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: my-ingress
annotations:
kubernetes.io/ingress.class: nginx
spec:
rules:
- host: example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: my-service
port:
number: 80
変更点の詳細は以下の通りです:
backend.serviceName→backend.service.namebackend.servicePort→backend.service.port.number(名前付きポートの場合は.name)pathTypeが必須になりました —Prefix、Exact、またはImplementationSpecificを指定してください
kubectl-convertによる一括移行
多数のマニフェストを更新する必要がある場合、kubectl-convert プラグインを使用すれば各ファイルを手動で編集することなく自動変換できます:
# プラグインのインストール(Linux)
curl -LO "https://dl.k8s.io/release/$(kubectl version --client -o json | jq -r .clientVersion.gitVersion)/bin/linux/amd64/kubectl-convert"
chmod +x kubectl-convert
sudo mv kubectl-convert /usr/local/bin/
# 変換後の出力をプレビュー
kubectl convert -f old-ingress.yaml --output-version networking.k8s.io/v1
# 新しいファイルに保存
kubectl convert -f old-ingress.yaml --output-version networking.k8s.io/v1 > new-ingress.yaml
クラスターをアップグレードする前に、pluto を使ってリポジトリ全体の非推奨API使用箇所を一度にスキャンできます:
# plutのインストール(macOS)
brew install FairwindsOps/tap/pluto
# ディレクトリ内のすべてのYAMLファイルをスキャン
pluto detect-files -d ./k8s/
# 稼働中のクラスターで使用状況を確認
pluto detect-all-in-cluster
修正の確認
まず、クラスターが対象のAPIを公開しているか確認します:
kubectl api-versions | grep networking
# 以下が含まれているはずです: networking.k8s.io/v1
更新したマニフェストを適用し、結果を確認します:
kubectl apply -f deploy.yaml
# 期待される出力: ingress.networking.k8s.io/my-ingress created
kubectl get ingress my-ingress
kubectl describe ingress my-ingress
注意点として、このIngressが以前に古いAPIでデプロイされていた場合、クラスターに古いオブジェクトが残っている可能性があります。その場合は先に削除してから再適用してください:
kubectl delete ingress my-ingress
kubectl apply -f deploy.yaml
予防策
- CIパイプラインに
pluto detect-files -d ./k8s/を追加しましょう — クラスターに適用される前に非推奨のAPIバージョンを検出できます。 - アップグレード前に、対象バージョンの Kubernetes API非推奨ガイド を確認してください。すべての削除予定項目が明示されています。
- YAMLを手動で編集する際は、ToolCraftのYAML ↔ JSONコンバーター に貼り付けて構造上の問題を早期に発見しましょう。ブラウザ上で完全に動作するため、マニフェストにクラスター認証情報や内部ホスト名が含まれている場合でも外部に送信されません。
- 慣れていないクラスターでは、デプロイ前に
kubectl api-resources | grep ingressを実行して利用可能なリソースを正確に把握しておきましょう。

