Опыт использования AWS ECS в нашей инфраструктуре
В данной статье я бы хотел поделиться нашим опытом использования AWS ECS в инфраструктуре, рассказать о плюсах и минусах этого продукта и о том, как мы решали проблемы с этим связанные. Начнём с определения:
Amazon EC2 Container Service — это высокопроизводительный сервис управления контейнерами с высокими возможностями масштабирования.
По сути ECS это попытка компании Amazon влезть в рынок управления контейнеров, где сейчас существуют Kubernetes, Mesos/Marathon, Docker Swarm и другие. Однако, в отличии от них Amazon предоставляет сервис с API, таким образом наиболее близкий аналог это Google Compute Engine (aka kubernetes-as-a-service). Стоит отметить, что сам ECS бесплатен, а платите вы только за EC2 инстансы.
Работа с ECS выглядит следующим образом:
- Создаем несколько EC2 инстансов, устанавливаем на них ECS-агента и объединяем в кластер
- Создаем файл с описанием контейнеров и как их нужно запускать (количество, стратегия деплоя, переменные окружения, etc)
- Передаем этот файлик через API в наш кластер
- ECS сам выберет на каком из инстансов следует запустить контейнер и перезапустит его в случае падения
- ???
- PROFIT
Для читателей, уже использовавших Kubernetes, эта схема покажется весьма знакомой. Помимо работы через API, эти же действия можно выполнить через веб-интерфейс. Наглядно на диаграмме:
Проблема балансировки и service discovery
Запустить контейнеры обычно бывает мало, нужно ещё как то до них достучатся из вне. Для этого нужно знать на каком из инстансов и на каком порту запущен наш контейнер. Для решения этой проблемы AWS предлагает интеграцию с ELB, где вы должны указать статический порт для вашего контейнера и подключить к кластеру ELB на этом порту. Такой подход используется в PaaS Empire.
Примечание: я не смотрел на новый AWS ALB, возможно там все по-другому.
Этот способ не лишён недостатков, например, нам нужно платить за каждый ELB для каждого типа сервисов, даже если на них нет трафика. Особенно эта проблема остро стоит если мы планируем создавать сервисы динамически. Так же мы не можем запускать больше 1 сервиса на 1 инстансе из-за конфликта портов. Все это ведёт к неэффективной утилизации ресурсов и неудобствам использования. Это не наш путь.
После поиска инструментов для service discovery наш выбор пал на consul от Hashicorp. Для регистрации контейнеров в consul мы используем registrator. Таким образом на инстансы помимо ECS-агента мы устанавливаем еще consul-агента и registrator. На схеме:
После старта контейнера ECS-агентом на случайном порту, registrator получает нотификацию через docker api и регистрирует сервис в consul. Registrator позволяет использовать магические переменные окружения для того чтобы определить healthcheck для сервиса в consul, а так же указать тэги.
Дальше нам необходимо решить проблему балансировки трафика между consul сервисами и мы решили попробовать fabio, основное преимущество которого отсутствие конфигурации. Fabio конфигурирует себя, читая список сервисов из consulа, и, согласно тэгам, строит таблицу маршрутизации. При изменении статуса сервиса или добавления нового, fabio моментально перестраивает таблицу маршрутизации. У Fabio есть так же интерфейс, в котором можно посмотреть текущие маршруты и количество трафика перенаправляемого на определённый контейнер:
На упрощённой схеме, можно видеть что нам удалось использовать лишь 1 ELB для всего кластера:
Сервисы
В ECS мы деплоим стандартные stateless 12factor приложения, обернутые в docker контейнеры. Мы используем собственную обёртку над AWS API для ECS, чтобы деплоить сервисы было ещё легче и удобнее. Так вместо JSONа, который принимает ECS, мы используем упрощённый yml, напоминающий формат Kubernetes:
---
- name: demo-service
image: test-image
version: 4.2
region: eu-central-1
cluster: ecs-cluster
cpu: 128
memory: 256
port: 8080
instances: 2
custom_env:
SOMEVAR: somevalue
Такой файл лежит в каждом репозитории каждого сервиса, который деплоится на ECS. Можете сравнить его с JSON, который принимает AWS. При этом для деплоя нужна только обёртка и AWS API ключ.
Мы так же интегрировали ECS с github через Jenkins и деплоим каждый pull request на ECS при открытии, для разработчиков это выглядит так:
Так при code review каждый сразу может проверить предлагаемые изменения в сервисе и запустить интеграционные тесты. Да и запустить приложение сразу «в облаке» достаточно приятно.
Плюсы
На мой взгляд, ECS вполне справляется с задачей оркестрирования контейнеров и с этим «можно жить». К очевидным плюсам я бы отнёс следующее:
- Бесплатность — плата только за EC2.
- Hosted решение, где вам не нужно думать о fault tolerance.
- Низкий порог входа, все можно «накликать» через веб-интерфейс.
- Интеграция с EC2 и ECS сразу знает, когда инстанс не доступен.
- Интеграция с CloudWatch и AutoScalingGroup, которая позволяет регулировать количество EC2 инстансов в ECS кластере в зависимости от количества запущенных контейнеров.
Минусы
А теперь того, чего нам не хватает и почему для следующего проекта я буду использовать Kubernetes.
- Vendor-lock на AWS.
- Медленное развитие ECS как продукта, так и интеграций других сервисов с ним. Так в eu-central-1 до сих пор нет интеграции с OpsWorks.
- В AWS SDK нет прямого способа проверить exit code контейнера, при запуске one-off task. В Kubernetes это есть.
- Хотя заявлено, что ECS знает про зоны доступности (aka availability zone aka AZ), распределение контейнеров между AZ не такой как вы могли бы ожидать. Так, например, в случае если одна AZ будет не доступна, то все контейнеры будут перемещены в другую, однако, после поднятия этой AZ ваши контейнеры уже не будут перемещены. Так же я наблюдал странности при деплое, когда весь сервис был задеплоен только в 1 AZ, потому что там были инстансы с наибольшим количеством ресурсов.
- ECS ничего не знает про healthcheckи контейнеров, запущенный сервис это тот, где контейнер запустился. В Kubernetes это есть.
- Если вы хотите statefull приложения — ECS не для вас. При этом в Kubernetes уже есть сносная поддержка и с каждым релизом ситуация улучшается.
- Проприетарный продукт, куда нельзя послать патч.
Вывод
Когда мы начинали использовать ECS (конец 2015 года) он был весьма неплох в сравнении с конкурентами. Однако, по прошествии времени можно сказать, что ECS не поспевает за рынком и этого продукта мало шансов на успех в будущем. Можно например посмотреть куда теперь коммитит самый активный разработчик ecs-agentа. ECS подходит тем, кто только начал своё погружение в мир оркестрации контейнеров, но если вы планируете серьёзный проект на длительный срок, то посмотрите в сторону Kubernetes или Mesos/Marathon.
Комментарии (1)
7 октября 2016 в 09:11
0↑
↓
По моему мнению, лучше развернуть Kubernetes поверх AWS, и избежать многих минусов, перечисленных в статье. Миграция между облачными (и self-hosted) решениями будет намного проще, в добавок k8s очень активно развивается.