Мы добавили возможность удобного запуска Kubernetes в сервисе Виртуальное приватное облако в режиме раннего beta-тестирования. Эта функциональность будет полезна пользователям, которым требуется удобное управление большим количеством приложений, запущенных в виде контейнеров. Kubernetes предлагает средства для масштабирования, самовосстановления, балансировки нагрузки для контейнеров, запущенных внутри кластера. Так как сервис Виртуальное приватное облако построен на базе OpenStack, мы используем один из его компонентов — OpenStack Magnum. Он позволяет быстро создавать приватные кластеры Kubernetes с нужным количеством нод. В настоящее время любой пользователь нашего сервиса может может создавать в своем проекте несколько независимых друг от друга кластеров. В качестве нод кластера будут использованы виртуальные машины, конфигурацию которых можно выбрать и изменить. В этой статье мы расскажем про основные объекты кластера Kubernetes и на примерах рассмотрим процесс создания кластера при помощи OpenStack Magnum. В настоящее время создание кластера Kubernetes возможно только через консольные утилиты или OpenStack API в зонах доступности ru-1a и ru-1b (Санкт-Петербург). Для начала работы вам понадобится: Для установки консольного клиента openstack можно воспользоваться инструкцией по ссылке, однако, стоит иметь ввиду, что для данного клиента также потребуется установить библиотеку python-magnumclient, для поддержки создания Kubernetes кластеров. Полный набор команд для установки openstack клиента с требуемым плагином для операционных систем семейства Ubuntu/Debian: Полный набор команд для установки openstack клиента с требуемым плагином для операционных систем семейства Fedora/CentOS: Для управления объектами Kubernetes вам потребуется консольный клиент kubectl. Способы установки для различных операционных систем описаны в официальной документации. Для создания кластера вам потребуется создать или использовать существующие: Вы можете создать cluster template и flavor самостоятельно, или использовать публичные заранее созданные шаблоны. Также вам потребуется определиться с зоной доступности, типом дисков для вашего кластера и количеством нод. Стоит учесть, что в мы еще не поддерживаем возможность создания одного кластера в нескольких зонах. Вы можете выбрать любой тип сетевого диска (быстрый, универсальный или базовый).
Подробнее о типах дисков можно узнать из нашей базы знаний. Количество нод может быть разное для master и для minion ролей. На нодах, выполняющих master роль, будут запущены управляющие элементы кластера — controller-manager, scheduler, api. На остальных нодах будут запущены сервисы kubelet, kube-proxy и все контейнеры приложений. Подробнее о компонентах, запускаемых на нодах кластера можно узнать из официальной документации. Для доступа на ноды по SSH вам потребуется использовать SSH-ключ, созданный ранее. В примерах команд будет использован ключ с именем ssh-test. Мы будем использовать публичные cluster template и flavor, быстрый тип диска, и зону доступности ru-1b.
В нашем кластере изначально будет запущено 2 master ноды и 3 minion ноды. Для проверки указанных параметров воспользуемся командами openstackclient и скачанным файлом доступа (rc.sh): Для примера мы выберем второй шаблон кластера, из него не будут созданы публично доступные плавающие адреса для каждой из нод. Нам они не потребуются. Обратите внимание, что мы выбрали одинаковую конфигурацию для разных нод (параметры master-flavor и flavor), вы можете выбирать разные наборы конфигурации в зависимости от требований кластера. Их изменение возможно и после его создания. Также стоит учесть, что при создании кластера с несколькими master нодами, автоматически будет создан балансировщик нагрузки для доступа к API Kubernetes. Через несколько минут в вашем проекте появится кластер Kubernetes. В панели управления проектом вы увидите новые виртуальные машины, диски и сетевые объекты. Вы можете проверить статус вашего кластера через openstackclient: После того как кластер перейдет в состояние CREATE_COMPLETE, вы сможете управлять его объектами через утилиту kubectl, скачав конфигурационный файл при помощи следующих команд: После этого можно работать с кластером при помощи утилиты kubectl: При необходимости вы можете увеличить или уменьшить количество minion нод в кластере через openstackclient, передав новое значение node_count: Несмотря на то, что Kubernetes руководит набором контейнеров, базовой сущностью, которой управляет Kubernetes, является не контейнер, а Pod. Pod представляет из себя набор пространства имен ядра Linux и настроек сетевого стека, которые позволяют собирать набор контейнеров в единую сущность.
Чаще всего, один контейнер с приложением запускается внутри одного отдельного Pod-а.
При необходимости, можно запускать и несколько контейнеров внутри одного Pod-а, это может быть полезно, когда вам необходимо предоставить доступ из одного контейнера в другой через сетевой интерфейс localhost, либо по каким-то другим причинам запускать несколько контейнеров на одном хосте.
Все контейнеры, запущенные в одном Pod-е будут иметь один хостнейм, IP-адрес, таблицу маршрутизации и диски. Стоит заметить, что при масштабировании количества экземпляров вашего приложения внутри Kubernetes, необходимо увеличивать именно количество Pod-ов, а не количество контейнеров в одном конкретном Pod-е.
Подробнее в официальной документации Pods. Для примера создадим максимально простой Pod с Nginx при помощи описания в формате yaml: Для создания Pod-а мы можем воспользоваться утилитой kubectl.
Мы добавили все примеры, изложенные в статье, в нашу группу Github, поэтому вы можете не создавать файлы у себя на компьютере, а использовать url-адрес файла из публичного репозитория : После создания мы можем запросить полную информацию о статусе Pod-а, используя команду kubectl describe: Как можно заметить, Pod запустился на ноде с именем test-cluster-nd5c5y6lsfxb-minion-0 и получил внутренний IP-адрес 10.100.88.9. Из раздела Events видно основные события запуска — выбор ноды для запуска и скачивание образа. Мы можем попасть в Pod и проверить состояние процессов внутри контейнера: Следует иметь ввиду, что IP-адрес 10.100.88.9 не будет доступен другим приложениям внутри и вне Kubernetes кластера, доступ к запущенному Nginx будет возможен только изнутри самого Pod-а: Вдобавок к тому, что указанный IP-адрес доступен только из контейнера, он также не является постоянным. Это значит, что если этот Pod будет пересоздан, то он может получить другой IP-адрес. Чтобы решить эти проблемы, можно использовать объект под названием Service. Service позволяет назначать постоянные IP-адреса для Pod-ов, предоставлять им доступ из внешних сетей и балансировать запросы между Pod-ами.
Подробнее про Service можно узнать в официальной документации. Для примера нам потребуется удалить запущенный Pod: Добавим в описание Pod-а метку (Label), которая потребуется для Service: Нам также потребуется описание Service: Создадим Pod и Service: Так как созданный Service имеет тип NodePort, то на всех нодах кластера будет открыт указанный нами порт 30001 на всех сетевых интерфейсах.
Это значит, что если мы добавим к любой ноде внешний IP-адрес, то мы сможем получить доступ к запущенному Pod-у с Nginx из внешней сети. Чтобы не использовать внешние адреса нод кластера для доступа к Service, мы можем использовать тип LoadBalancer вместо NodePort.
Нам понадобится новое описание сервиса: Удалим текущий сервис и применим новое описание: После запуска сервиса, Nginx станет доступен по TCP порту 80 из внешней сети, при этом не будет необходимости назначать и использовать внешние адреса для нод кластера. Service с типом LoadBalancer автоматически выделит новый внешний адрес в ваш проект VPC и начнет его использовать. Вы можете получить информацию о выделенном внешнем адресе при помощи kubectl: В наших примерах запускался только один Pod с Nginx. Чтобы масштабировать приложение на большее количество Pod-ов, мы можем использовать Deployment. Deployment представляет из себя сущность кластера Kubernetes, позволяющую масштабировать Pod-ы и производить удобное обновление или откат версий для большого количества Pod-ов.
Вместо Deployment можно также использовать объект ReplicaSet, однако мы не коснемся его в наших примерах.
Подробнее о Deployment можно узнать в официальной документации. Нам снова потребуется удалить Pod (нам не требуется удалять Service): Добавим следующее описание Deployment: Создадим указанный Deployment: Мы выбрали значение 10 для параметра replicas, поэтому в нашем кластере будут созданы 10 Pod-ов с приложением Nginx: Вы можете получить доступ из внешней сети к запущенному приложению, используя Service, созданный в предыдущем разделе. Service будет производить автоматическую балансировку запросов из внешней сети между 10 экземплярами Nginx. При необходимости, мы можем обновить версию Nginx. Обновим описание Deployment, изменив версию образа с 1.14-alpine на 1.15-alpine: Для запуска процесса обновления Pod-ов, воспользуемся командой kubectl. Обратите внимание на аргумент --record, он нам пригодится для последующего удобного отката версии Nginx: Вы можете следить за ходом обновления при помощи следующей команды: Kubernetes будет ждать 10 секунд после успешного обновления одного Pod-а, так как мы указали значение 10 для параметра minReadySeconds в описании Deployment. После завершения обновления все Pod-ы для Deployment перейдут в активное состояние: Мы можем произвести откат версии приложения, если что-то пошло не так. Для этого нам потребуется выбрать нужную ревизию Deployment: В выводе команды есть 2 ревизии — первая это изначальное создание Deployment, вторая это обновление. Так как мы использовали аргумент --record при обновлении, то мы видим команду, которая создала вторую ревизию Deployment. Для отката версии воспользуемся следующей командой: Аналогично с обновлением, мы можем следить за выполнением отката версии при помощи команды: Во всех наших примерах мы использовали контейнеры без постоянного хранилища данных. В следующем разделе мы это исправим. По умолчанию, все данные контейнеров запущенных внутри Pod-ов являются эфемерными и будут потеряны падении Pod-а. Для запуска Pod-ов с постоянным хранилищем данных можно использовать объект PersistentVolumeClaim. Создать такой объект в кластере очень просто — достаточно добавить его описание, по аналогии с тем, как мы создавали Pod, Service или Deployment в предыдущих разделах. Подробнее можно узнать из официальной документации. Пример описания PersistentVolumeClaim, создающего диск размером 10GB: Мы можем подключить его в виде диска к нашему Pod, обновив описание Pod c Nginx, созданного ранее: Однако, для того, чтобы диск был создан, вам потребуется указать свойства создаваемого диска в виде StorageClass. В сервисе “Виртуальное приватное облако” можно использовать сетевые диски быстрого, универсального и базового типов в качестве постоянного хранилища данных Pod-ов Kubernetes. К примеру, чтобы создать StorageClass, который позволит использовать быстрые диски в зоне доступности ru-1b, вам потребуется следующее описание: Перед созданием указанных объектов, удалим Deployment, созданный ранее: В первую очередь создадим StorageClass, таким образом он станет классом по умолчанию, и созданный впоследствии PersistentVolumeClaim будет использовать его: Создадим PersistentVolumeClaim и Pod: После этого в вашем проекте автоматически будет создан диск, который будет подключен к одной из minion-нод кластера. При её падении, диск будет автоматически переключен в другую ноду. Мы можем увидеть диск внутри контейнера с Nginx: Вы можете подключать диск и к Deployment. С соответствующим примером можно ознакомиться в официальной документации. Вы можете использовать встроенную панель (dashboard) самого Kubernetes для просмотра состояния объектов кластера и их управления. Для доступа ко всем возможностям панели вам потребуется создать аккаунт с ролью администратора в вашем кластере. Для этого нам понадобится описание аккаунта: И описание роли: Создадим указанные объекты: Далее вам потребуется узнать значение сгенерированного токена для этого аккаунта.
Для этого требуется найти соответствующий объект типа Secret в кластере: И посмотреть значение токена у найденного Secret с именем admin-user-token-bkfhb: В ответ вы получите значение токена, сохраните его, оно нам пригодится в дальнейшем.
С подробностями разграничения доступа к объектам Kubernetes можно ознакомиться в официальной документации.  В том случае, если вы создавали кластер из публичного шаблона, в нем уже существуют Pod и Service, обеспечивающие работу панели: Так как Service имеет тип ClusterIP, то он будет доступен только изнутри самого кластера.
Вы можете получить доступ к панели со своего рабочего компьютера с конфигурационным файлом кластера, используя команду kubectl: Проверьте работоспособность proxy, открыв указанный адрес в браузере: Если вы видите ответ, аналогичный скриншоту, то можно перейти на экран панели управления, используя следующий адрес: Перейдя по нему, вы должны увидеть экран логина в панель: Вам потребуется указать токен, полученный ранее. После входа вы сможете использовать панель управления: Обо всех возможностях панели управления можно узнать в официальной документации. В случае использования публичного шаблона кластера, у вас будут автоматически запущены компоненты для сбора и отображения метрик — Prometheus и Grafana. Аналогично панели управления, в качестве типа Service установлен ClusterIP, доступ к нему возможен только изнутри кластера или посредством kubectl proxy. Вы можете получить доступ к Grafana со своего рабочего компьютера по следующему адресу:  В этой статье мы изучили наиболее часто используемые объекты Kubernetes и рассмотрели примеры по запуску и управлению кластером при помощи OpenStack Magnum. В ближайшее время станет возможным использование последних релизов Kubernetes, а управление кластером будет доступно через панель управления. Будем рады, если вы воспользуетесь нашим сервисом в режиме тестирования и предоставите обратную связь. Software Engineer