Всем привет! Сегодняшняя статья, как вы увидели в заголовке, посвящена настройке Elastic Beanstalk, а конкретно — балансировщика AWS и количества инстансов TagretGroup в зависимости от нужных нам условий.
Введение в Elastic Beanstalk
Elastic Beanstalk представляет собой высокоуровневую сервисную платформу, которая автоматизирует развертывание приложений в облаке. EB автоматически настраивает необходимую инфраструктуру и ресурсы, такие как экземпляры EC2 (виртуальные серверы), группы безопасности, объекты S3 для хранения файлов версии приложения, базы данных RDS, балансировщики нагрузки Elastic Load Balancing и многое другое, чтобы обеспечить запуск приложения с минимальными затратами времени и усилий со стороны разработчика.
Ключевыми компонентами Elastic Beanstalk являются:
-
Приложение (Application) является основной единицей. Сначала вы создаете приложение, которое служит контейнером для ваших версий и окружений.
-
Окружение (Environment) представляет собой версию приложения, которая развертывается на конкретной инфраструктуре AWS и служит выполнения определенной роли, например, тестового или продакшн окружения.
Ресурсы, с которыми мы будем иметь дело:
-
EC2 (Elastic Compute Cloud) — это виртуальные серверы, которые можно арендовать в облаке AWS для запуска приложений.
-
Target Group — это концепция, используемая в AWS для управления трафиком на уровне приложений. Target Group позволяют указать куда именно должен быть направлен трафик, поступающий на балансировщик нагрузки (Load Balancer). Каждая Target Group ассоциирована с определёнными ресурсами, например с EC2 либо лямбда-функциями.
-
Auto Scaling Groups дают возможность автоматического масштабирования количества экземпляров EC2 в ответ на изменения нагрузки/возникновения других факторов
После небольшого описания EB, приступим к теме статьи.
Вступление и проблемы
Наше приложение было запущено на одном экземпляре c5.xlarge и все status checks от AWS выдавали «Success«, машина была в состоянии «Running«, однако приложение не отвечало. Посмотрев логи сервера, мы поняли, что проблема крылась в перезапуске IIS (эта процедура стандартная — обычно это происходит каждые 29 часов, но также можно настроить период индивидуально).
Однако выяснилось, что сервер перезапустился только через 4 (!) минуты. В контексте нашего приложения 4 минуты неработоспособности веб-сервера недопустимо.
К сожалению, такого рода падения сервера мы не смогли определить с помощью системы мониторинга NewRelic. Всё что мы получили из его логов — что сервер не отвечал на запросы, факты увеличения времени отклика и пр. показатели.
Поэтому в итоге мы решили использовать стандартные фичи ElasticBeanstalk для того чтобы повысить отказоустойчивость нашего приложения. И тут возникли следующие мысли — следует не только заменять неработающие инстансы, но и при большой нагрузке увеличивать их число, либо уменьшать при малой.
Elastic Beanstalk
EB не заточен под работу с одной машиной, поэтому после разговора с заказчиком мы сделали такой сэтап:
-
2x c5.large (c5.large стоит ровно в 2 раза дешевле, чем c5.xlarge)
-
если в течении 5 минут нагрузка на процессор >80%, мы добавляем еще одни инстанс
-
если в течении 5 минут нагрузка на процессор <40%, мы убираем один инстанс
Конфигурация
Resources: AWSEBAutoScalingGroup: Type: "AWS::AutoScaling::AutoScalingGroup" Properties: MinSize: 2 MaxSize: 3 AWSEBCloudwatchAlarmHigh: Type: "AWS::CloudWatch::Alarm" Properties: EvaluationPeriods: 1 MetricName: CPUUtilization Namespace: AWS/EC2 Period: 300 Statistic: Average ComparisonOperator: GreaterThanOrEqualToThreshold Threshold: 80 Unit: Percent AlarmActions: - Ref: "AWSEBAutoScalingScaleUpPolicy" AWSEBCloudwatchAlarmLow: Type: "AWS::CloudWatch::Alarm" Properties: EvaluationPeriods: 1 MetricName: CPUUtilization Namespace: AWS/EC2 Period: 300 Statistic: Average ComparisonOperator: LessThanOrEqualToThreshold Threshold: 40 Unit: Percent AlarmActions: - Ref: "AWSEBAutoScalingScaleDownPolicy" AWSEBAutoScalingScaleUpPolicy: Type: "AWS::AutoScaling::ScalingPolicy" Properties: AdjustmentType: ChangeInCapacity AutoScalingGroupName: Ref: "AWSEBAutoScalingGroup" Cooldown: 360 ScalingAdjustment: 1
Главная проблема такого решения в том, что оно не будет работать как задумано — по умолчанию AWS считает, что если все Status Check на инстансе проходят, то на него можно пускать траффик. Что неверно для нашего кейса — нам нужно добавить к этим проверкам наш собственный HealthCheck, установленный в .NET приложении.
Начнем!
Конфигурация
Для конфигурации нам понадобиться Environment ID и вот эти вкладки в сайдбаре EC2:
Пойдем по порядку:
1) Target Groups
Здесь нам нужно в соответствием с нашими критериями uptime’а задать конфигурацию TG.
Для нашем случае мы посчитали достаточным обнаружение unhealthy машины через 1 минуту:
3 запроса каждые 15 секунд + таймауты (5 сек) = 1 минута
Также во вкладке Attributes есть важный параметр — Deregistration delay. Когда инсанc перестает отвечать по /hc, то он должен быть заменен за время, указанное в этом параметре:
Конфигурация
Resources: AWSEBV2LoadBalancerTargetGroup: Type: "AWS::ElasticLoadBalancingV2::TargetGroup" Properties: HealthCheckIntervalSeconds: 15 HealthCheckPath: /hc HealthCheckProtocol: HTTP HealthCheckTimeoutSeconds: 5 HealthyThresholdCount: 5 UnhealthyThresholdCount: 3 TargetGroupAttributes: - Key: deregistration_delay.timeout_seconds Value: '20'
2) Auto Scaling Groups
2.1 Enable HealthChecks & Set grace period
Самый важный параметр, без которого все конфигурации выше не будут применены:
Чтобы добавить проверку по ELB, нужно нажать на «Turn on Elastic Load Balancing health checks» и установить Health check grace period.
Health check grace period — это время ожидания, в течение которого AWS не будет предпринимать никаких действий по удалению или замене только что созданных (или запущенных) инстансов в рамках Auto Scaling Group, даже если они не проходят health check.
Например, мы только запустили своё новое приложение и ему нужно некоторое время, чтобы полностью загрузиться и начать работать правильно. Если бы AWS сразу же начинал проверять, работает ли оно как надо, и при этом видел, что что-то не так (потому что приложению просто еще нужно время, чтобы завершить все процессы запуска), то AWS маркировал бы его как unhealthy и попытаться перезапустить его или создать новый экземпляр.
Подбор оптимального grace period — задача не самая тривиальная. Мы просто замерили сколько в среднем времени нужно новому приложению, чтобы оно начало отдавать 200-е запросы. Для нашего приложения это менее 8 минут, поэтому мы выставили с запасом значение 500 секунд.
Следует учитывать разные факторы, которые могут увеличить время загрузки приложения — миграции БД или крупные обновления приложения. В таких случаях потребуется увеличить grace period вручную
Конфигурация
Resources: AWSEBAutoScalingGroup: Type: "AWS::AutoScaling::AutoScalingGroup" Properties: HealthCheckType: ELB HealthCheckGracePeriod: 500
2.2 Instance maintenance policy
Также нам нужно разрешить ELB превышать лимит в N инстансов в случае, если один из них не отвечает, но еще не удален из EB. То есть мы хотим разрешить превентивно добавлять 1 инстанс, пока происходит удаление нерабочего. В итоге мы будем одномоментно иметь на 1 инстанс больше, чем разрешено в EB. Для этого в Auto Scaling Group выбираем параметр «Instance maintenance policy» и устанавливаем для него значение Launch before terminating:
Эксперимент
Давайте проверим, как будет вести себя балансировщик, если мы целенаправленно остановим наше приложение на одном инстансе (например командой Stop-Service)
Немного изменим нашу конфигурация для эксперимента — максимальное количество инстансов сделаем равным 2, оставив такие же параметры CPU:
Cтоит упомянуть, что в нашем кейсе также настроен Blue/Green Deployment, но его конфигурация выходит за рамки этой статьи.
Видим рабочие инстансы:
Останавливаем сервис на одном из них:
В течении одной минуты (по нашим настройкам TargetGroups) мы увидим следующую картину:
Инстанс закономерно не прошел HealthCheck и в теперь весь траффик идет на единственный оставшийся инстанс.
И в тоже время (как мы помним, в течении 20 секунд) стартует запуск нового инстанса, даже пока предыдущий не удалён! В результате мы видим 3 инстанса (конечно, рабочих инстансов всегда будет всего 2):
После удаления нерабочего инстанса наша система возвращается в стабильное состояние из двух рабочих машин.
Что можно увидеть и в EB Envorinment Events:
Заключение
На этом всё, надеемся что описание нашего кейса сэкономило вам немало времени и вы узнали больше о настройке Elastic Beanstalk в AWS.
ссылка на оригинал статьи https://habr.com/ru/articles/790892/
Добавить комментарий