はじめに
Kubernetes の API は常に進化しています。古いクラスタで動作していたマニフェストが、新しいクラスタでは API バージョンの削除やフィールド構造の変更によって動作しなくなることがあります。CKAD の業務において、これは一般的なメンテナンス作業として現れます。つまり、エラーを読み解き、現在の API を特定し、マニフェストを更新し、新しいバージョンが受け入れられることを確認するプロセスです。
この実験では、古い Ingress マニフェストを networking.k8s.io/v1beta1 から networking.k8s.io/v1 へ移行します。まず Ingress が参照する Service を作成し、古いマニフェストが失敗することを確認します。その後、kubectl の探索コマンドを使用して現在の API を調査し、マニフェストを書き換えて、修正した Ingress を適用します。
Service 参照の準備
このステップでは、クリーンな名前空間とシンプルな Service を準備します。古いマニフェストと新しいマニフェストの両方がこの Service を参照するようにすることで、Pod の準備状況やトラフィックルーティングではなく、API の構造に焦点を当てた移行作業を行います。
/home/labex/project から開始します:
mkdir -p /home/labex/project
cd /home/labex/project
Kubernetes API サーバーにアクセスできるか確認します。VM が起動した直後でノードの準備ができていない場合は、数秒待ってから再度コマンドを実行してください。
kubectl get nodes --request-timeout=5s
期待される出力例:
NAME STATUS ROLES AGE VERSION
labex-v135 Ready control-plane ... v1.35...
ckad-prep-api-migration という名前の名前空間を作成し、現在の名前空間として設定します:
kubectl create namespace ckad-prep-api-migration
kubectl config set-context --current --namespace=ckad-prep-api-migration
app-web という名前の ClusterIP Service を作成します。--tcp=80:80 オプションは、Service がポート 80 でリッスンし、一致する Pod が存在すればターゲットポート 80 に転送することを意味します。今回の移行実験では、HTTP トラフィックではなく Ingress API フィールドの検証が目的であるため、Service オブジェクトが存在するだけで十分です。
kubectl create service clusterip app-web --tcp=80:80
Service が存在することを確認します:
kubectl get service app-web
期待される出力例:
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
app-web ClusterIP ... <none> 80/TCP ...
非推奨マニフェストの失敗を確認
このステップでは、古い Ingress マニフェストを作成し、現在のクラスタで拒否される様子を確認します。移行作業における最初のヒントは多くの場合 API サーバーのエラーメッセージであるため、これは非常に有益な練習です。
old-ingress.yaml を作成します:
cat > old-ingress.yaml <<'EOF'
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: app-web
spec:
rules:
- host: app.example.local
http:
paths:
- path: /
backend:
serviceName: app-web
servicePort: 80
EOF
ファイルの上部を確認します。apiVersion フィールドは、どの API グループとバージョンがこのオブジェクトを処理すべきかを Kubernetes に伝えます。
sed -n '1,20p' old-ingress.yaml
期待される出力例:
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
...
serviceName: app-web
servicePort: 80
作成は行わずに、API サーバーにマニフェストの検証を依頼します。--dry-run=server は検証のためにオブジェクトを API サーバーに送信します。|| true を付けているのは、この失敗は想定内であるため、チュートリアルを中断させないためです。
kubectl apply --dry-run=server -f old-ingress.yaml || true
以下のようなエラーが出力されるはずです:
error: resource mapping not found for name: "app-web" namespace: "" from "old-ingress.yaml": no matches for kind "Ingress" in version "networking.k8s.io/v1beta1"
重要な証拠は no matches for kind "Ingress" in version "networking.k8s.io/v1beta1" です。これは、現在のクラスタがこの API バージョンをサポートしていないことを意味します。
現在の Ingress API 仕様の調査
このステップでは、ファイルを書き換える前に現在の Ingress API を調査します。これは移行作業を確実に行うための重要なプロセスです。クラスタが受け入れ可能な仕様を提示してくれるので、推測でフィールドを埋める必要はありません。
提供されている Ingress リソースを一覧表示します:
kubectl api-resources | grep -i '^ingresses'
期待される出力例:
ingresses ing networking.k8s.io/v1 true Ingress
kubectl explain を使用して、現在のバックエンド Service フィールドを調査します。Service バックエンドは spec.rules[].http.paths[].backend.service の下にネストされているため、パスは長くなります。
kubectl explain ingress.spec.rules.http.paths.backend.service --recursive | sed -n '1,80p'
期待される出力例:
GROUP: networking.k8s.io
KIND: Ingress
VERSION: v1
FIELD: service <IngressServiceBackend>
...
name <string> -required-
port <ServiceBackendPort> -required-
次に、移行後の current-ingress.yaml を作成します。新しいマニフェストでは networking.k8s.io/v1 を使用し、pathType を追加し、serviceName と servicePort をネストされた service.name および service.port.number フィールドに置き換えます。
cat > current-ingress.yaml <<'EOF'
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: app-web
spec:
rules:
- host: app.example.local
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: app-web
port:
number: 80
EOF
サーバーサイドのドライランで、移行後のマニフェストを検証します:
kubectl apply --dry-run=server -f current-ingress.yaml
期待される出力:
ingress.networking.k8s.io/app-web created (server dry run)
移行した Ingress の適用と確認
このステップでは、移行した Ingress を作成し、Kubernetes に保存されたフィールドを確認します。リソースを適用することは、マニフェストが現在の API サーバーと一致したことを証明する最終的なステップです。
移行したマニフェストを適用します:
kubectl apply -f current-ingress.yaml
期待される出力:
ingress.networking.k8s.io/app-web created
Ingress を一覧表示します:
kubectl get ingress app-web
期待される出力例:
NAME CLASS HOSTS ADDRESS PORTS AGE
app-web ... app.example.local ... 80 ...
保存されたオブジェクトから、移行されたバックエンドフィールドを直接確認します:
kubectl get ingress app-web -o jsonpath='{.apiVersion}{" "}{.spec.rules[0].http.paths[0].pathType}{" "}{.spec.rules[0].http.paths[0].backend.service.name}{":"}{.spec.rules[0].http.paths[0].backend.service.port.number}{"\n"}'
期待される出力:
networking.k8s.io/v1 Prefix app-web:80
この出力は、オブジェクトが現在の API バージョンを使用していること、パスに明示的な pathType が設定されていること、そしてバックエンドが networking.k8s.io/v1 で要求されるネストされた Service 参照を使用していることの 3 点を証明しています。
まとめ
実用的な API 移行ワークフローを実践しました。古い networking.k8s.io/v1beta1 の Ingress マニフェストを作成し、サーバーサイドのドライランを使用して現在のクラスタで拒否されることを確認しました。その後、提供されている networking.k8s.io/v1 API を調査し、pathType とネストされた Service 参照を使用してバックエンドフィールドを書き換え、最後に移行した Ingress を適用して確認を行いました。


