Kubernetes 1.19 GA: обновляем production с extensions/v1beta1 на Ingress v1
Kubernetes 1.19 вышел GA с 14-месячной поддержкой. Переводим production-кластер: Ingress v1 стабилен, мигрируем манифесты с extensions/v1beta1, проверяем Helm-чарты.
Kubernetes 1.19 вышел в GA с расширенным циклом поддержки 14 месяцев вместо обычных 9
Kubernetes 1.19 получил статус GA. Главная административная новость релиза - цикл поддержки вырос с 9 до 14 месяцев. Для production-кластеров под managed-сопровождением это означает больше времени на плановое обновление и меньше паники по поводу EOL. Хорошая новость.
Техническая главная новость - Ingress API переходит из networking.k8s.io/v1beta1 и окончательно покидает extensions/v1beta1, получая стабильный статус в networking.k8s.io/v1. Мы отрабатывали этот переход ещё на RC в июле, и теперь, с выходом GA, пришло время прокатить его на production.
Что случилось с extensions/v1beta1
extensions/v1beta1 - это старая группа API, через которую в Kubernetes исторически проходили Ingress, Deployment, DaemonSet и прочие ресурсы до того, как у них появились постоянные дома. С 1.19 extensions/v1beta1 для Ingress помечен deprecated окончательно - apiserver его ещё принимает, но в audit log появляются предупреждения, а контроллеры, которые читают Ingress через deprecated группу, могут вести себя непредсказуемо в зависимости от версии.
Удалят extensions/v1beta1 для Ingress в 1.22 по roadmap. Так что время есть, но переписывать манифесты лучше сейчас, пока кластер свежий, а не в авральном режиме перед очередным обновлением.
Миграция манифестов: что реально меняется
Ключевые изменения в схеме networking.k8s.io/v1 по сравнению с extensions/v1beta1:
spec.backendпереименован вspec.defaultBackend. Если в старом манифесте былоspec.backend.serviceName/spec.backend.servicePort, теперь этоspec.defaultBackend.service.nameиspec.defaultBackend.service.port.number(порт стал объектом, не строкой/числом напрямую).- В путях (
spec.rules[].http.paths[]) появилось обязательное полеpathType- значенияPrefix,ExactилиImplementationSpecific. Без него apimachinery ругается на невалидный объект. servicePortвbackendтоже реструктурирован: теперьservice.port.nameилиservice.port.number- два отдельных поля вместо одного полиморфного.
Для аудита используем kubectl-convert - тот же инструмент, что и на RC:
kubectl-convert -f ingress-old.yaml --output-version networking.k8s.io/v1
Он честно показывает изменённую структуру, но аннотации не трогает - их правим руками. На нашем кластере прошло около десятка Ingress-манифестов, из них в трёх было поле spec.backend в старом виде, в остальных достаточно было поменять apiVersion и добавить pathType.
Проверка Helm-чартов и операторов
Перед обновлением узлов рабочей нагрузки прогнали helm list --all-namespaces и проверили версии чартов для всего, что разворачивает Ingress-ресурсы. Несколько наблюдений:
nginx-ingress (ingress-nginx). Чарт 3.x под контроллером 0.35+ работает с networking.k8s.io/v1 нормально. Версии чарта 2.x с контроллером 0.26-0.29 смотрят на extensions/v1beta1 при создании ресурсов через Helm - их надо обновлять. Мы были на 3.4, проблем нет.
cert-manager. Версия 1.0 (вышла буквально на прошлой неделе) полностью поддерживает новый Ingress API. До 0.16 включительно - создаёт Ingress-ресурсы через extensions/v1beta1. Если используете cert-manager и собираетесь оставаться на 0.15-0.16 долго - заложите время на проверку, что Certificate и Issuer через Ingress работают как ожидается после обновления кластера.
Операторы. Если оператор управляет Ingress-ресурсами напрямую через client-go, версия используемой им k8s-библиотеки важна. client-go 0.18 и старше работает с deprecated API, но может выдавать предупреждения. Мы прошлись по трём операторам на кластере - у двух были свежие образы, у одного пришлось проверить версию библиотеки в Dockerfile.
Порядок обновления
Использовали стандартную последовательность для kubeadm-кластера. Сначала control plane:
# На control plane ноде
apt-get update && apt-get install -y kubeadm=1.19.0-00
kubeadm upgrade plan
kubeadm upgrade apply v1.19.0
apt-get install -y kubelet=1.19.0-00 kubectl=1.19.0-00
systemctl restart kubelet
Затем рабочие ноды по одной - drain, обновление пакетов, uncordon, наблюдение за логами между шагами. На кластере с несколькими нодами рабочей нагрузки это занимает около часа с учётом ожидания выхода подов и проверки метрик.
После обновления control plane и до обновления рабочих нод кластер работает в смешанном состоянии: новый apiserver, старые kubelet-ы на воркерах. Kubernetes это допускает - version skew policy разрешает kubelet быть на две minor-версии ниже apiserver. Никаких проблем с workload в этот период не было.
Что ещё интересного в 1.19
Помимо Ingress v1 в релизе есть несколько вещей, на которые обратили внимание:
- Structured Logging - эксперимент по переводу kubelet и kube-scheduler на структурированный JSON-лог. В alpha, но интересно: если включить
--logging-format=json, логи становятся значительно удобнее для парсинга Filebeat/Fluentd. Включили на одном ноде, посмотрели - работает, хотя покрытие не полное, часть сообщений продолжает идти в старом формате. - Server-side Apply выходит в beta. Механизм, при котором apiserver сам отслеживает field ownership - кто последний писал поле, тот и владелец. Полезно при смешанном управлении ресурсами через Helm и kubectl apply.
kubectl debugстановится beta - удобнее отлаживать crashlooping-поды через ephemeral containers без написания отдельного debug-pod манифеста.
Где сейчас
Production-кластер обновлён. Ingress-манифесты переведены на networking.k8s.io/v1, чарты проверены, cert-manager обновлён до 1.0. Расширенный цикл поддержки 14 месяцев снижает давление на следующее плановое обновление - следующий milestone теперь не горит.
Чек-лист для тех, кто идёт тем же путём:
- Аудит Ingress-манифестов через
kubectl-convert, особенноspec.backendиservicePort. pathType- проверить что добавлен во всех путях, иначе apply упадёт.- Helm-чарты - версии nginx-ingress и cert-manager критичны, проверить отдельно.
- Операторы с Ingress - посмотреть версию client-go в образе, если оператор создаёт Ingress-ресурсы.
- kubeadm drain/uncordon на рабочих нодах - по одной, с паузой и наблюдением.