обзор AWS ECS на примере


Это вторая статья из цикла «инфраструктура Jenkins в ECS». В предыдущей статье акцент был уделен сбору логов из ECS контейнеров. Давайте поподробнее разберёмся, как устроен ECS и как его правильно готовить. Если кто-то уже знаком с kubernetes, то ECS немного похож на него. Атомарной единицей в ECS является task, это, по сути, один или группа контейнеров. Таск описывается с помощью task definition, там можно задать лимиты ресурсов (памяти, процессора), дисковые тома, переменные окружения, порты и многое другое, смотри документацию по ссылке выше. Task definition представляет из себя json. Пример task definition для jenkins, можете подсмотреть в предыдущей статье.

Над task, в иерархии ECS стоит service, он может включать в себя несколько копий одинаковых тасков. Также для сервиса можно задавать политики деплоймента, балансировщик, IAM роли. Пример service definition для jenkins. Все дальнейшие примеры написаны на HCL для terraform.

resource "aws_ecs_task_definition" "jenkins-master" {
  family                = "jenkins"
  container_definitions = "${data.template_file.jenkins-master.rendered}"

  volume {
    name      = "jenkins_home"
    host_path = "/srv/synced/jenkins_home"
  }
}

# Template for task config json to set different git commit sha per cluster
data "template_file" "jenkins-master" {
  template = "${file("${path.module}/templates/jenkins-master.json")}"
}

resource "aws_ecs_service" "jenkins-master" {
  name                               = "jenkins-master"
  cluster                            = cluster_id
  task_definition                    = "${aws_ecs_task_definition.jenkins-master.arn}"
  desired_count                      = 1
  iam_role                           = iam-role-to-register-in-elb
  deployment_maximum_percent         = 100
  deployment_minimum_healthy_percent = 0

  load_balancer = {
    elb_name       = "${aws_elb.jenkins-master.id}"
    container_name = "jenkins-master"
    container_port = 8080
  }
}

Группировать сервисы можно по кластерам, в которые входят ec2 instances. Лучше всего использовать сервисы с ALB, но для дженкинса это не получится, т.к. ALB не поддерживает tcp, а он нужен для корректной работы протокола jnlp.

Создадим балансировщик для нашего дженкинса.

resource "aws_elb" "jenkins-master" {
  name    = "jenkins-master"
  subnets = [pub-subnet1id, pub-subnet2id, pub-subnet3id,]

  security_groups = [
    security-group-id,
  ]

  idle_timeout                = 1200
  connection_draining         = true
  connection_draining_timeout = 10
  internal                    = false

  listener {
    instance_port      = 8080
    instance_protocol  = "http"
    lb_port            = 443
    lb_protocol        = "https"
    ssl_certificate_id = acm-certificate-id
  }

  listener {
    instance_port     = 8080
    instance_protocol = "http"
    lb_port           = 80
    lb_protocol       = "http"
  }

  listener {
    instance_port     = 50000
    instance_protocol = "tcp"
    lb_port           = 50000
    lb_protocol       = "tcp"
  }

  health_check {
    healthy_threshold   = 2
    unhealthy_threshold = 10
    timeout             = 10
    target              = "HTTP:8080/login"
    interval            = 15
  }

  tags {
    Name      = "jenkins-master"
  }
}

Убедимся, что health check прописан правильно, иначе ecs планировщик будет перезапускать наш таск бесконечно.

Этапы жизни сервиса:

  1. Мы обновили task definition, например, указав новую версию image.
  2. Начинается деплой. В зависимости от политик, старый таск может или быть остановлен, после того как побудет определённое количество времени в состоянии draining в балансировщике, или же будет создан новый таск, параллельно с существующим, в таком случае мы получим Green Blue деплой. После того как новые таски пройдут проверку на балансировщике, старые начнут постепенно заменяется новыми или единовременно будут остановлены. Стоит обратить внимание, что если по каким-либо причинам новые таски не могут запуститься или пройти проверку, вам необходимо вмешаться и откатиться на старую версию, иначе планировщик не прекратит попытки деплоя. Иногда мониторинг количества тасков в состоянии Pending не кажется такой уж и плохой затеей.

В нашем случае, единственный контейнер с дженкинс будет остановлен, а новый будет деплоиться после этого.

Минусы ECS:

  1. Vendor lock, если вы захотите съехать с Амазона, вам придется переписывать всю конфигурацию сервисов.
  2. Нет нотификаций про неудачные деплои, нужно в ручном режиме мониторить или писать всякие обвязки воркуг.
  3. ECS Agent поддерживает не все возможности докера, например, во время написания этой статьи нельзя было поменять параметр shm-size.