Поскольку 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 , которая нам в дальнейшем понадобится (копируем ее в буфер обмена)
Дальше необходимо запушить сборку в локальный репозиторий Docker. Выполняем следующую команду, подставляя в параметры свой хеш:
- :app – это имя нашего контейнера (можно указать свой).
- :v0 – это tag. Обычно через него выставляется версионность для удобной навигации в репозитории.
Контейнер уже можно увидеть в списке локального репозитория Docker, выполнив следующую команду:
Приложение откликается, значит контейнер рабочий. Последний штрих – запушить контейнер из локального репозитория в удаленный, например, в 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 :
Супер! У нас есть IP, по которому можно обращаться к сервису в кластере с любого пода.
Подведем итог статьи. Мы добились следующих результатов:
- Написали приложение на Python + Flask.
- Упаковали приложение в контейнер Docker.
- Разместили контейнер в репозитории Docker hub.
- Сделали Deployment и Service в кластере k8s.
Поздравляю, вы развернули первое приложение в кластере k8s! Возможно оно простовато, но в следующих статьях мы будем доводить его до ума.