image

В данной статье я бы хотел поделиться нашим опытом использования AWS ECS в инфраструктуре, рассказать о плюсах и минусах этого продукта и о том, как мы решали проблемы с этим связанные. Начнём с определения:
Amazon EC2 Container Service – это высокопроизводительный сервис управления контейнерами с высокими возможностями масштабирования.

По сути ECS это попытка компании Amazon влезть в рынок управления контейнеров, где сейчас существуют Kubernetes, Mesos/Marathon, Docker Swarm и другие. Однако, в отличии от них Amazon предоставляет сервис с API, таким образом наиболее близкий аналог это Google Container Engine (aka kubernetes-as-a-service). Стоит отметить, что сам ECS бесплатен, а платите вы только за EC2 инстансы.

Работа с ECS выглядит следующим образом:

  • Создаем несколько EC2 инстансов, устанавливаем на них ECS-агента и объединяем в кластер
  • Создаем файл с описанием контейнеров и как их нужно запускать (количество, стратегия деплоя, переменные окружения, etc)
  • Передаем этот файлик через API в наш кластер
  • ECS сам выберет на каком из инстансов следует запустить контейнер и перезапустит его в случае падения
  • ???
  • PROFIT

Для читателей, уже использовавших Kubernetes, эта схема покажется весьма знакомой. Помимо работы через API, эти же действия можно выполнить через веб-интерфейс. Наглядно на диаграмме:

image

Проблема балансировки и service discovery


Запустить контейнеры обычно бывает мало, нужно ещё как то до них достучатся из вне. Для этого нужно знать на каком из инстансов и на каком порту запущен наш контейнер. Для решения этой проблемы AWS предлагает интеграцию с ELB, где вы должны указать статический порт для вашего контейнера и подключить к кластеру ELB на этом порту. Такой подход используется в PaaS Empire.

Примечание: я не смотрел на новый AWS ALB, возможно там все по-другому.

Этот способ не лишён недостатков, например, нам нужно платить за каждый ELB для каждого типа сервисов, даже если на них нет трафика. Особенно эта проблема остро стоит если мы планируем создавать сервисы динамически. Так же мы не можем запускать больше 1 сервиса на 1 инстансе из-за конфликта портов. Все это ведёт к неэффективной утилизации ресурсов и неудобствам использования. Это не наш путь.

После поиска инструментов для service discovery наш выбор пал на consul от Hashicorp. Для регистрации контейнеров в consul мы используем registrator. Таким образом на инстансы помимо ECS-агента мы устанавливаем еще consul-агента и registrator. На схеме:

image

После старта контейнера 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:

demo-service.yml
---
- 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.
Поделиться с друзьями
-->

Комментарии (16)


  1. Biggo
    07.10.2016 09:11

    По моему мнению, лучше развернуть Kubernetes поверх AWS, и избежать многих минусов, перечисленных в статье. Миграция между облачными(и self-hosted) решениями будет намного проще, в добавок k8s очень активно развивается.


    1. ptQa
      07.10.2016 10:08

      Kubernetes тоже не лишён минусов, fault tolerant master так и не запилили, например.


      1. Biggo
        07.10.2016 10:28

        Master HA можно запилить самому, есть руководство, но скоро видимо запилят это в новый kubeadm


        1. ptQa
          07.10.2016 10:47

          Можно ссылку на руководство? Вы уверены что речь идёт о мастере, который задеплоен на несколько датацентров (aka availability zone) и он остаётся доступен при падении 1 из них? Вроде бы этим занимается подпроект Ubernetes.


          1. Biggo
            07.10.2016 10:49

            http://kubernetes.io/docs/admin/high-availability/

            Оно несколько топорное, но надеюсь что это все будет автоматизировано в будущем


            1. ptQa
              07.10.2016 11:02

              Это руководство для мастера, который устойчив к падению нод в датацентре, но не всего датацентра. Да и вообще не ясно как это сделать поверх etcd. Ведь если у меня 2 датацентра, а для консенсуса RAFT требует 2/3, 3/5, и т.д., то как тут сделать fault tolerant etcd. Об этом же написано в issue https://github.com/kubernetes/kubernetes/issues/21124


              В общем не путайте людей, в kubernetes все еще этого нет.


              1. Biggo
                07.10.2016 11:04

                А я и ни слова не говорил про отказустойчивость между датацентрами.


              1. Eternalko
                07.10.2016 13:01

                FYI Если у вас 2 датацентра, то нет возможности решить split-brain problem.


  1. AsianCat
    07.10.2016 10:06

    А зачем нужен этот зоопарк, когда GC уже имеет k8s в своем составе (что более чем логично) и практически готов к использованию сразу же? Кроме того k8s при желании можно развернуть где угодно, о чем верно написано.


  1. ForeverYoung
    07.10.2016 10:13

    не можем запускать больше 1 сервиса на 1 инстансе из-за конфликта портов

    Есть же Application Balancer
    Интеграция с CloudWatch и AutoScalingGroup, которая позволяет регулировать количество EC2 инстансов в ECS кластере в зависимости от количества запущенных контейнеров.

    Можно об этом поподробнее?


    1. ptQa
      07.10.2016 10:35

      Потому я и написал:


      Примечание: я не смотрел на новый AWS ALB, возможно там все по-другому.
      Когда мы начинали использовать ECS (конец 2015 года)...

      Про CloudWatch дал ссылку на тутлориал в статье.



  1. litvin
    07.10.2016 19:11

    Удивительно мало знают у нас о Cloud Foundry. Можно использовать как сервис (Pivotal Web Services, IBM Bluemix, GE Predix, Swisscom, CenturyLink) а можно и установить в свою инфраструктуру. Даже на лэптоп.


  1. dnefedkin
    09.10.2016 20:08
    +1

    «таким образом наиболее близкий аналог это Google Compute Engine (aka kubernetes-as-a-service)»: Google Compute Engine — это аналог EC2, Google Container Engine — это Kubernetes as a service.


    1. ptQa
      09.10.2016 23:58

      Поправил, спасибо.


  1. shuron
    09.10.2016 23:44

    А теперь того, чего нам не хватает и почему для следующего проекта я буду использовать Kubernetes.

    Именно так! Тоже с две недели поткали ЕЦС и лично я пришел вашему выводу!