Введение в Kubernetes
Kubernetes – это мощная система с открытым исходным кодом, изначально разработанная Google для управления контейнерными приложениями в кластерной среде. Она предоставляет эффективные способы управления связанными распределенными компонентами и услугами в разнообразной инфраструктуре.
В этом руководстве мы обсудим некоторые основные концепции Kubernetes. Мы поговорим об архитектуре системы, проблемах, которые она решает, и модели, которую она использует для обработки контейнерных развертываний и масштабирования.
Что такое Kubernetes?
Kubernetes на своем базовом уровне – это система для запуска и координации контейнерных приложений в кластере машин. Это платформа, предназначенная для полного управления жизненным циклом контейнерных приложений и служб с использованием методов, обеспечивающих предсказуемость, масштабируемость и высокую доступность.
Как пользователь Kubernetes вы можете определить, как ваши приложения должны работать и как они должны иметь возможность взаимодействовать с другими приложениями или внешним миром. Вы можете масштабировать свои сервисы вверх или вниз, выполнять плавные скользящие обновления и переключать трафик между различными версиями ваших приложений для тестирования функций или отката проблемных развертываний. Kubernetes предоставляет интерфейсы и составляемые примитивы платформы, которые позволяют определять приложения и управлять ими с высокой степенью гибкости, мощности и надежности.
Архитектура Kubernetes
Чтобы понять, как Kubernetes может предоставить эти возможности, полезно понять, как он спроектирован и организован на высоком уровне. Kubernetes можно визуализировать как систему, построенную по уровням, причем каждый более высокий уровень абстрагируется от сложности, обнаруженной на более низких уровнях.
В своей основе Kubernetes объединяет отдельные физические или виртуальные машины в кластер, используя общую сеть для связи между каждым сервером. Этот кластер представляет собой физическую платформу, на которой настроены все компоненты, возможности и рабочие нагрузки Kubernetes.
Каждой машине в кластере отводится роль в экосистеме Kubernetes. Один сервер (или небольшая группа в высокодоступных развертываниях) функционирует как главный сервер. Этот сервер действует как шлюз и мозг для кластера, предоставляя API для пользователей и клиентов, проверяя работоспособность других серверов, решая, как лучше всего разделить и назначать работу (известное как «планирование»), а также организуя связь между другими компонентами. Главный сервер действует как основная точка контакта с кластером и отвечает за большую часть централизованной логики, которую предоставляет Kubernetes.
Другие машины в кластере обозначаются как узлы: серверы, отвечающие за прием и выполнение рабочих нагрузок с использованием локальных и внешних ресурсов. Чтобы помочь с изоляцией, управлением и гибкостью, Kubernetes запускает приложения и службы в контейнерах , поэтому каждый узел должен быть оснащен средой выполнения контейнера (например, Docker или rkt). Узел получает рабочие инструкции от главного сервера и соответственно создает или уничтожает контейнеры, настраивая сетевые правила для маршрутизации и пересылки трафика соответствующим образом.
Как упоминалось выше, сами приложения и службы запускаются в кластере внутри контейнеров. Базовые компоненты обеспечивают соответствие желаемого состояния приложений фактическому состоянию кластера. Пользователи взаимодействуют с кластером, взаимодействуя с главным сервером API напрямую или с клиентами и библиотеками. Чтобы запустить приложение или службу, отправляется декларативный план в формате JSON или YAML, в котором определяется, что создавать и как им управлять. Затем главный сервер берет план и выясняет, как запустить его в инфраструктуре, исследуя требования и текущее состояние системы. Эта группа определяемых пользователем приложений, работающих в соответствии с указанным планом, представляет собой последний уровень Kubernetes.
Компоненты главного сервера
Как мы описали выше, главный сервер действует как основная плоскость управления для кластеров Kubernetes. Он служит основной точкой контакта для администраторов и пользователей, а также предоставляет множество общекластерных систем для относительно простых рабочих узлов. В целом компоненты на главном сервере работают вместе, чтобы принимать запросы пользователей, определять наилучшие способы планирования контейнеров рабочих нагрузок, аутентифицировать клиентов и узлы, настраивать сеть в масштабе кластера и управлять функциями масштабирования и проверки работоспособности.
Эти компоненты могут быть установлены на одном компьютере или распределены по нескольким серверам. В этом разделе мы рассмотрим каждый из отдельных компонентов, связанных с главными серверами.
Etcd
Один из основных компонентов, необходимых Kubernetes для работы, – это глобально доступное хранилище конфигурации. Etcd-проект , разработанный командой в CoreOS, распределенное хранилище “ключ-значение”, которое может быть сконфигурировано для пролета по нескольким узлам.
Kubernetes использует etcd для хранения данных конфигурации, к которым может получить доступ каждый из узлов кластера. Это можно использовать для обнаружения служб и может помочь компонентам настроить или перенастроить себя в соответствии с актуальной информацией. Он также помогает поддерживать состояние кластера с помощью таких функций, как выбор лидера и распределенная блокировка. Предоставляя простой HTTP / JSON API, интерфейс для установки или получения значений становится очень простым.
Как и большинство других компонентов в плоскости управления, etcd можно настроить на одном главном сервере или, в производственных сценариях, распределить между несколькими машинами. Единственное требование – чтобы он был доступен по сети для каждой машины Kubernetes.
Kube-аписервер
Одна из самых важных мастер-служб – это сервер API. Это основная точка управления всем кластером, поскольку она позволяет пользователю настраивать рабочие нагрузки Kubernetes и организационные подразделения. Он также отвечает за etcdсогласование сведений о магазине и сервисе развернутых контейнеров. Он действует как мост между различными компонентами для поддержания работоспособности кластера и распространения информации и команд.
Сервер API реализует интерфейс RESTful, что означает, что с ним могут легко взаимодействовать многие различные инструменты и библиотеки. Клиент под названием kubectl доступен как метод по умолчанию для взаимодействия с кластером Kubernetes с локального компьютера.
Kube-контроллер-менеджер
Диспетчер контроллера – это служба общего назначения, на которую возложено множество обязанностей. В первую очередь, он управляет различными контроллерами, которые регулируют состояние кластера, управляют жизненными циклами рабочих нагрузок и выполняют рутинные задачи. Например, контроллер репликации гарантирует, что количество реплик (идентичных копий), определенных для модуля, соответствует количеству, развернутому в данный момент в кластере. Подробности этих операций записываются etcd, где диспетчер контроллеров отслеживает изменения через сервер API.
Когда замечается изменение, контроллер считывает новую информацию и реализует процедуру, которая выполняет желаемое состояние. Это может включать в себя масштабирование приложения вверх или вниз, настройку конечных точек и т. д.
Kube-scheduler
Процесс, который фактически назначает рабочие нагрузки определенным узлам в кластере, – это планировщик. Эта служба считывает операционные требования рабочей нагрузки, анализирует текущую среду инфраструктуры и размещает работу на приемлемом узле или узлах.
Планировщик отвечает за отслеживание доступной мощности на каждом хосте, чтобы гарантировать, что рабочие нагрузки не будут запланированы сверх доступных ресурсов. Планировщик должен знать общую емкость, а также ресурсы, уже выделенные для существующих рабочих нагрузок на каждом сервере.
Облачный контроллер-менеджер
Kubernetes может быть развернут во многих различных средах и может взаимодействовать с различными поставщиками инфраструктуры, чтобы понимать и управлять состоянием ресурсов в кластере. Хотя Kubernetes работает с общими представлениями ресурсов, такими как подключаемое хранилище и балансировщики нагрузки, ему нужен способ сопоставить их с фактическими ресурсами, предоставляемыми неоднородными облачными провайдерами.
Менеджеры облачных контроллеров действуют как связующее звено, которое позволяет Kubernetes взаимодействовать с поставщиками с различными возможностями, функциями и API, сохраняя при этом относительно общие конструкции внутри. Это позволяет Kubernetes обновлять информацию о своем состоянии в соответствии с информацией, полученной от поставщика облачных услуг, настраивать облачные ресурсы по мере необходимости в системе, а также создавать и использовать дополнительные облачные службы для удовлетворения рабочих требований, представленных кластеру.
Компоненты сервера узла
В Kubernetes серверы, выполняющие работу за счет запуска контейнеров, называются узлами. У узловых серверов есть несколько требований, которые необходимы для связи с главными компонентами, настройки сети контейнера и выполнения назначенных им фактических рабочих нагрузок.
Среда выполнения контейнера
Первый компонент, который должен иметь каждый узел, – это среда выполнения контейнера. Обычно это требование удовлетворяется путем установки и запуска Docker, но также доступны альтернативы, такие как rkt и runc .
Среда выполнения контейнера отвечает за запуск и управление контейнерами, приложениями, инкапсулированными в относительно изолированную, но легкую операционную среду. Каждая единица работы в кластере на своем базовом уровне реализована как один или несколько контейнеров, которые необходимо развернуть. Среда выполнения контейнера на каждом узле – это компонент, который в конечном итоге запускает контейнеры, определенные в рабочих нагрузках, отправленных в кластер.
Кубелет
Основной точкой контакта для каждого узла с кластерной группой является небольшая служба под названием kubelet. Эта служба отвечает за ретрансляцию информации в службы уровня управления и из них, а также за взаимодействие с etcd-хранилищем для чтения деталей конфигурации или записи новых значений.
В kubeletсервисе обменивается данные с мастером – компонентами для аутентификации в кластер и прием команд и работу. Работа поступает в виде манифеста, который определяет рабочую нагрузку и рабочие параметры. Затем kubelet-процесс берет на себя ответственность за поддержание состояния работы на сервере узла. Он управляет средой выполнения контейнера, чтобы запускать или уничтожать контейнеры по мере необходимости.
Kube-proxy
Для управления подсетями отдельных хостов и предоставления услуг другим компонентам на каждом сервере узла запускается небольшая прокси-служба, называемая kube-proxy. Этот процесс перенаправляет запросы в правильные контейнеры, может выполнять примитивную балансировку нагрузки и, как правило, отвечает за обеспечение предсказуемости и доступности сетевой среды, но при необходимости изолированной.
Объекты и рабочие нагрузки Kubernetes
В то время как контейнеры являются основным механизмом, используемым для развертывания приложений, Kubernetes использует дополнительные уровни абстракции над интерфейсом контейнера для обеспечения функций масштабирования, отказоустойчивости и управления жизненным циклом. Вместо непосредственного управления контейнерами пользователи определяют экземпляры, состоящие из различных примитивов, предоставляемых объектной моделью Kubernetes, и взаимодействуют с ними. Ниже мы рассмотрим различные типы объектов, которые можно использовать для определения этих рабочих нагрузок.
Pods
Pod является самым основным блоком , которым Kubernetes занимается. Сами контейнеры хостам не назначаются. Вместо этого один или несколько тесно связанных контейнеров инкапсулируются в объект, называемый контейнером.
Pod обычно представляет собой один или несколько контейнеров, которыми следует управлять как одним приложением. Поды состоят из контейнеров, которые работают вместе, имеют общий жизненный цикл и всегда должны планироваться на одном узле. Они полностью управляются как единое целое и совместно используют свою среду, тома и IP-пространство. Несмотря на их контейнерную реализацию, вы должны обычно думать о модулях как о едином монолитном приложении, чтобы лучше понять, как кластер будет управлять ресурсами и расписанием модуля.
Обычно поды состоят из основного контейнера, который удовлетворяет общему назначению рабочей нагрузки, и, при необходимости, некоторых вспомогательных контейнеров, которые облегчают выполнение тесно связанных задач. Это программы, которые выигрывают от запуска и управления в своих собственных контейнерах, но тесно привязаны к основному приложению. Например, в модуле может быть один контейнер, в котором запущен основной сервер приложений, и вспомогательный контейнер, загружающий файлы в общую файловую систему при обнаружении изменений во внешнем репозитории. Горизонтальное масштабирование обычно не рекомендуется на уровне модуля, потому что есть другие объекты более высокого уровня, более подходящие для этой задачи.
Как правило, пользователи не должны сами управлять модулями, поскольку они не предоставляют некоторых функций, которые обычно требуются в приложениях (например, сложного управления жизненным циклом и масштабирования). Вместо этого пользователям предлагается работать с объектами более высокого уровня, которые используют модули или шаблоны модулей в качестве базовых компонентов, но реализуют дополнительные функции.
Контроллеры репликации и наборы репликации
Часто при работе с Kubernetes вместо работы с отдельными модулями вы будете управлять группами идентичных реплицированных модулей. Они создаются из шаблонов модулей и могут масштабироваться по горизонтали с помощью контроллеров, известных как контроллеры репликации и наборы репликации.
Контроллер репликации представляет собой объект, который определяет шаблон и контроль параметров POD в масштабе идентичных реплик стручка по горизонтали путем увеличения или уменьшения количества работающих копий. Это простой способ распределить нагрузку и повысить доступность непосредственно в Kubernetes. Контроллер репликации знает, как создавать новые модули по мере необходимости, потому что шаблон, который очень похож на определение модуля, встроен в конфигурацию контроллера репликации.
Контроллер репликации отвечает за то, чтобы количество модулей, развернутых в кластере, соответствовало количеству модулей в его конфигурации. Если модуль или базовый хост выходит из строя, контроллер запускает новые модули для компенсации. Если количество реплик в конфигурации контроллера изменяется, контроллер либо запускает, либо уничтожает контейнеры, чтобы соответствовать желаемому количеству. Контроллеры репликации также могут выполнять чередующиеся обновления, чтобы один за другим переносить набор модулей на новую версию, минимизируя влияние на доступность приложений.
Наборы репликации – это итерация конструкции контроллера репликации с большей гибкостью в том, как контроллер идентифицирует поды, которыми он должен управлять. Наборы репликации начинают заменять контроллеры репликации из-за их более широких возможностей выбора реплик, но они не могут выполнять скользящие обновления для циклического перехода к новой версии, как это могут делать контроллеры репликации. Вместо этого наборы репликации предназначены для использования внутри дополнительных модулей более высокого уровня, которые обеспечивают эту функциональность.
Как и поды, контроллеры репликации и наборы репликации редко являются модулями, с которыми вы будете работать напрямую. Хотя они основаны на конструкции модуля, чтобы добавить гарантии горизонтального масштабирования и надежности, им не хватает некоторых тонких возможностей управления жизненным циклом, присущих более сложным объектам.
Развертывания
Развертывания – одна из наиболее распространенных рабочих нагрузок, которые нужно создавать напрямую и управлять ими. Развертывания используют наборы репликации в качестве строительного блока, добавляя гибкие функциональные возможности управления жизненным циклом.
Хотя развертывания, построенные с использованием наборов репликации, могут дублировать функциональные возможности, предлагаемые контроллерами репликации, развертывания решают многие проблемы, которые существовали при реализации скользящих обновлений. При обновлении приложений с помощью контроллеров репликации пользователи должны предоставить план для нового контроллера репликации, который заменит текущий контроллер. При использовании контроллеров репликации такие задачи, как отслеживание истории, восстановление после сбоев сети во время обновления и откат плохих изменений, либо затруднены, либо оставлены на ответственности пользователя.
Развертывания – это объект высокого уровня, предназначенный для упрощения управления жизненным циклом реплицированных модулей. Развертывания можно легко изменить, изменив конфигурацию, и Kubernetes будет настраивать наборы реплик, управлять переходами между различными версиями приложений и, при необходимости, автоматически вести журнал событий и возможности отмены. Из-за этих функций развертывания, скорее всего, будут тем типом объекта Kubernetes, с которым вы работаете чаще всего.
Наборы с сохранением состояния
Наборы с отслеживанием состояния – это специализированные контроллеры модулей, которые предлагают гарантии упорядоченности и уникальности. В первую очередь, они используются для более детального управления, когда у вас есть особые требования, связанные с порядком развертывания, постоянными данными или стабильной сетью. Например, наборы с отслеживанием состояния часто связаны с приложениями, ориентированными на данные, такими как базы данных, которым требуется доступ к тем же томам, даже если они перенесены на новый узел.
Наборы с отслеживанием состояния обеспечивают стабильный сетевой идентификатор, создавая уникальное числовое имя для каждого модуля, которое будет сохраняться, даже если модуль необходимо переместить на другой узел. Точно так же постоянные тома хранилища могут быть перенесены с помощью модуля, когда необходимо перепланировать. Тома сохраняются даже после удаления модуля, чтобы предотвратить случайную потерю данных.
При развертывании или настройке масштабирования наборы с отслеживанием состояния выполняют операции в соответствии с пронумерованным идентификатором в их имени. Это дает большую предсказуемость и контроль над порядком выполнения, что может быть полезно в некоторых случаях.
Наборы демонов
Наборы демонов – это еще одна специализированная форма контроллера модуля, которая запускает копию модуля на каждом узле кластера (или подмножестве, если указано). Это чаще всего полезно при развертывании модулей, которые помогают выполнять обслуживание и предоставляют услуги для самих узлов.
Например, сбор и пересылка журналов, агрегирование показателей и запуск служб, которые увеличивают возможности самого узла, являются популярными кандидатами на роль наборов демонов. Поскольку наборы демонов часто предоставляют основные услуги и необходимы для всего парка, они могут обойти ограничения планирования модулей, которые не позволяют другим контроллерам назначать модули определенным хостам. Например, из-за своих уникальных обязанностей главный сервер часто настраивается так, чтобы быть недоступным для обычного планирования модулей, но наборы демонов имеют возможность отменять ограничение для каждого модуля, чтобы убедиться, что основные службы работают.
Все рабочие нагрузки, которые мы описали до сих пор, предполагали длительный жизненный цикл, подобный сервисному. Kubernetes использует рабочую нагрузку, называемую заданиями, для обеспечения рабочего процесса, в большей степени основанного на задачах, при котором запущенные контейнеры должны успешно завершиться через некоторое время после завершения своей работы. Задания полезны, если вам нужно выполнять разовую или пакетную обработку вместо непрерывного обслуживания.
Использование рабочих мест – это работа cron. Как и обычные cron-демоны в Linux и Unix-подобных системах, которые выполняют сценарии по расписанию, задания cron в Kubernetes предоставляют интерфейс для выполнения заданий с компонентом планирования. Задания Cron можно использовать для планирования задания, которое будет выполняться в будущем или на регулярной, повторяющейся основе. Задания cron в Kubernetes – это, по сути, повторная реализация классического поведения cron с использованием кластера в качестве платформы вместо единой операционной системы.
Другие компоненты Kubernetes
Помимо рабочих нагрузок, которые вы можете запускать в кластере, Kubernetes предоставляет ряд других абстракций, которые помогают вам управлять своими приложениями, управлять сетью и обеспечивать постоянство. Здесь мы обсудим несколько наиболее распространенных примеров.
Сервисы
До сих пор мы использовали термин «служба» в обычном, Unix-подобном смысле: для обозначения длительно выполняющихся процессов, часто подключенных к сети, способных отвечать на запросы. Однако в Kubernetes служба – это компонент, который действует как базовый внутренний балансировщик нагрузки и представитель подов. Сервис объединяет логические коллекции модулей, которые выполняют одну и ту же функцию, чтобы представить их как единый объект.
Это позволяет вам развернуть службу, которая может отслеживать и направлять все внутренние контейнеры определенного типа. Внутренним потребителям нужно знать только о стабильной конечной точке, предоставляемой службой. Между тем, абстракция сервисов позволяет масштабировать или заменять внутренние рабочие единицы по мере необходимости. IP-адрес службы остается стабильным независимо от изменений в модулях, на которые она направляется. Развертывая службу, вы легко получаете возможность обнаружения и можете упростить дизайн контейнера.
Каждый раз, когда вам нужно предоставить доступ к одному или нескольким модулям другому приложению или внешним потребителям, вы должны настроить службу. Например, если у вас есть набор модулей, на которых работают веб-серверы, которые должны быть доступны из Интернета, служба предоставит необходимую абстракцию. Точно так же, если вашим веб-серверам необходимо хранить и извлекать данные, вы можете настроить внутреннюю службу, чтобы предоставить им доступ к вашим модулям базы данных.
Хотя службы по умолчанию доступны только с использованием IP-адреса с внутренней маршрутизацией, их можно сделать доступными за пределами кластера, выбрав одну из нескольких стратегий. NodePort конфигурация работает, открыв статический порт на внешнем сетевом интерфейсе каждого узла. Трафик на внешний порт будет автоматически маршрутизироваться на соответствующие модули с использованием внутренней IP-службы кластера.
В качестве альтернативы тип службы LoadBalancer создает внешний балансировщик нагрузки для маршрутизации к службе с использованием интеграции балансировщика нагрузки Kubernetes от облачного поставщика. Диспетчер облачного контроллера создаст соответствующий ресурс и настроит его, используя адреса внутренней службы.
Volums
Надежный обмен данными и гарантия их доступности между перезапусками контейнеров является проблемой во многих контейнерных средах. Среда выполнения контейнера часто предоставляет некоторый механизм для присоединения хранилища к контейнеру, который сохраняется после окончания срока службы контейнера, но реализациям обычно не хватает гибкости.
Чтобы решить эту проблему, Kubernetes использует собственную абстракцию томов, которая позволяет использовать данные для всех контейнеров внутри модуля и оставаться доступными до тех пор, пока модуль не будет завершен. Это означает, что тесно связанные модули могут легко обмениваться файлами без сложных внешних механизмов. Сбои контейнера в модуле не повлияют на доступ к общим файлам. После завершения работы модуля общий том уничтожается, поэтому это не лучшее решение для действительно постоянных данных.
Постоянные тома – это механизм абстрагирования более надежного хранилища, не привязанного к жизненному циклу модуля. Вместо этого они позволяют администраторам настраивать ресурсы хранения для кластера, которые пользователи могут запрашивать и требовать для запущенных модулей. После создания модуля с постоянным томом политика восстановления тома определяет, будет ли том храниться до тех пор, пока он не будет удален вручную, или будет немедленно удален вместе с данными. Постоянные данные можно использовать для защиты от сбоев узлов и выделения большего объема хранилища, чем доступно локально.
Ярлыки и аннотации
Организационная абстракция Kubernetes, связанная с другими концепциями, но не относящаяся к ним, – это маркировка. Метка в Kubernetes является семантическим признаком , который может быть присоединен к Kubernetes объектов , чтобы отметить их как часть группы. Затем их можно выбрать при нацеливании на различные экземпляры для управления или маршрутизации. Например, каждый из объектов на основе контроллера использует метки для идентификации модулей, с которыми они должны работать. Сервисы используют метки, чтобы понимать, в какие серверные модули они должны направлять запросы.
Ярлыки представлены в виде простых пар “ключ-значение”. У каждого блока может быть более одной метки, но у каждого блока может быть только одна запись для каждой клавиши. Обычно ключ «name» используется в качестве идентификатора общего назначения, но вы можете дополнительно классифицировать объекты по другим критериям, таким как стадия разработки, общедоступность, версия приложения и т. д.
Аннотации – это аналогичный механизм, который позволяет вам прикреплять к объекту произвольную информацию о параметрах “ключ-значение”. Хотя метки следует использовать для семантической информации, полезной для сопоставления модуля с критериями выбора, аннотации имеют более произвольную форму и могут содержать менее структурированные данные. Как правило, аннотации – это способ добавления метаданных к объекту, который не помогает при выборе.
Вывод
Kubernetes – это захватывающий проект, который позволяет пользователям запускать масштабируемые, высокодоступные контейнерные рабочие нагрузки на высоко абстрагированной платформе. Хотя архитектура и набор внутренних компонентов Kubernetes на первый взгляд могут показаться устрашающими, их мощность, гибкость и надежный набор функций не имеют себе равных в мире открытого исходного кода. Понимая, как сочетаются друг с другом основные строительные блоки, вы можете приступить к проектированию систем, которые полностью используют возможности платформы для запуска и управления вашими рабочими нагрузками в любом масштабе.