Если вы недавно познакомились с Docker, возможно, вы уже слышали о Kubernetes. Если вы не до конца понимаете связь, различия или схожесть этих технологий, эта статья для вас.

Мы расскажем, зачем нужен Kubernetes, если вы уже пользуетесь Docker-контейнерами. Так что же такого можно сделать в Kubernetes, чего нельзя достичь средствами Docker?

Что такое Kubernetes и сравнение его с Docker

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

Kubernetes и Docker нельзя сравнивать напрямую. Docker — инструмент для создания и запуска контейнеров, а Kubernetes — оркестратор, инструмент для управления контейнерами. Kubernetes позволяет построить кластер (Cluster) — распределенную отказоустойчивую систему, в то время как Docker работает на отдельном узле.

Еще есть Docker Swarm — это встроенный в докер инструмент оркестровки контейнеров. Его как как раз и можно полноценно сравнивать с Kubernetes, мы написали об этом отдельную статью.

Важно понимать, что в этой статье мы говорим о простых Docker-контейнерах, без применения оркестратора Docker Swarm.

Главное преимущество Kubernetes — автоматизация

Основное преимущество Kubernetes перед простыми Docker-контейнерами можно описать одним словом — автоматизация. Но под этой автоматизацией понимается много различных возможностей, о которых мы расскажем далее и приведем несколько конкретных примеров.

Нужно отметить, что все эти автоматизации можно сделать и без Kubernetes, но для этого придется использовать много отдельных инструментов, настраивать их и писать скрипты. Например, для автоматизации выкатки обновлений приложений можно использовать Ansible — систему управления конфигурациями. Такая система может обновить все инстансы приложения и убедиться, что оно работает. Но для этого она должна знать, какие хосты сейчас работают, как к ним обратиться, на каких именно хостах работают инстансы нужного приложения. Для этого придется писать скрипты, которые будут за этим следить.

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

В Kubernetes все эти автоматизации уже включены, они разрабатываются и поддерживаются большим сообществом разработчиков. Когда выходит новая версия Kubernetes, разработчики тестируют и проверяют все сами, а значит, все внутренние интеграции и автоматизации точно будут работать.

Единое управление всеми узлами

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

Docker работает в рамках отдельных узлов. Если у вас несколько узлов, то на каждом из них запущен докер-демон, который ничего не знает о существовании других узлов. Каждый демон знает лишь о том, что происходит на его узле. И поэтому обычными докер-контейнерами сложно управлять централизованно.

У Kubernetes есть центральная точка управления — API-сервер. В кластере может быть много узлов, контейнеров и настроек, но всеми ими можно управлять через единый сервер. В кластер можно отправить команду (например, чтобы обновить наше приложение), и Kubernetes сам найдет, на каких узлах оно находится, и обновит его.

Kubernetes как сервис с сертификацией CNCF
Беспроблемная доставка ваших приложений
Перейти

Управление конфигурациями и конфиденциальными данными

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

Docker. Так как докер-демон работает отдельно на каждом узле, все манипуляции по доставке и синхронизации этих файлов между узлами нужно проводить вручную. К тому же у Docker-контейнеров нет возможности хранения конфиденциальных данных в зашифрованном виде. Докер может использовать только переменные окружения.

В Kubernetes есть средство для центрального управления конфигурациями — ConfigsMaps для настроек и Secrets для конфиденциальных данных. Если разместить в них свои настройки, то приложения смогут получить к ним доступ из любого узла.

Автомасштабирование узлов

Технология контейнеризации позволяет легко масштабировать приложение. Если нагрузка на приложение растет, можно запустить дополнительные экземпляры, чтобы приложение не зависало. Но отслеживать изменение нагрузки вручную неправильно, гораздо удобнее это автоматизировать. Здесь под масштабированием мы имеем в виду как увеличение количества контейнеров, так и подключение дополнительных узлов, если ресурсов существующих узлов становится недостаточно.

Docker. Контейнеры не могут автомасштабироваться. Так как каждый докер-демон работает только в рамках своего узла, он не знает, что происходит на остальных. Докер-демон не может следить за нагрузкой, создавать дополнительные контейнеры или подключать новые узлы.

Kubernetes умеет автомасшабироваться. «Из коробки» он умеет масштабировать количество контейнеров, и дополнительно можно настроить подключение новых узлов. Когда нагрузка на приложение возрастет, Kubernetes добавит новые инстансы приложения, а при необходимости и подключит новые узлы. Когда нагрузка спадет, Kubernetes завершит лишние контейнеры и освободит узлы.

Обновления приложений и откаты

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

Другая задача — откат обновлений. Иногда для быстрого устранения ошибки нужно откатить обновление, чтобы потом спокойно разбираться и устранять ошибку. По сути, эта процедура аналогична обновлению, просто в обратном направлении.

В Docker нужно обновлять отдельно каждый контейнер. У контейнеров нет средства, чтобы одной или несколькими командами обновить все инстансы. Нужно найти все узлы, на которых работает приложение, и обновлять их по очереди.

Kubernetes. Чтобы выкатить новую версию приложения в Kubernetes, достаточно в Deployment-файле указать новую версию в имени образа. При этом если нужно выполнить обновление по типу Rolling-Update, это тоже достаточно указать в Deployment-файле. Если после обновления нужно откатиться, достаточно выполнить команду rollout, и Kubernetes сам откатит все контейнеры.

Система хранения данных

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

У Docker есть тома (Volumes), которые нужны для упрощения работы с постоянными данными. Но в любом случае тома нужно дополнительно настраивать, причем делать это придется для каждого контейнера отдельно. Например, у нас есть сетевое хранилище Ceph. Чтобы подключить его к контейнеру, сначала нужно создать том, подключить его ко всем узлам с контейнерами и потом смонтировать этот том в каждый отдельный контейнер.

Kubernetes намного упрощает работу с дисками. Полностью «из коробки» подключить диски не получится, тут все равно потребуется некоторая настройка и дополнительные инструменты. Но сделать это гораздо проще за счет объектов PersistentVolume и PersistentVolumeClaim. Сначала нужно создать том и настроить его один раз, а потом каждый контейнер может самостоятельно запрашивать ресурсы, без необходимости дополнительных манипуляций. Подробнее об этом механизме читайте в нашей статье про основы Kubernetes.

Распределение нагрузки и маршрутизация трафика из внешней сети

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

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

Docker. В простых докер-контейнерах нет возможности распределять нагрузку между инстансами приложения. Например, приложение хочет обратиться к сервису. Чтобы это сделать, оно должно знать IP-адрес этого сервиса. А если у сервиса несколько инстансов, то приложение должно знать все адреса и само решать, в какой именно инстанс обратиться. Если один из контейнеров сервиса перезапустится и получит новый адрес, приложение должно как-то об этом узнать. Это неудобный и неправильный подход к разработке.

Проблема усугубляется, если к сервису нужно обращаться из внешней сети. Для этого придется поддерживать в актуальном состоянии и еще и таблицу маршрутизации для внешнего трафика.

Kubernetes берет распределение трафика на себя. Если рассматривать пример выше, то Kubernetes позволяет над всеми инстансами сервиса создать единый объект типа Service. Этот объект сам следит за всеми инстансами, и, если контейнер перезапускается, он сам обновит информацию о его новом адресе. И чтобы приложение могло обратиться к сервису, достаточно знать одно доменное имя, которое будет всегда постоянным.

Также Kubernetes умеет перенаправлять внешний трафик в контейнеры. Для этого нужно установить и настроить Ingress Controller, но это гораздо проще, чем самостоятельно настраивать и поддерживать маршрутизацию. Kubernetes позволяет сделать так, чтобы к приложениям можно было обращаться по доменным именам или URL-путям. Ingress Controller сам будет перенаправлять трафик на нужный инстанс контейнера.

Чем еще хорош Kubernetes

Кроме автоматизации, есть еще несколько особенностей, которые выделяют Kubernetes перед обычными докер-контейнерами.

  • Kubernetes — это готовая платформа. С помощью Kubernetes можно построить платформу промышленного уровня. В нем есть механизмы авторизации, возможность разделять работу нескольких команд и проектов, отдельные пространства имен и многое другое. С простыми докер-контейнерами сложно построить такую систему самостоятельно.
  • Kubernetes — это проект-конструктор. Для Kubernetes существует много сторонних расширений и интеграций с другими инструментами: мониторинг, безопасность, инструменты разработки и многое другое. Это позволяет настроить его под себя так, как нужно именно для ваших нужд.

Когда использовать Kubernetes, а когда достаточно Docker-контейнеров?

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

Прежде чем начать работать с Kubernetes, его нужно изучить. Потому что это больше, чем просто Docker и контейнеры. Необходимо развернуть кластер, настроить его и поддерживать. Эти задачи можно упростить, если использовать облачные решения, например Kubenetes as a Service от Mail.ru Cloud Solutions. Мы возьмем на себя установку, первоначальную настройку, обновление и поддержку кластера. А вы будете пользоваться им как готовым решением, без необходимости администрирования.