Обновление устаревших манифестов API

KubernetesBeginner
Практиковаться сейчас

Введение

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.