Автор Шимон Тольц
ironSource — ведущая в мире платформа для поиска, распространения, доставки и монетизации программного обеспечения. Решение состоит из четырех ядер — installCore, mobileCore, displayCore и mediaCore — которые связывают разработчиков программного обеспечения и пользователей на разных платформах и устройствах.
В обязанности отдела инфраструктуры входит обработка данных, полученных со всех наших платформ, для нашего собственного анализа данных и выставления счетов. В любой день мы получаем десятки или даже сотни миллионов событий с настольных компьютеров, мобильных телефонов и веб-браузеров. Наша система состоит из сотен серверов, поддерживающих более 5000 одновременных подключений.
В этой статье я опишу, как мы в IronSource масштабируем Node.js с помощью Docker — автоматически собираем , разворачиваем и запускаем приложение Node.js в контейнере Docker для производства.
Стек приложений IronSource
Мы широко используем облако AWS и действительно наслаждаемся им. Наш облачный набор в значительной степени «по книге» (наш консультант AWS весьма доволен): Elastic Load Balancer (ELB) получает весь трафик, отправляя его на кучу стандартных машин Ubuntu, и, естественно, мы используем auto-scaling-group масштабировать размер нашего кластера автоматически.
Мы используем архитектуру микросервисов, в которой множество отдельных приложений взаимодействуют друг с другом. Мы стараемся ограничить каждый сервис только одним делом. Наш основной язык разработки — Node.js, работающий на Linux. Сервисы взаимодействуют друг с другом через очередь (RabbitMQ). поток (Kinessis) или вызовы HTTP REST API.
Мы выполняем короткие циклы разработки и практикуем непрерывную интеграцию и доставку . Каждый раз, когда разработчик инициирует слияние с нашей промежуточной ветвью, сервер Jenkins CI обнаруживает изменения и запускает процесс сборки, за которым следуют автоматические тесты. Если слияние выполнено успешно, код объединяется с основной веткой и помещается в нашу производственную среду.
Так почему Докер?
В настоящее время мы используем предварительно «запеченный» образ (AMI) с предварительно установленными требованиями для запуска приложения. Мы используем скрипт начальной загрузки, который загружает последний код из нашего частного репозитория npm (Node.js Package Manager) и запускает его. Мы ж
намеревался перейти к полностью автоматизированному циклу инициализации, который позволил бы нам динамически настраивать изображение для приложения. Естественно, на ум пришли два кандидата — шеф-повар и докер. И Chef, и Docker позволяют запускать инфраструктуру в виде кода, но Chef тратит время на подготовку каждого нового экземпляра при загрузке. Это происходит довольно часто, потому что мы динамически масштабируем количество работающих серверов в соответствии с изменяющимся спросом. В процессе сборки Docker стоит один раз только один раз. Нам нравится идея контейнеров, которые работают изолированно через ядро Linux (скоро Windows?). Итак, с последним обманом и массовым внедрением этой технологии, мы решили попробовать Docker.
Наш контейнер
Контейнер Docker запускает приложение Node.js за обратным прокси-сервером Nginx. Мы используем систему управления процессами с именем Supervisor, которая запускает наше приложение в контейнере и действует как сторожевой таймер — в случае сбоя приложения. Каждый контейнер Docker получает точку входа, процесс, запускаемый при запуске контейнера. Supervisor — это точка входа в наш контейнер. Приложения Nginx и Node.js запускаются через Supervisor.
Мы используем тип экземпляра c3.large для большинства наших приложений. В связи с тем, что этот тип экземпляра имеет два ядра процессора. Мы запускаем два процесса Node.js, прослушивая порты 8000 и 8001. Nginx прослушивает порт 80 и действует как обратный прокси-сервер для перенаправления трафика на экземпляры приложения Node.js на портах 8000-8001. Мы используем Ubuntu 14.04 как для хоста, так и для контейнера.
The Magic: Конфигурация начальной загрузки Amazon AMI
Процесс начальной загрузки (пользовательские данные) довольно прост. Мы загружаем стандартный образ Ubuntu (14.04). Затем мы выполняем обновление дистрибутива / безопасности, устанавливаем клиент Docker, входим в репозиторий Docker и запускаем наш контейнер, открывающий порт 80 — это так просто!
#AMI - c3.large - ubuntu 14.04 - user-data: #!/bin/bash sudo apt-get update sudo apt-get -y dist-upgrade sudo apt-get -y install docker.io sudo docker login -u <user> -p <password> -e <email> sudo docker pull user/container sudo docker run -p 80:80 -d user/container
GitHub для технической спецификации и настроек — https://github.com/ironSource/docker-config
Финальные заметки
Контейнеры Linux и Docker позволяют нам полностью использовать нашу архитектуру микро-сервисов. Нам больше не нужно беспокоиться о разных версиях в разработке и производстве. Это позволяет нам строить для нагрузки и масштабировать с первого дня. Docker по-настоящему перегружен нашими циклами разработки.
Будущие разработки
Некоторое дальнейшее исследование, которое я планирую, заключается в использовании облегченной ОС Linux для контейнера и хоста (CoreOS?). ИТ-мониторинг контейнера для меня все еще неясен. Я рассматриваю возможность установки ИТ-агента NewRelic на каждый контейнер. Я также планирую протестировать новую службу управления контейнерами ( ECS ) Amazon для контроля загрузки парка. Я также хотел бы проверить эту настройку на платформе Microsoft Azure.