Введение
API Kubernetes постоянно развиваются. Манифест, который работал в старом кластере, может не сработать в новом из-за удаления версии API или изменения структуры полей. В работе специалиста CKAD это обычно выглядит как стандартная задача по обслуживанию: прочитать ошибку, определить актуальную версию API, обновить манифест и убедиться, что новая версия принята системой.
В этой лабораторной работе вы выполните миграцию старого манифеста Ingress с версии networking.k8s.io/v1beta1 на networking.k8s.io/v1. Сначала вы создадите Service, на который будет ссылаться Ingress, затем увидите ошибку при использовании старого манифеста, воспользуетесь командами обнаружения kubectl для проверки текущего API, перепишете манифест и примените исправленный Ingress.
Подготовка ссылки на Service
На этом этапе вы подготовите чистый namespace и простой Service. Старый и новый манифесты Ingress будут указывать на этот Service, поэтому миграция будет сосредоточена на структуре API, а не на готовности подов или маршрутизации трафика.
Начните работу в /home/labex/project:
mkdir -p /home/labex/project
cd /home/labex/project
Убедитесь, что API-сервер Kubernetes доступен. Если виртуальная машина только что запустилась и узел еще не готов, подождите несколько секунд и повторите команду.
kubectl get nodes --request-timeout=5s
Ожидаемый вывод:
NAME STATUS ROLES AGE VERSION
labex-v135 Ready control-plane ... v1.35...
Создайте namespace с именем ckad-prep-api-migration и установите его в качестве текущего:
kubectl create namespace ckad-prep-api-migration
kubectl config set-context --current --namespace=ckad-prep-api-migration
Создайте ClusterIP Service с именем app-web. Опция --tcp=80:80 означает, что Service прослушивает порт 80 и перенаправляет трафик на целевой порт 80, если существуют соответствующие поды. Для этой лабораторной работы достаточно самого объекта Service, так как вы проверяете поля API Ingress, а не HTTP-трафик.
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 сообщает Kubernetes, какая группа и версия API должны обрабатывать этот объект.
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.
Обнаружение актуальной структуры API Ingress
На этом этапе вы изучите текущий API Ingress перед тем, как переписывать файл. Это дисциплинирует процесс миграции: не нужно угадывать новые поля, когда кластер может показать вам корректную структуру.
Выведите список доступных ресурсов Ingress:
kubectl api-resources | grep -i '^ingresses'
Ожидаемый вывод:
ingresses ing networking.k8s.io/v1 true Ingress
Используйте kubectl explain для проверки текущего поля backend-сервиса. Путь длинный, так как backend сервиса вложен в 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 ...
Проверьте мигрированные поля backend напрямую из сохраненного объекта:
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, а backend использует вложенную ссылку на Service, требуемую в networking.k8s.io/v1.
Резюме
Вы отработали практический процесс миграции API. Вы создали старый манифест Ingress версии networking.k8s.io/v1beta1, использовали серверную валидацию (dry-run), чтобы подтвердить, что текущий кластер отклоняет его, изучили актуальный API networking.k8s.io/v1, переписали поля backend с использованием pathType и вложенной ссылки на Service, а затем применили и проверили мигрированный Ingress.


