Контейнер – на конвейер: CRI-O теперь по умолчанию в OpenShift Container Platform 4

Платформа Red Hat OpenShift Container Platform 4 позволяет поставить на поток создание хостов для развертывания контейнеров, в том числе в инфраструктуре поставщиков облачных сервисов, на платформах виртуализации или в bare-metal системах. Чтобы создать в полном смысле облачную платформу, нам пришлось взять под жесткий контроль все применяемые элементы и таким образом повысить надежность сложного процесса автоматизации.

Контейнер – на конвейер: CRI-O теперь по умолчанию в OpenShift Container Platform 4

Очевидным решением стало использование в качестве стандарта Red Hat Enterprise Linux CoreOS (разновидности Red Hat Enterprise Linux) и CRI-O, и вот почему…

Поскольку тема мореплавания является весьма удачной для поиска аналогий при объяснении работы Kubernetes и контейнеров, попробуем рассказать о тех бизнес-проблемах, которые решают CoreOS и CRI-O, на примере изобретения Брюнеля для производства такелажных блоков. В 1803 году перед Марком Брюнелем была поставлена задача изготовить 100 тысяч такелажных блоков для нужд растущего морского флота Великобритании. Такелажный блок – тип оснастки, которая используется для крепления канатов к парусам. Вплоть до самого начала 19-го столетия эти блоки изготавливались вручную, но Брюнелю удалось автоматизировать производство и начать изготавливать стандартизированные блоки с помощью станков. Автоматизация этого процесса означала, что в результате все блоки получались практически одинаковыми, могли быть с легкостью заменены в случае поломки и могли изготавливаться в больших количествах.

А теперь представьте, что Брюнелю пришлось бы проделать эту работу для 20 различных моделей судов (версий Kubernetes) и для пяти различных планет с совершенно разными морскими течениями и ветрами (облачные провайдеры). К тому же требовалось, чтобы все корабли (кластеры OpenShift), независимо от планет, по которым осуществляется навигация, с точки зрения капитанов (операторов, управляющих работой кластеров) вели себя одинаково. Продолжая морскую аналогию, капитанам кораблей абсолютно не важно, какие такелажные блоки (CRI-O) используются на их кораблях – для них главное, чтобы эти блоки были прочными и надежными.

Перед OpenShift 4, как облачной платформой, стоит очень похожая бизнес-задача. Новые ноды должны создаваться в момент создания кластера, в случае сбоя в одном из узлов, или при масштабировании кластера. При создании и инициализации нового узла должны быть соответственно сконфигурированы и критические компоненты хоста, в том числе CRI-O. Как и в любом другом производстве в начале необходимо подать «сырье». В случае кораблей в качестве сырья выступают металл и древесина. Однако в случае создания хоста для развертывания контейнеров в кластере OpenShift 4, на входе нужно иметь файлы конфигурации и предоставляемые API серверы. После чего OpenShift будет обеспечивать нужный уровень автоматизации в течение всего жизненного цикла, предлагая необходимую продуктовую поддержку для конечных пользователей и окупая таким образом инвестиции в платформу.

OpenShift 4 создавалась таким образом, чтобы обеспечить возможность удобного обновления системы на протяжении всего жизненного цикла платформы (для версий 4.X) для всех основных поставщиков облачных вычислений, платформ виртуализации и даже bare metal систем. Для этого узлы должны создаваться на базе взаимозаменяемых элементов. Когда кластер требует новую версию Kubernetes, он также получает соответствующую версию CRI-O на CoreOS. Поскольку версия CRI-O привязана непосредственно к Kubernetes, все это в значительной степени упрощает любые перестановки с целью тестирования, устранения неполадок или поддержки. Кроме того, подобный подход позволяет снизить издержки для конечных пользователей и Red Hat.

Это принципиально новый взгляд на кластеры Kubernetes, который закладывает основу для планирования новых весьма полезных и привлекательных функций. CRI-O (проект открытого контейнера Container Runtime Interface — Open Container Initiative, сокращенно CRI-OCI) оказался наиболее удачным выбором для массового создания узлов, которое необходимо для работы с OpenShift. CRI-O придет на смену использовавшемуся ранее движку Docker, предлагая пользователям OpenShift экономный, стабильный, простой и скучный – да, вы не ослышались – скучный контейнерный движок, созданный специально для работы с Kubernetes.

Мир открытых контейнеров

Мир уже давно движется к открытым контейнерам. Будь то в Kubernetes, или на более низких уровнях, развитие контейнерных стандартов приводит к появлению экосистемы инноваций на каждом уровне.

Все началось с создания инициативы Open Containers Initiative в июне 2015 года. На этом раннем этапе работы были сформированы спецификации контейнерного образа (image) и среды исполнения (runtime). Это позволило гарантировать, что инструменты могут использовать единый стандарт контейнерных образов и единый формат для работы с ними. Позднее были добавлены спецификации дистрибуции (distribution), что позволило пользователям с легкостью обмениваться контейнерными образами.

Затем сообщество Kubernetes разработало единый стандарт подключаемого интерфейса (pluggable interface), получившего название Container Runtime Interface (CRI). Благодаря этому пользователи Kubernetes смогли подключать различные движки для работы с контейнерами в дополнение к Docker.

Инженеры Red Hat и Google увидели существовавшую на рынке потребность в контейнерном движке, который мог бы принимать запросы от Kubelet по протоколу CRI и представили контейнеры, которые были совместимы с упомянутыми выше спецификациями OCI. Так появился OCID. Но позвольте, ведь мы же сказали, что этот материал будет посвящен CRI-O? На самом деле так и есть, просто с выпуском версии 1.0 проект был переименован в CRI-O.

Рис. 1.

Контейнер – на конвейер: CRI-O теперь по умолчанию в OpenShift Container Platform 4

Инновации с CRI-O и CoreOS

С запуском платформы OpenShift 4, был изменен контейнерный движок, используемый в платформе по умолчанию, и на смену Docker пришел CRI-O, предложивший экономичную, стабильную, простую и скучную среду для запуска контейнера, которая развивается параллельно с Kubernetes. Это значительно упрощает поддержку и конфигурацию кластера. Конфигурирование контейнерного движка и хоста, а также управление ими становится автоматизированной в рамках OpenShift 4.

Стоп, как это?

Именно так, с появлением OpenShift 4, теперь больше нет нужды подключаться к отдельным хостам и устанавливать контейнерный движок, конфигурировать хранилище, настраивать сервера для поиска или конфигурировать сеть. Платформа OpenShift 4 была полностью переработана для использования the Operator Framework не только с точки зрения приложений конечных пользователей, но и с точки зрения базовых операций на уровне платформы, таких как развертывание образов, конфигурирование системы или установка обновлений.

Kubernetes всегда позволял пользователям управлять приложениями, определяя желаемое состояние и используя контроллеры (Controllers), чтобы гарантировать, что фактическое состояние максимально соответствует заданному состоянию. Этот подход с использованием заданного состояния и фактического состояния открывает большие возможности как с точки зрения разработки, так и с точки зрения операций. Разработчики могут определить требуемое состояние, передать его оператору в виде YAML или JSON файла, а затем оператор может создать в эксплуатационной среде необходимый экземпляр приложения, при этом рабочее состояние этого экземпляра будет полностью соответствовать заданному.

Используя операторы (Operators) в платформе, OpenShift 4 привносит эту новую парадигму (с использованием концепции заданного и фактического состояния) в управление RHEL CoreOS и CRI-O. Задачи конфигурирования и управления версиями операционной системы и контейнерного движка автоматизируется с помощью так называемого оператора конфигурации машины (Machine Config Operator, MCO). MCO значительно упрощает работу администратора кластера, по сути автоматизируя последние этапы установки, а также последующие операции после установки (day two operations). Все это делает OpenShift 4 настоящей облачной платформой. Мы остановимся на этом чуть позже.

Запуск контейнеров

У пользователей была возможность использовать движок CRI-O в платформе OpenShift начиная с версии 3.7 в статусе Tech Preview и с версии 3.9 в статусе Generally Available (поддерживается в настоящее время). Кроме того, Red Hat массово использует CRI-O для запуска производственных рабочих нагрузок в OpenShift Online начиная с версии 3.10. Все это позволило команде, работающей над CRI-O, получить огромный опыт массового запуска контейнеров на крупных кластерах Kubernetes. Чтобы получить базовые представления о том, как Kubernetes использует CRI-O, давайте рассмотрим следующую иллюстрацию, на которой показан принцип работы архитектуры.

Рис. 2. Как работают контейнеры в кластере Kubernetes

Контейнер – на конвейер: CRI-O теперь по умолчанию в OpenShift Container Platform 4

CRI-O упрощает создание новых контейнерных хостов за счет синхронизации всего верхнего уровня при инициализации новых нод, а при выпуске новых версий платформы OpenShift. Ревизия всей платформы целиком позволяет выполнять транзакционные обновления / откаты, а также предотвращает взаимные блокировки в зависимостях между ядром контейнерного хвоста, контейнерным движком, нодами (Kubelets) и мастер-нодой Kubernetes Master. При централизованном управлении всеми компонентами платформы, с контролем и управлением версиями, можно всегда отследить четкий путь из состояния A в состояние B. Это позволяет упростить процесс обновлений, повышает безопасность, улучшает ведение отчетности по производительности и помогает снизить затраты на обновления и установку новых версий.

Демонстрация мощи сменных элементов

Как было упомянуто ранее, использование Machine Config Operator для управления хостом контейнера и контейнерным движком в OpenShift 4 обеспечивает новый уровень автоматизации, который не был возможен на платформе Kubernetes ранее. Чтобы продемонстрировать новые возможности, мы покажем, как вы могли бы вносить изменения в файл crio.conf. Чтобы не запутаться в терминологии, старайтесь сконцентрироваться на результатах.

Сначала, давайте создадим то, что называется конфигурацией среды исполнения контейнера – Container Runtime Config. Считайте, что это некий ресурс Kubernetes, который представляет конфигурацию для CRI-O. В действительности же это специализированная версия того, что называется MachineConfig, что представляет собой любую конфигурацию, развертываемую на машине RHEL CoreOS в рамках кластера OpenShift.

Этот кастомный ресурс, называемый ContainerRuntimeConfig, был придуман для того, чтобы облегчить для администраторов кластера настройку CRI-O. Это достаточно мощный инструмент, что его можно применять только к определенным узлам в зависимости от настроек MachineConfigPool. Считайте это группой машин, которые служат одной и той же цели.

Обратите внимание на две последние строчки, которые мы собираемся изменить в файле /etc/crio/crio.conf. Эти две строчки очень похожи на строчки в файле crio.conf, это:

vi ContainerRuntimeConfig.yaml

Вывод:

apiVersion: machineconfiguration.openshift.io/v1
kind: ContainerRuntimeConfig
metadata:
 name: set-log-and-pid
spec:
 machineConfigPoolSelector:
   matchLabels:
     debug-crio: config-log-and-pid
 containerRuntimeConfig:
   pidsLimit: 2048
   logLevel: debug

Теперь отправим этот файл в кластер Kubernetes и проверим, что он действительно создан. Обратите внимание, что работа осуществляется точно так же, как и с любым другим ресурсом Kubernetes:

oc create -f ContainerRuntimeConfig.yaml
oc get ContainerRuntimeConfig

Вывод:

NAME              AGE
set-log-and-pid   22h

После того, как мы создали ContainerRuntimeConfig, нам необходимо изменить один из MachineConfigPools, чтобы дать понять Kubernetes, что мы хотим применить эту конфигурацию к определенной группе машин в кластере. В этом случае мы изменим MachineConfigPool для мастер-узлов:

oc edit MachineConfigPool/master

Вывод (для наглядности оставлена основная суть):

...
metadata:
 creationTimestamp: 2019-04-10T23:42:28Z
 generation: 1
 labels:
   debug-crio: config-log-and-pid
   operator.machineconfiguration.openshift.io/required-for-upgrade: ""
...

В этот момент MCO начинает создавать новый файл crio.conf для кластера. При этом полностью готовый файл конфигурации можно просмотреть средствами Kubernetes API. Помните, ContainerRuntimeConfig – это всего лишь специализированная версия MachineConfig, поэтому мы можем увидеть результат, взглянув на нужные строки в MachineConfigs:

oc get MachineConfigs | grep rendered

Вывод:

rendered-master-c923f24f01a0e38c77a05acfd631910b                  4.0.22-201904011459-dirty 2.2.0 16h
rendered-master-f722b027a98ac5b8e0b41d71e992f626                  4.0.22-201904011459-dirty 2.2.0 4m
rendered-worker-9777325797fe7e74c3f2dd11d359bc62                  4.0.22-201904011459-dirty 2.2.0 16h

Обратите внимание, что полученный файл конфигураций для мастер-узлов оказался более новой версией, чем исходные конфигурации. Чтобы просмотреть его, запустите следующую команду. Попутно отметим, что это, возможно, один из лучших однострочных скриптов за всю историю Kubernetes:

python3 -c "import sys, urllib.parse; print(urllib.parse.unquote(sys.argv[1]))" $(oc get MachineConfig/rendered-master-f722b027a98ac5b8e0b41d71e992f626 -o YAML | grep -B4 crio.conf | grep source | tail -n 1 | cut -d, -f2) | grep pid

Вывод:

pids_limit = 2048

Теперь убедимся, что конфигурация была применена ко всем мастер-узлам. Сначала получим список узлов в кластере:

oc get node | grep master

Output:

ip-10-0-135-153.us-east-2.compute.internal   Ready master 23h v1.12.4+509916ce1

ip-10-0-154-0.us-east-2.compute.internal     Ready master 23h v1.12.4+509916ce1

ip-10-0-166-79.us-east-2.compute.internal    Ready master 23h v1.12.4+509916ce1

Теперь просмотрим установленный файл. Вы увидите, что файл был обновлен по новым значениям директив pid и debug, которые мы указали в ресурсе ContainerRuntimeConfig. Сама элегантность:

oc debug node/ip-10-0-135-153.us-east-2.compute.internal — cat /host/etc/crio/crio.conf | egrep 'debug||pid’

Вывод:

...
pids_limit = 2048
...
log_level = "debug"
...

Все эти изменения в кластере были внесены даже без запуска SSH. Вся работа была выполнена путем обращения к мастер-узлу Kuberentes. То есть эти новые параметры были сконфигурированы только на мастер-узлах. Рабочие узлы при этом не менялись, что демонстрирует преимущества методологии Kubernetes с использованием заданных и актуальных состояний применительно к хостам контейнеров и контейнерных движков с взаимозаменяемыми элементами.

Приведенный выше пример показывает возможность вносить изменения в небольшой кластер OpenShift Container Platform 4 с тремя рабочими нодами или в огромный производственный кластер с 3000 нодов. В любом случае объем работ будет одинаковым – и совсем небольшим – достаточно настроить файл ContainerRuntimeConfig, и изменить одну метку (label) в MachineConfigPool. И вы можете проделать это с любой версией используемой в Kubernetes платформы OpenShift Container Platform 4.X в течение всего ее жизненного цикла.

Зачастую технологические компании развиваются настолько быстро, что мы не в состоянии объяснить, почему мы выбираем те или иные технологии для базовых компонентов. Контейнерные движки исторически были тем компонентом, с которым пользователи взаимодействуют напрямую. Поскольку популярность контейнеров закономерно начиналась с появления контейнерных движков, пользователи нередко проявляют к ним заинтересованность. Это еще одна причина, почему Red Hat остановила свой выбор на CRI-O. Контейнеры развиваются, при этом сегодня основное внимание уделяется оркестровке, и мы пришли к выводу, что CRI-O обеспечивает наилучший опыт при работе с OpenShift 4.

Источник: habr.com