Portainer+Container

Всем доброго времени суток! В этой статье хотел бы кратко в режиме смузи осветить возможности Portainer API и применение в разворачивании проектов.

Рассмотрим несколько задач:

  • Управление. Иметь возможность отображать работу всех контейнеров на определенном узле, управлять и отслеживать состояние, читать логи и контролировать ресурсы.
  • Разворачивание. Минимизировать участие пользователя и создать благоприятные условия для автоматизированного разворачивания на новом месте.
  • Интеграция с gitlab-ci. Упростить процесс разработки.

Управление


Обладая опытом работы с Docker, переход на docker-swarm привлек относительной простотой и скоростью освоения в сравнении с Kubernetes. Для одного менеджер узла (leader node) и нескольких worker-ов предстояло решить, как отобразить в одном окне статус запуска, количество работ, статистику использования памяти и health-чеки. В первую очередь необходимо готовое решение с графическим интерфейсом исходя из потребностей задачи.

Можно найти много статей по сравниванию между собой GUI-интерфейсов для управления Docker-ом. Приведу несколько примеров: тут и тут. Необходимые требования для решения задачи были найдены в Portainer.

Положительные моменты:

  • простота разворачивания
  • авторизация из коробки
  • API
  • возможность добавления собственного registry
  • возможность подключения к консоли контейнера
  • чтение логов
  • отслеживание характеристик использованой памяти и сети контейнеров.

Portainer состоит из двух элементов: Portainer Server и Portainer Agent. Оба элемента работают как контейнеры Docker — достаточно задеплоить. Вообще работа Portainer основывается на размещении своих агентов на всех нодах, осуществляя общение через http-запросы. Из документации становится ясно, что Portainer Agent — это обходной путь для ограничений API Docker для управления его средой, так как из коробки взаимодействие с containers, networks, volumes, images ограничено текущим узлом, к которому нацелен запрос Docker API. Решение этому есть, например, открыть порт на каждом узле , а потом защитить сертификатами, наладить схему общения и т.д. Одним словом — не удобно, но вариант. Задача же агента — предоставить возможность общения кластерно-ориентированным ресурсам ранее определенного узла. Достаточно выполнить только один запрос API Docker, чтобы получить все эти ресурсы из каждого узла в кластере.

Portainer Agents

В целом, улучшается user-experience при управлении кластерами Swarm. Немного больше и со скриншотами можно посмотреть тут или тут.

Разворачивание


(Ссылку на скрипты и стеки оставлю внизу).

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

docker stack deploy -c "имя файла стека"

В таком случаем стек загрузится, но в Portainer будет заблокированным для редактирования, что опять же не соответствует потребностям задачи. Тогда на выручку приходит Portainer API с возможностью загрузки стеков. Для удобства рекомендую установить пакеты httpie и jq на manager unix-машину либо использовать классический curl. Передаем скрипту логин и пароль для входа в Portainer и запускаем командой:

sh script.sh Username Password

Для начала получаем ключ авторизации:

key=$(http POST 127.0.0.1:9000/api/auth Username="$1" Password="$2" | jq -r '.jwt')

Получаем swarm_id (адрес, куда полетят стеки):

swarm_id=$(http GET 127.0.0.1:9000/api/endpoints/1/docker/swarm "Authorization: Bearer $key" | jq -c '.ID')

Дальше запускаем процесс загрузки, попутно получаем некоторую второстепенную информацию:

for file in stacks/*  
	do
	dir=$(readlink -f "$file")
filename=$(basename "$file" .yml)
	curl -X POST "http://127.0.0.1:9000/api/stacks?method=file&type=1&endpointId=1" -H "Content-Type: multipart/form-data" -H "Accept: application/json" -H "Authorization: Bearer $key" -F "Name=$filename" -F "SwarmID=$swarm_id" -F "file=@$dir"

После этого в Portainer отобразится доступный для редактирования стек. Справедлива и обратная ситуация, когда пользователь вносит изменения в стек через Portainer. Для того чтобы получить эти изменения, необходимо выгрузить и сохранить стек в yml-файле в директорию с другими стеками. Как это можно сделать:

Получаем ключ:

key=$(http POST 127.0.0.1:9000/api/auth Username="$2" Password="$3" | jq -r '.jwt')

Пробегаем по всем стекам и получаем имена и id, сохраняем:

for var in $(http GET 127.0.0.1:9000/api/stacks "Authorization: Bearer $key" | jq -c '.[]?')
  do
    name=$(echo $var | jq -r '.Name')
    id=$(echo $var | jq -r '.Id')
   http GET 127.0.0.1:9000/api/stacks/$id/file "Authorization: Bearer $key" | jq -r '.StackFileContent' > $name.yml
  done

Каждый может найти свое применение инструменту Portainer API.

Тестирование


Для примера использовался gitlab-runner. Рассмотрим следующий вариант применения gitlab-ci: в скрипт service.sh закладываем выполнение вышеизложенных ситуаций и запускаем.

stages:
  - staging
stage-short:
  stage: staging
  image: [SOME_STAGE]
  only:
    changes:
      - [SOME_PROJECT]/*   
    refs:
      - master
  script:  
    - /scripts/service.sh $PORTAINER_ADMIN $PORTAINER_PASS

Думаю на этом все, прикрепляю ссылку на github.