company_banner

Kubernetes 1.15: обзор основных новшеств



    В понедельник должен был официально состояться (но пока этого не случилось… ОБНОВЛЕНО 20.06: в блоге K8s появился анонс) очередной релиз Kubernetes — 1.15. По сложившейся для нашего блога традиции, рассказываем о наиболее значимых изменениях в новой версии.

    Информация, использованная для подготовки этого материала, взята из таблицы Kubernetes enhancements tracking, CHANGELOG-1.15 и сооветствующих issues, pull requests, а также Kubernetes Enhancement Proposals (KEP). Поскольку на следующей неделе пройдет конференция KubeCon в Шанхае, у этого релиза был сокращённый 11-недельный цикл (вместо 12 недель), что на количество значимых изменений, впрочем, заметно не повлияло. Итак, поехали!..

    Хранилища данных


    Представлен новый API ExecutionHook, позволяющий динамически исполнять пользовательские команды в pod'е/контейнере или группе pod'ов/контейнеров, а вместе с ним — соответствующий контроллер (ExecutionHookController), реализующий управление жизненным циклом хука. Мотивацией к появлению этой фичи стало желание предоставить пользователям возможность создавать/удалять снапшоты в соответствии с логикой работы приложения, т.е. выполнять какие-то специфичные для приложения команды до и после создания снапшота. Предполагается, что такие хуки также могут быть полезны и для других ситуаций — например, выполнения обновлений, отладки, обновления конфигурационных файлов, рестарта контейнера, подготовки к иным событиям вроде миграции базы данных. Текущий статус — альфа-версия (ожидается перевод в бету для следующего релиза), подробности — в KEP.

    В ephemeral-storage, что позволяет разграничивать для конкретных pod'ов/контейнеров объём общего разделяемого пространства (shared storage), добавлена поддержка квот файловой системы. Этот новый механизм использует квоты на проект (project quotas), доступные в XFS и ext4, обеспечивая мониторинг потребления ресурсов и опциональное накладывание лимитов на них. Текущий статус — альфа-версия; планы по будущим релизам пока не уточняются.

    Ещё одна новая возможность, представленная sig-storage, — использование существующих PVC в качестве DataSource для создания новых PVC. Иными словами, это реализация функции клонирования томов. Клоны следует отличать от снапшотов, поскольку каждый клон является новым и «полноценным» томом: он создан как копия уже существующего, однако полностью следует жизненному циклу обычных томов (в отличие от снапшотов, хоть и являющихся копиями томов на определённый момент времени, но не самостоятельными томами). Иллюстрация использования возможности:

    kind: PersistentVolumeClaim
    apiVersion: v1
    metadata:
        name: pvc-2
        namespace: myns
    spec:
      capacity:
        storage: 10Gi
      dataSource:
        kind: PersistentVolumeClaim
        name: pvc-1

    В этом случае будет создан новый самостоятельный PV/PVC (pvc-2), содержащий те же данные, что были на pvc-1. При этом указано, что новый PVC должен иметь то же пространство имён, что и оригинальный.

    Существующие ограничения — поддержка только динамического provisioner'а и только плагинов CSI (у них должна присутствовать capability CLONE_VOLUME). Подробнее читайте в KEP.

    До статуса бета-версии (а значит и активации в инсталляциях Kubernetes по умолчанию) «доросли» следующие возможности:

    • Функция расширения размера Persistent Volume «онлайн», т.е. без необходимости в рестарте pod'а, использующего соответствующий PVC. Впервые (в статусе альфа-версии) она появилась в K8s 1.11.
    • Поддержка переменных окружения для названий директорий, монтируемых как subPath, которая была впервые представлена в K8s 1.11 и получила развитие в прошлом 1.14.

    А вот процесс миграции внутренностей старых плагинов для хранилищ, реализованных внутри кодовой базы Kubernetes (in-tree), в пользу плагинов для нового интерфейса CSI затянулся. Ожидалось, что к релизу 1.15 завершат миграцию всех плагинов облачных провайдеров, однако принято решение оставить статус альфа-версии, поскольку фича зависит от API, представленных в K8s 1.15 и пока что реализованных тоже лишь в альфа-версии (в частности, речь идёт об улучшениях в поддержке Azure: плагинов Azure File и Azure Disk в csi-translation-lib).

    Планировщик


    Два заметных нововведения — оба пока в виде альфа-версий — доступны в планировщике Kubernetes.

    Первое — фреймворк планирования (Kubernetes Scheduling Framework), представляющий собой новый набор API для плагинов, расширяющих возможности существующего планировщика. Плагины создаются вне основного репозитория (out-of-tree), но входят в состав планировщика при компиляции. Таким образом, функциональное ядро планировщика остаётся максимально простым и удобным в поддержке, а дополнительные возможности реализуются отдельно, причём без тех многочисленных ограничений, которыми «страдал» нынешний способ расширения фич планировщика (с помощью webhooks).

    В новом фреймворке каждая попытка планирования pod'а разбивается на два этапа:

    • планирования (scheduling cycle) — где выбирается узел для pod'а,
    • и привязывания (binding cycle) — где выбранное решение реализуется в рамках кластера.

    На каждом из этих этапов (вместе их ещё называют контекстом планирования — scheduling context) существует множество точек расширения (extension points), на каждой из которых могут вызываться плагины фреймворка.


    (Жизненный цикл для вызова плагинов в Scheduling Framework.)

    В рамках альфа-версии фреймворка реализованы только точки Reserve, Unreserve и Prebind. Подробности об этом масштабном нововведении читайте в KEP.

    Второе — опция Non-Preempting для PriorityClasses.

    Классы приоритетов получили стабильный (GA) статус в прошлом релизе Kubernetes, что повлияло на процессы планирования и выборки pod'ов: pod'ы планируются в соответствии с приоритетом, а если pod не может быть создан из-за недостатка ресурсов, то pod'ы с более низким приоритетом могут вытесняться для освобождения необходимого пространства.

    Новая опция — Preempting, определяемая как булев в структуре PriorityClass, означает: если pod ожидает своего планирования и имеет Preempting=false, его создание не приведёт к вытеснению других pod'ов. Это поле появляется в PodSpec в процессе pod admission (аналогично тому, как и значение PriorityClass). Подробности о реализации — в KEP.

    API Machinery


    Для CustomResources представлены улучшения, призванные реализовать для данных, хранимых таким образом (в рамках JSON в CRD), поведение, которое лучше соответствует общепринятому в Kubernetes API (для «родных» объектов K8s):

    • автоматическое удаление полей, не указанных в схемах валидации OpenAPI, — подробности см. в KEP «Pruning for Custom Resources»;
    • возможность задавать в схемах валидации OpenAPI v3 значения по умолчанию (defaulting) для полей, что особенно важно для сохранения совместимости API при добавлении объектам новых полей, — подробности см. в KEP «Defaulting for Custom Resources».

    Обе фичи изначально планировались на включение в состав релиза K8s 1.12, однако только теперь представлены в виде альфа-версий.

    Этим изменения в CRD не ограничились:

    • возможность Publish CRD OpenAPI — т.е. валидация CustomResources на стороне сервера (с помощью схемы OpenAPI v3), представленная в прошлом релизе Kubernetes, — достигла бета-версии и теперь включена по умолчанию;
    • механизм преобразования версий CRD-ресурсов, основанный на внешних webhooks, тоже переведён в бета-версию.

    Другое интересное нововведение получило название Watch bookmark. Его суть сводится к добавлению нового типа события в Watch APIBookmark. Этот тип означает метку, что все объекты до определённой resourceVersion уже были обработаны watch'ем. Такой механизм позволит снизить нагрузку на kube-apiserver, уменьшив количество событий, которые требуется обрабатывать при каждом перезапуске watch'а, а также снизить количество нежелательных ошибок типа «resource version too old». В Kubernetes 1.15 фича имеет статус альфа-версии, а её повышение до беты ожидается к следующему релизу.

      Added    EventType = "ADDED"
      Modified EventType = "MODIFIED"
      Deleted  EventType = "DELETED"
      Error    EventType = "ERROR"
      Bookmark EventType = "BOOKMARK"

    (Возможные типы событий в Watch API.)

    В Admission Webhooks:

    • добавлена поддержка селектора объектов (object selector) в дополнение к существующим селекторам пространств имён;
    • реализована возможность регистрации конкретной версии ресурса и вызова, когда модифицируется любая более старая версия этого ресурса;
    • в AdmissionReview API добавлено поле Option, сообщающее об опциях выполняемой операции.

    Сеть


    Значимое новшество в сетевой части Kubernetes — так называемая «защита финализатора» (Finalizer Protection) для балансировщиков нагрузки. Теперь перед тем, как удалять ресурсы LoadBalancer'а, производится проверка, что соответствующий ресурс Service'а не был полностью удалён. Для этого к каждому сервису с type=LoadBalancer прикрепляется так называемый finalizer: при удалении такого сервиса реальное удаление ресурса блокируется, пока finalizer не будет удалён, а сам finalizer не удаляется до тех пор, пока не завершится «подчистка» ресурсов соответствующего балансировщика нагрузки (service.kubernetes.io/load-balancer-cleanup). Текущая версия реализации — альфа-версия, а подробности о ней можно найти в KEP.

    Кроме того:

    • Плагин NodeLocal DNS Cache, представленный в Kubernetes 1.13 и улучшающий производительность работы DNS, достиг бета-версии.
    • Kube-proxy больше автоматически не удаляет сетевые правила, созданные в результате его работы в других режимах (для этого требуется явный запуск kube-proxy --cleanup).

    CLI


    Как всегда, не обошлось без приятных мелочей в консольных командах для работы с кластерами Kubernetes:

    • Перевод kubectl get на получение данных с сервера (а не клиента) для полноценной поддержки расширений объявлен завершённым (стабильным).
    • В kubectl top добавили опцию --sort-by:

      $ kubectl --kubeconfig=kubectl.kubeconfig top pod --sort=memory
      NAME                               CPU(cores)   MEMORY(bytes)
      elasticsearch-logging-v1-psc43     2m           2406Mi
      hadoop-journalnode-2               13m          362Mi
      hodor-v0.0.5-3204531036-fqb0q      23m          64Mi
      kubernetes-admin-mongo-...         5m           44Mi 
      cauth-v0.0.5-2463911897-165m8      34m          10Mi
      test-1440672787-kvx8h              0m           1Mi
    • В kubectl rollout restart добавили поддержку DaemonSets и StatefulSets.
    • Добавлена новая команда kubeadm upgrade node для обновления узлов кластера, заменившая (ныне объявленные устаревшими) kubeadm upgrade node config и kubeadm upgrade node experimental-control-plane.
    • Добавлены новые команды kubeadm alpha certs certificate-key (для генерации случайного ключа, который можно затем передать в kubeadm init --experimental-upload-certs) и kubeadm alpha certs check-expiration (для проверки времени действия локальных PKI-сертификатов).
    • Команда kubeadm config upload объявлена устаревшей, поскольку её замена (kubeadm init phase upload-config) стала зрелой.

    Другие


    Среди прочих заметных изменений в Kubernetes 1.15:

    • Поддержка Pod Disruption Budget (PDB) добавлена и для сторонних ресурсов/контроллеров, основанных на CRD (например: EtcdCluster, MySQLReplicaSet…), с помощью Scale subresource. Пока это бета-версия, которую сделают стабильной уже в следующем релизе. Подробности — в KEP.
    • До бета-версии дошли две фичи для узлов/Kubelet: поддержка сторонних плагинов для мониторинга устройств (дабы вынести из Kubelet, т.е. out-of-tree, все специфичные для устройств знания) и SupportNodePidsLimit (изоляция PID'ов от узла к pod'ам).
    • Для кодовой базы Kubernetes добавлена и включена по умолчанию поддержка Go Modules (вместо Godep и режима GOPATH, объявленного устаревшим).
    • Поддержка AWS NLB (Network Load Balancer), впервые представленная ещё в K8s 1.9, достигла уровня бета-версии. В частности, она получила возможность конфигурации accessLogs, терминации TLS и обновления LoadBalancerSourceRanges.
    • Реализована возможность конфигурировать облачного провайдера Azure из секретов Kubernetes (для этого добавлена новая опция cloudConfigType, одним из значений которой может быть secret). Также Kubelet в Azure теперь может работать без Azure identity (для этого должен быть включён useInstanceMetadata).
    • В cluster-lifecycle довели до бета-версии возможность создания HA-кластеров с помощью kubeadm, а также завершили очередной этап (v1beta2) в реорганизации формата конфигурационного файла kubeadm.
    • В метрики от планировщика добавлено количество pods в статусе pending в разных очередях, а от CSI — статистика о томах через kubelet volume metrics.
    • Обновления в используемом/зависимом программном обеспечении: Go 1.12.5, cri-tools 1.14.0, etcd 3.3.10 (версия не изменилась для сервера, но обновилась для клиента). Не изменились версии CNI, CSI, CoreDNS (в одной из альфа-версий Kubernetes 1.15 её обновили до 1.5.0, но потом снова откатили к 1.3.1), поддерживаемые версии Docker.

    P.S.


    Читайте также в нашем блоге:

    • +36
    • 10,4k
    • 8
    Флант
    771,18
    Специалисты по DevOps и Kubernetes
    Поделиться публикацией

    Комментарии 8

      0
      А какой политики обновления кластеров k8s вы придерживаетесь сами? Как скоро обновляетесь на более новую версию?
        +2

        В настоящий момент мы ставим на новые кластера 1.11 и обновляем все существующие тоже до 1.11. На глаз: примерно половина на 1.11 и вторая половина на 1.10 и 1.9. С одной стороны – все норм и все работает, поэтому не форсируем, с другой стороны – есть очень большая пачка расширенных фич, которые мы не можем использовать и это нас очень расстраивает (например, ipvs и kubelet dynamic config мы до сих пор не можем использовать, ну и куча еще всего).


        Однако, мы решили форсировать этот вопрос и прямо сейчас готовим обновление 1.11 -> 1.13 (за одну операцию через две версии, там есть нюансы, но в целом так можно), должны закончить на этой неделе. И на следующей будем делать обновление 1.13 -> 1.15. Под "делать обновление" в нашем случае подразумевается проработка на тестовых стендах и подготовка инструкций для наших DevOps-команд. Сейчас мы поддерживаем три способа инсталляции: kubeadm (bare metal и все виды простых VM), kops (AWS, GCE) и aks (Azure).


        В целом, буквально через несколько недель, планируем выйти на следующую политику:


        1. Не позднее чем через месяц после релиза мы должны:
          • ставить новые кластера уже на эту версию,
          • иметь возможность обновить любой из существующих кластеров на эту версию.
        2. Мы поддерживаем кластера не более чем трех последних версий (с выходом 1.15 это будут 1.12, 1.13 и 1.14) и если кластер старше – мы форсируем обновление (даже если фичи не нужны – все равно требуется обновление).

        Плюс, скорей всего придем к тому, что для нечетных версий будем готовить обновление через одну версию, чтобы там, где не нужны фичи можно было обновляться в два раза реже.

          +1
          Спасибо, вообще было бы интересно увидеть отдельную статью про обновления кластеров. Как делали, какие подводные камни и тд. Например, как быть с кластером etcd при переходе на 1.14 с 1.13.
            0
            Побуду занудой, но частично первый пункт невыполним, как минимум на aks, там версия запаздывает обычно на 2 мажорных. Если конечно вы не используется aks-engine, который позволяет начать использовать новые версии раньше.
              0

              aks-engine

          0
          А вот [минувшей ночью] и официальный анонс подоспел. Не так, чтобы «фича», но всё же: из него мы дополнительно узнаём, что у kubeadm появился свой логотип! :-)

            0

            ExecutionHookController, я так понимаю он похож по функционалу на ваш AddonOperator?

          Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

          Самое читаемое