Первое знакомство с Kubernetes создаем приложение для развертывания в кластере

Первое знакомство с Kubernetes создаем приложение для развертывания в кластере

Поскольку Python – единственный язык программирования, на котором я что-то умею писать, особого выбора у меня нет. Приложения будет запускаться как веб-сервер, слушать указанный порт и при обращении выдавать приветствие “Hello from Python”. Кроме Python потребуется фреймворк Flask.

Код приложения:

В первых двух строчках мы подключаем Flask, а далее создаем обработку корневого запроса. Приложение неидеально, но как минимальный вариант для развертывания в кластере k8s оно сгодится. Так как k8s – это среда запуска контейнеров, для переноса приложение необходимо упаковать, например, в Docker.

Упаковываем приложение в контейнер Docker

Чтобы собрать контейнер, нужно поставить Docker на локальную машину (да, да – Капитан очевидность). Инструкция по инсталляции есть на официальном сайте – процесс довольно несложен. Далее собирать образ можно средствами Docker, я использую для этих целей утилиту buildah. Она ни разу меня не подводила, рекомендую.

Для начала создаем директорию, из которой будем собирать контейнер. Первый файл в директории назовем, например, app.py (его код приведен выше). Для установки зависимостей нам потребуется файл requirements.txt . Поскольку приложение простенькое, достаточно добавить только модуль Flask:

Третий файл называется Dockerfile – без расширения. Его содержимое:

Разберем его построчно:

  • FROM python:3.9-alpine – добавляем в контейнер интерпретатор Python 3.9, сборка alpine.
  • RUN mkdir /app – создаем директорию /app внутри контейнера.
  • WORKDIR /app – позволяет один раз указать конкретный путь (каталог на диске), после чего большинство инструкций (например, RUN или COPY) будут выполняться в контексте этого каталога.
  • ADD . /app/ – очень важная команда, если мы делаем контейнер для k8s. Дело в том что когда отрабатывает запуск контейнера, k8s думает, что нам необходима внешняя директория /app . Ее в кластере нет, и контейнер падает с ошибкой (не найден файл /app/app.py ).
  • RUN pip install -r requirements.txt – запускаем pip и скармливаем ему файл зависимостей. Flask скачивается и устанавливается в контейнер.
  • EXPOSE 5000 – пробрасываем порт 5000 для общения с нашим приложением.
  • CMD [“python”, “/app/app.py”] – запускаем интерпретатор Python и наше приложение app.py .

Находясь в директории с файлами, выполняем команду для сборки контейнера на основе Dockerfile с помощью утилиты buildah:

Запустится сборка, прогрузятся все зависимости из requirements.txt , и в итоге сгенерируется хеш – строка Storing signatures , которая нам в дальнейшем понадобится (копируем ее в буфер обмена)

Первое знакомство с Kubernetes создаем приложение для развертывания в кластере

Дальше необходимо запушить сборку в локальный репозиторий Docker. Выполняем следующую команду, подставляя в параметры свой хеш:

  • :app – это имя нашего контейнера (можно указать свой).
  • :v0 – это tag. Обычно через него выставляется версионность для удобной навигации в репозитории.

Контейнер уже можно увидеть в списке локального репозитория Docker, выполнив следующую команду:

Первое знакомство с Kubernetes создаем приложение для развертывания в кластере

Первое знакомство с Kubernetes создаем приложение для развертывания в кластере

Приложение откликается, значит контейнер рабочий. Последний штрих – запушить контейнер из локального репозитория в удаленный, например, в Docker Hub. Это нужно, чтобы мы могли скачать контейнер в кластер k8s и запуститься его уже там.

Чтобы это сделать, потребуется авторизоваться на Docker Hub и создать пустой репозиторий. Детально описывать эту процедуру не буду: процесс похож на создание Git-репозитория.

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

Цель – развернуть приложение Python из контейнера, но уже в кластере k8s в нескольких репликах.

Для этого необходимо создать два объекта (подробнее мы рассматривали их в предыдущей статье):

  • Deployment – развернет приложение и будет поддерживать необходимое количество реплик.
  • Service – обеспечит сетевое взаимодействие внутри кластера.

Создаем Deployment для приложения в кластере k8s

Заходим по SSH на мастер-узел (ноду), проверяем работоспособность kubectl . Далее необходимо создать deployment.yaml .

Разбираем подробнее:

  • kind: Deployment – определяем, какой у нас будет объект. В данном случае Deployment , но может быть и Service или, скажем, Pod .
  • name: app – имя нашего Deployment (именно так он будет отображаться в кластере k8s).
  • matchLabels: и app: app – метка приложения, ее уникальный идентификатор для дальнейшего мапинга с сервисом и другими объектами k8s.
  • replicas: 2 – сколько экземпляров приложения необходимо создать
  • containers: – этой секции описывается, откуда нам спулить контейнер (ясно дело, с Docker Hub). Порт для сетевого взаимодействия.
  • resources: – интересная секция. Тут описаны минимально необходимые ресурсы для запуска ( limits ). Без этих ресурсов приложение не стартует и планировщик кластера будет искать подходящий узел, удовлетворяющую минимальным ресурсам. Запрашиваемые ( requests ) – это ресурсы, которые резервируются на ноде для вашего приложения. Сверх этих ограничений приложение не получит ресурсов CPU и RAM.

Сохраняем файл deployment.yaml и выполняем команду для развертывания приложения:

Если ошибок в файле не было, успешный исход – активное приложение в 2 репликах. Посмотреть состояние можно следующей командой:

Приложение развернуто в двух репликах – с помощью curl можно обратиться к каждой из них по IP пода, но это плохой вариант (поды рано или поздно переедут на другие узлы и IP поменяются). Давайте напишем еще один объект кластера, который закроет эту проблему – Service .

Создаем Service приложения в кластере k8s

Создаем еще один файл service.yaml .

Его главные отличительные особенности:

  • ports: port – порт, по которому Service будет принимать трафик.
  • targetPort – порт для связи с приложением.
  • selector: – мапим наш Deployment и все реплики по этой метке.
  • type: clusterIP – тип объекта Service . В нашем случае для сетевого взаимодействия внутри кластера k8s.

Запускаем процедуру создания следующей командой:

Далее смотрим детали Service :

Первое знакомство с Kubernetes создаем приложение для развертывания в кластере

Супер! У нас есть IP, по которому можно обращаться к сервису в кластере с любого пода.

Подведем итог статьи. Мы добились следующих результатов:

  • Написали приложение на Python + Flask.
  • Упаковали приложение в контейнер Docker.
  • Разместили контейнер в репозитории Docker hub.
  • Сделали Deployment и Service в кластере k8s.

Поздравляю, вы развернули первое приложение в кластере k8s! Возможно оно простовато, но в следующих статьях мы будем доводить его до ума.