AWS: AutoScaling – описание, примеры и Elastic Load Balancer

Автор: | 27/10/2016
 

aws-logo-square-02Введение

AWS Auto Scaling предназначена для того, что бы ваше приложение всегда имело достаточное количество ресурсов для работы, независимо от нагрузки.

Для этого – вы можете создать Auto Scaling Groups, в которой будет указано минимальное и максимальное количество инстансов для работы. Вы так же можете указать политики мастабирования (scaling policies) – и AWS будет запускать и удалять новые EC2 при необходимости.

Подготовка инфрастуктуры

Подробнее – AWS: VPC – EC2 в public и private подсетях, NAT и Internet Gateway и AWS: миграция RTFM, часть #1: ручное создание инфраструктуры – VPC, подсети, IGW, NAT GW, маршруты и EC2.

VPC

Создаём VPC:

$ aws ec2 create-vpc --cidr-block 10.0.0.0/16
{
    "Vpc": {
        "VpcId": "vpc-51e78835", 
        "InstanceTenancy": "default", 
        "State": "pending", 
        "DhcpOptionsId": "dopt-6a91c90f", 
        "CidrBlock": "10.0.0.0/16", 
        "IsDefault": false
    }
}

Добавляем теги:

$ aws ec2 create-tags --resources vpc-51e78835 --tags Key=Name,Value=API-TEST-VPC

Проверяем:

$ aws ec2 describe-vpcs --vpc-ids vpc-51e78835
{
    "Vpcs": [
        {
            "VpcId": "vpc-51e78835", 
            "InstanceTenancy": "default", 
            "Tags": [
                {
                    "Value": "API-TEST-VPC", 
                    "Key": "Name"
                }
            ], 
            "State": "available", 
            "DhcpOptionsId": "dopt-6a91c90f", 
            "CidrBlock": "10.0.0.0/16", 
            "IsDefault": false
        }
    ]
}

Security Group

По vpc-id находим Security Group, которая была создана при добавлении VPC:

$ aws ec2 describe-security-groups --filters Name=vpc-id,Values=vpc-51e78835 --query '[SecurityGroups[*].GroupId]' --output text
sg-5b03d73d

Используя ID группы sg-5b03d73d добавляем два правила – доступ по портам 8080 (со всех IP) и 22 (из сети офиса):

$ aws ec2 authorize-security-group-ingress --group-id sg-5b03d73d --protocol tcp --port 8080 --cidr 0.0.0.0/0
$ aws ec2 authorize-security-group-ingress --group-id sg-5b03d73d --protocol tcp --port 22 --cidr 194.***.***.45/32

Проверяем:

$ aws ec2 describe-security-groups --filters Name=group-id,Values=sg-5b03d73d --output text
SECURITYGROUPS  default VPC security group      sg-5b03d73d     default 947191746595    vpc-51e78835
IPPERMISSIONS   8080    tcp     8080
IPRANGES        0.0.0.0/0
IPPERMISSIONS           -1
USERIDGROUPPAIRS        sg-5b03d73d     947191746595
IPPERMISSIONS   22      tcp     22
IPRANGES        194.***.***.45/32
IPPERMISSIONSEGRESS     -1
IPRANGES        0.0.0.0/0

Добавляем тег Name:

$ aws ec2 create-tags --resources sg-5b03d73d --tags Key=Name,Value=API-TEST-SG

Подсети

В созданной VPC нам требуется две подсети в двух различных Availability Zones, для будущего Elastic Load Balancer. Обе сети будут публичными, с Internet Gateway для маршрутизации трафика от инстансов в них – в Интернет.

Создаём подсеть 10.0.1.0/24 в AZ eu-west-1a:

$ aws ec2 create-subnet --vpc-id vpc-51e78835 --cidr-block 10.0.1.0/24 --availability-zone  eu-west-1a
{
    "Subnet": {
        "VpcId": "vpc-51e78835", 
        "CidrBlock": "10.0.1.0/24", 
        "State": "pending", 
        "AvailabilityZone": "eu-west-1a", 
        "SubnetId": "subnet-937108e5", 
        "AvailableIpAddressCount": 251
    }
}

Создаём подсеть 10.0.2.0/24 в AZ eu-west-1b:

$ aws ec2 create-subnet --vpc-id vpc-51e78835 --cidr-block 10.0.2.0/24 --availability-zone  eu-west-1b
{
    "Subnet": {
        "VpcId": "vpc-51e78835", 
        "CidrBlock": "10.0.2.0/24", 
        "State": "pending", 
        "AvailabilityZone": "eu-west-1b", 
        "SubnetId": "subnet-b4ef62ec", 
        "AvailableIpAddressCount": 251
    }
}

Добавляем теги:

$ aws ec2 create-tags --resources subnet-937108e5 --tags Key=Name,Value=API-TEST-WEST1A
$ aws ec2 create-tags --resources subnet-b4ef62ec --tags Key=Name,Value=API-TEST-WEST1B

Т.к. обе сети будут публичными – разрешаем автоматом назначать Public IP для инстансов, создаваемых в них:

$ aws ec2 modify-subnet-attribute --subnet-id subnet-937108e5 --map-public-ip-on-launch
$ aws ec2 modify-subnet-attribute --subnet-id subnet-b4ef62ec --map-public-ip-on-launch

VPC Internet Gateway

Создаём Internet Gateway для VPC:

$ aws ec2 create-internet-gateway
{
    "InternetGateway": {
        "Tags": [], 
        "InternetGatewayId": "igw-859b70e1", 
        "Attachments": []
    }
}

Подключаем его к VPC:

$ aws ec2 attach-internet-gateway --internet-gateway-id igw-859b70e1 --vpc-id vpc-51e78835

Добавляем теги:

$ aws ec2 create-tags --resources igw-859b70e1 --tags Key=Name,Value=API-TEST-IGW

Route table

Для маршрутизации трафика из созданных подсетей через IGW – создаём новую таблицу маршрутизации в VPC:

$ aws ec2 create-route-table --vpc-id vpc-51e78835
{
    "RouteTable": {
        "Associations": [], 
        "RouteTableId": "rtb-84e6d0e0", 
        "VpcId": "vpc-51e78835", 
        "PropagatingVgws": [], 
        "Tags": [], 
        "Routes": [
            {
                "GatewayId": "local", 
                "DestinationCidrBlock": "10.0.0.0/16", 
                "State": "active", 
                "Origin": "CreateRouteTable"
            }
        ]
    }
}

Добавляем теги:

$ aws ec2 create-tags --resources rtb-84e6d0e0 --tags Key=Name,Value=API-TEST-IGW-ROUTE

Используя route-table-id и gateway-id – добавляем правило маршрутизации в сеть 0.0.0.0/0 (весь Интернет) через Internet Gateway:

$ aws ec2 create-route --route-table-id rtb-84e6d0e0 --destination-cidr-block 0.0.0.0/0 --gateway-id igw-859b70e1
{
    "Return": true
}

Подключаем эту таблицу к созданным ранее подсетям:

$ aws ec2 associate-route-table --route-table-id rtb-84e6d0e0 --subnet-id subnet-937108e5
{
    "AssociationId": "rtbassoc-0a64f36d"
}
$ aws ec2 associate-route-table --route-table-id rtb-84e6d0e0 --subnet-id subnet-b4ef62ec
{
    "AssociationId": "rtbassoc-1164f376"
}

На этом инфрастуктура готова.

Быстро проверим её работу.

Добавляем EC2 инстанс в одной из этих сетей:

$ aws ec2 run-instances --image-id ami-369bd545 --key-name aws-test --count 1 --subnet-id subnet-937108e5 --security-group-ids sg-5b03d73d --instance-type t2.micro
{
    "OwnerId": "947191746595",
    "ReservationId": "r-0b23203e6af7b4f80",
    "Groups": [],
...

Ждём, пока машина проинициализируется:

$ aws ec2 describe-instances --instance-ids i-0e44d3ef01c3bd5c3 --query '[Reservations[*].Instances[*].State]' --output text
16      running

Получаем её Public IP:

$ aws ec2 describe-instances --instance-ids i-0e44d3ef01c3bd5c3 --query '[Reservations[*].Instances[*].NetworkInterfaces[*].Association.PublicIp]' --output text
52.212.239.28

Проверяем сеть:

$ ssh [email protected] -i .ssh/aws-test.pem 
The authenticity of host '52.212.239.28 (52.212.239.28)' can't be established.
...
ubuntu@ip-10-0-1-166:~$ ping -c 1 ya.ru
PING ya.ru (93.158.134.3) 56(84) bytes of data.
64 bytes from www.yandex.ru (93.158.134.3): icmp_seq=1 ttl=47 time=61.9 ms

--- ya.ru ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 61.931/61.931/61.931/0.000 ms

Удаляем машину:

$ aws ec2 terminate-instances --instance-ids i-0e44d3ef01c3bd5c3
{
    "TerminatingInstances": [
        {
            "InstanceId": "i-0e44d3ef01c3bd5c3", 
            "CurrentState": {
                "Code": 32, 
                "Name": "shutting-down"
            }, 
            "PreviousState": {
                "Code": 16, 
                "Name": "running"
            }
        }
    ]
}

Инфрастуктура готова.

Создание Auto Scaling

Компоненты Auto Scaling

В Auto Scaling входят три основных компонента:

  1. Launch Configuration: группа использует launch configuration как шаблон для EC2 инстансов в ней. Когда вы создаёте launch configuration – вы можете указать AMI, тип инстансов, ключ, группы безопасности и т.д. Подробнее –  Launch Configurations.
  2. Auto Scaling Group: ваши EC2 собраны в одну группу, являя собой единый логический юнит для масштабирования и управления. При создании группы – вы указываете минимальное, максимальное и желаемое количество инстансов в ней. Подробнее – Auto Scaling Groups.
  3. Scaling plans: в scaling plan  описывается как именно должно выполняться масшабирование. Например – вы можете создать scaling plan, основанный на возникновении определённых условий (динамическое масштабирование), либо – выполнять изменения по расписанию. Подробнее – Scaling Plans.

Создание Launch Configuration

Launch configuration определяет тип инстанса, его AMI для запуска и т.д.

Используя create-launch-configuration – создаём:

$ aws autoscaling create-launch-configuration --launch-configuration-name API-TEST --image-id ami-369bd545 --instance-type t2.micro --key-name aws-test --security-groups sg-5b03d73d --user-data file://api_start.sh

В userdata передаётся скрипт api_start.sh для запуска Docker контейнеров из AMI ami-369bd545, который был собран с помощью Packer.

Примечание: во избежание ошибки  “The parameter groupName cannot be used with the parameter subnet.” при создании Autto Scale group – в параметре --security-groups используйте ID группы (sg-5b03d73d), и не имена (aws-test).

Создание Auto Scaling Group

С помощью create-auto-scaling-group создаём Auto Scaling группу, в которой будут создаваться только 2 EC2 в двух подсетях в двух Availability Zones, без Elastic Load Balancer и без изменения количества инстансов в группе.

Можно передать либо две подсети, либо две AZ.

Так как у нас имеются созданные подсети – используем их:

$ aws autoscaling create-auto-scaling-group --auto-scaling-group-name API-TEST-ASG --launch-configuration-name API-TEST --min-size 2 --max-size 2 --vpc-zone-identifier subnet-937108e5,subnet-b4ef62ec

asg_1

Проверяем:

$ aws autoscaling describe-auto-scaling-groups --auto-scaling-group-names API-TEST-ASG
{
    "AutoScalingGroups": [
        {
            "AutoScalingGroupARN": "arn:aws:autoscaling:eu-west-1:947191746595:autoScalingGroup:942903e4-d7d6-4a6f-a24a-890380609bf8:autoScalingGroupName/API-TEST-ASG", 
            "TargetGroupARNs": [], 
            "SuspendedProcesses": [], 
            "DesiredCapacity": 2, 
            "Tags": [], 
            "EnabledMetrics": [], 
            "LoadBalancerNames": [], 
            "AutoScalingGroupName": "API-TEST-ASG", 
            "DefaultCooldown": 300, 
            "MinSize": 2, 
            "Instances": [
                {
                    "ProtectedFromScaleIn": false, 
                    "AvailabilityZone": "eu-west-1b", 
                    "InstanceId": "i-04b3c02b8255d8a02", 
                    "HealthStatus": "Healthy", 
                    "LifecycleState": "InService", 
                    "LaunchConfigurationName": "API-TEST"
                }, 
                {
                    "ProtectedFromScaleIn": false, 
                    "AvailabilityZone": "eu-west-1a", 
                    "InstanceId": "i-06dd044c42b066d8e", 
                    "HealthStatus": "Healthy", 
                    "LifecycleState": "InService", 
                    "LaunchConfigurationName": "API-TEST"
                }
            ], 
            "MaxSize": 2, 
            "VPCZoneIdentifier": "subnet-937108e5,subnet-b4ef62ec", 
            "HealthCheckGracePeriod": 0, 
            "TerminationPolicies": [
                "Default"
            ], 
            "LaunchConfigurationName": "API-TEST", 
            "CreatedTime": "2016-10-26T10:41:26.496Z", 
            "AvailabilityZones": [
                "eu-west-1b", 
                "eu-west-1a"
            ], 
            "HealthCheckType": "EC2", 
            "NewInstancesProtectedFromScaleIn": false
        }
    ]
}

Обращаем внимание на инстансы и их зоны доступности:

...
            "Instances": [
                {
                    "ProtectedFromScaleIn": false, 
                    "AvailabilityZone": "eu-west-1b", 
                    "InstanceId": "i-04b3c02b8255d8a02", 
                    "HealthStatus": "Healthy", 
                    "LifecycleState": "InService", 
                    "LaunchConfigurationName": "API-TEST"
                }, 
                {
                    "ProtectedFromScaleIn": false, 
                    "AvailabilityZone": "eu-west-1a", 
                    "InstanceId": "i-06dd044c42b066d8e", 
                    "HealthStatus": "Healthy", 
                    "LifecycleState": "InService", 
                    "LaunchConfigurationName": "API-TEST"
                }
            ],
...

Проверяем подсети:

$ aws ec2 describe-instances --instance-ids i-04b3c02b8255d8a02 i-06dd044c42b066d8e | grep Subnet
                    "SubnetId": "subnet-b4ef62ec", 
                            "SubnetId": "subnet-b4ef62ec", 
                    "SubnetId": "subnet-937108e5", 
                            "SubnetId": "subnet-937108e5", 

Создание Auto Scaling Group с  Dynamic Scaling Policy

Для того, что бы изменять количество инстансов в зависимости от различных параметров (далее используем CPU Load) – требуется добавить Scaling Policy.

Scaling Policy могут быть трёх типов:

  • Manual Scaling: при необходимости – вы можете вручную измененить кол-во инстансов.
  • Scheduled Scaling: изменение по расписанию. Например, если пик нагрузки приходится на 18.00 – вы можете увеличивать кол-во машин между 17.00 и 19.00.
  • Dynamic Scaling: то, что будем использовать.

Для Dynamic Scaling – требуется создать CloudWatch Alarm, которые будут отслеживать определённые условия (нагрузка CPU, например) и в случае превышения порога – отправлять сигнал Auto Scale Group, которая на основании Scale Policy будет увеличивать или уменьшать количество запущенных инстансов.

Масштабирование может быть один из трёх типов:

  • ChangeInCapacity: увеличение или уменьшение размера Auto Scale Group на указанное кол-во инстансов. Например – у вас есть 3 машины, а в --scaling-adjustment указывается 5. В таком случае, после применения политики у вас будет 8 машин.
  • ExactCapacity: измнение группы до указанного кол-ва машин. Например, у вас есть 3 машины, и в --scaling-adjustment указывается 5. В таком случае, после вызова политики у вас будет 5 машин.
  • PercentChangeInCapacity: изменение количества машин на указанный %. Например – у вас есть 10 машин, и --scaling-adjustment указывается 10% – то в результате применения политки у вас будет 10 штук + 10% = 11 машин.

Мы используем ChangeInCapacity.

С помощью put-scaling-policy создаём политику для увеличения машин:

$ aws autoscaling put-scaling-policy --auto-scaling-group-name API-TEST-ASG --policy-name scale-up --scaling-adjustment 1 --adjustment-type ChangeInCapacity --cooldown 300
{
    "PolicyARN": "arn:aws:autoscaling:eu-west-1:947191746595:scalingPolicy:bd847076-2471-426f-a929-b3a6e2aca731:autoScalingGroupName/API-TEST-ASG:policyName/scale-up"
}

И вторую – для уменьшения:

$ aws autoscaling put-scaling-policy --auto-scaling-group-name API-TEST-ASG --policy-name scale-down --scaling-adjustment -1 --adjustment-type ChangeInCapacity --cooldown 300
{
    "PolicyARN": "arn:aws:autoscaling:eu-west-1:947191746595:scalingPolicy:a9ac5c6a-65ea-444c-af97-0431124d3315:autoScalingGroupName/API-TEST-ASG:policyName/scale-down"
}

asg_2

Следующим шагом – требуется добавить CloudWatch Alarm, который будет вызывать scaling-policy.

Используем put-metric-alarm. Вся команда будет выглядеть так:

aws cloudwatch put-metric-alarm --alarm-name API-TEST-ASG-scale-up \
--metric-name CPUUtilization \
--namespace "AWS/EC2" \
--period 300 \
--evaluation-periods 1 \
--threshold 5 \
--statistic Average \
--comparison-operator GreaterThanThreshold \
--alarm-actions arn:aws:autoscaling:eu-west-1:947191746595:scalingPolicy:bd847076-2471-426f-a929-b3a6e2aca731:autoScalingGroupName/API-TEST-ASG:policyName/scale-up \
--dimensions Name=AutoScalingGroupName,Value=API-TEST-ASG

Выполняем её:

$ aws cloudwatch put-metric-alarm --alarm-name API-TEST-ASG-scale-up \
> --metric-name CPUUtilization \
> --namespace "AWS/EC2" \
> --period 300 \
> --evaluation-periods 1 \
> --threshold 5 \
> --statistic Average \
> --comparison-operator GreaterThanThreshold \
> --alarm-actions arn:aws:autoscaling:eu-west-1:947191746595:scalingPolicy:bd847076-2471-426f-a929-b3a6e2aca731:autoScalingGroupName/API-TEST-ASG:policyName/scale-up \
> --dimensions Name=AutoScalingGroupName,Value=API-TEST-ASG

Аналогично – добавляем Alarm, который будет отслеживать уменьшение использования CPU до < 5 LA, и вызывать scaling-policy scale-down:

aws cloudwatch put-metric-alarm --alarm-name API-TEST-ASG-scale-down \
--metric-name CPUUtilization \
--namespace "AWS/EC2" \
--period 300 \
--evaluation-periods 1 \
--threshold 3 \
--statistic Average \
--comparison-operator LessThanThreshold \
--alarm-actions arn:aws:autoscaling:eu-west-1:947191746595:scalingPolicy:a9ac5c6a-65ea-444c-af97-0431124d3315:autoScalingGroupName/API-TEST-ASG:policyName/scale-down \
--dimensions Name=AutoScalingGroupName,Value=API-TEST-ASG

Выполняем:

$ aws cloudwatch put-metric-alarm --alarm-name API-TEST-ASG-scale-down \
> --metric-name CPUUtilization \
> --namespace "AWS/EC2" \
> --period 300 \
> --evaluation-periods 1 \
> --threshold 3 \
> --statistic Average \
> --comparison-operator LessThanThreshold \
> --alarm-actions arn:aws:autoscaling:eu-west-1:947191746595:scalingPolicy:a9ac5c6a-65ea-444c-af97-0431124d3315:autoScalingGroupName/API-TEST-ASG:policyName/scale-down \
> --dimensions Name=AutoScalingGroupName,Value=API-TEST-ASG

Проверяем:

$ aws cloudwatch describe-alarms --alarm-names API-TEST-ASG-scale-up API-TEST-ASG-scale-down
{
    "MetricAlarms": [
        {
            "EvaluationPeriods": 1, 
            "AlarmArn": "arn:aws:cloudwatch:eu-west-1:947191746595:alarm:API-TEST-ASG-scale-down", 
            "StateUpdatedTimestamp": "2016-10-26T11:28:32.696Z", 
            "AlarmConfigurationUpdatedTimestamp": "2016-10-26T11:28:32.137Z", 
            "ComparisonOperator": "LessThanThreshold", 
            "AlarmActions": [
                "arn:aws:autoscaling:eu-west-1:947191746595:scalingPolicy:a9ac5c6a-65ea-444c-af97-0431124d3315:autoScalingGroupName/API-TEST-ASG:policyName/scale-down"
            ], 
            "Namespace": "AWS/EC2", 
            "StateReasonData": "{\"version\":\"1.0\",\"queryDate\":\"2016-10-26T11:28:32.687+0000\",\"startDate\":\"2016-10-26T11:23:00.000+0000\",\"statistic\":\"Average\",\"period\":300,\"recentDatapoints\":[0.03777777777777778],\"threshold\":3.0}", 
            "Period": 300, 
            "StateValue": "ALARM", 
            "Threshold": 3.0, 
            "AlarmName": "API-TEST-ASG-scale-down", 
            "Dimensions": [
                {
                    "Name": "AutoScalingGroupName", 
                    "Value": "API-TEST-ASG"
                }
            ], 
            "Statistic": "Average", 
            "StateReason": "Threshold Crossed: 1 datapoint (0.03777777777777778) was less than the threshold (3.0).", 
            "InsufficientDataActions": [], 
            "OKActions": [], 
            "ActionsEnabled": true, 
            "MetricName": "CPUUtilization"
        }, 
        {
            "EvaluationPeriods": 1, 
            "AlarmArn": "arn:aws:cloudwatch:eu-west-1:947191746595:alarm:API-TEST-ASG-scale-up", 
            "StateUpdatedTimestamp": "2016-10-26T11:23:51.211Z", 
            "AlarmConfigurationUpdatedTimestamp": "2016-10-26T11:23:50.606Z", 
            "ComparisonOperator": "GreaterThanThreshold", 
            "AlarmActions": [
                "arn:aws:autoscaling:eu-west-1:947191746595:scalingPolicy:bd847076-2471-426f-a929-b3a6e2aca731:autoScalingGroupName/API-TEST-ASG:policyName/scale-up"
            ], 
            "Namespace": "AWS/EC2", 
            "StateReasonData": "{\"version\":\"1.0\",\"queryDate\":\"2016-10-26T11:23:51.201+0000\",\"startDate\":\"2016-10-26T11:18:00.000+0000\",\"statistic\":\"Average\",\"period\":300,\"recentDatapoints\":[0.051000000000000004],\"threshold\":5.0}", 
            "Period": 300, 
            "StateValue": "OK", 
            "Threshold": 5.0, 
            "AlarmName": "API-TEST-ASG-scale-up", 
            "Dimensions": [
                {
                    "Name": "AutoScalingGroupName", 
                    "Value": "API-TEST-ASG"
                }
            ], 
            "Statistic": "Average", 
            "StateReason": "Threshold Crossed: 1 datapoint (0.051000000000000004) was not greater than the threshold (5.0).", 
            "InsufficientDataActions": [], 
            "OKActions": [], 
            "ActionsEnabled": true, 
            "MetricName": "CPUUtilization"
        }
    ]
}

asg_3

Обновляем параметры созданной ранее Auto Scale group, в которой мы укаазывали max-size 2, увеличиваем до 5:

$ aws autoscaling update-auto-scaling-group --auto-scaling-group-name API-TEST-ASG --max-size 5

Проверяем.

Подключаемся к одному из инстансов, устанавливаем утилиту stress, и генерируем нагрузку

$ ssh [email protected] -i .ssh/aws-test.pem
...
$ sudo -s
# apt-get update && apt-get install stress
# stress --cpu 10 --timeout 400 &
[1] 2413

Проверяем запущенные “воркеры”:

# ps aux | grep stress
root      2449  0.0  0.0   7304   624 pts/0    S    11:42   0:00 stress --cpu 10 --timeout 400
root      2450 10.1  0.0   7304    96 pts/0    R    11:42   0:02 stress --cpu 10 --timeout 400
root      2451 10.1  0.0   7304    96 pts/0    R    11:42   0:02 stress --cpu 10 --timeout 400
root      2452 10.1  0.0   7304    96 pts/0    R    11:42   0:02 stress --cpu 10 --timeout 400
root      2453 10.1  0.0   7304    96 pts/0    R    11:42   0:02 stress --cpu 10 --timeout 400
root      2454 10.1  0.0   7304    96 pts/0    R    11:42   0:02 stress --cpu 10 --timeout 400
root      2455 10.1  0.0   7304    96 pts/0    R    11:42   0:02 stress --cpu 10 --timeout 400
root      2456 10.1  0.0   7304    96 pts/0    R    11:42   0:02 stress --cpu 10 --timeout 400
root      2457 10.1  0.0   7304    96 pts/0    R    11:42   0:02 stress --cpu 10 --timeout 400
root      2458 10.1  0.0   7304    96 pts/0    R    11:42   0:02 stress --cpu 10 --timeout 400
root      2459 10.1  0.0   7304    96 pts/0    R    11:42   0:02 stress --cpu 10 --timeout 400

Проверяем Load Average:

# uptime 
 11:42:59 up  1:00,  1 user,  load average: 5.95, 1.74, 0.64

Проверяем кол-во инстансов:

$ aws autoscaling describe-auto-scaling-groups --auto-scaling-group-names API-TEST-ASG --query '[AutoScalingGroups[*].DesiredCapacity]' --output text
3

asg_4

Было 2 – стало три.

После окончания работы stress – их снова будет два.

Auto Scaling и Elastic load Balancer

ELB является “точкой входа” для всех инстансов в его Target Group, и может быть подключен к Auto Scaling для перенаправления трафика к группе EC2 инстансов, распределяя нагрузку и исключая “упавшие” инстансы. Кроме того – ELB можно использовать для реализации Blue/Green деплоя.

Подробнее про создание и настройку ELB – в посте AWS: Application Load Balancer – настройка.

Создаём ELB:

$ aws elbv2 create-load-balancer --name API-ASG-ELB-TEST --subnets subnet-937108e5 subnet-b4ef62ec --security-groups sg-5b03d73d --scheme internet-facing
{
    "LoadBalancers": [
        {
            "VpcId": "vpc-51e78835",
            "LoadBalancerArn": "arn:aws:elasticloadbalancing:eu-west-1:947191746595:loadbalancer/app/API-ASG-ELB-TEST/3ab3f64400545d4b",
            "State": {
                "Code": "provisioning"                                                                                                                                                                                                                                         
            },
            "DNSName": "API-ASG-ELB-TEST-1785045986.eu-west-1.elb.amazonaws.com",
            "SecurityGroups": [
                "sg-5b03d73d"
            ],
            "LoadBalancerName": "API-ASG-ELB-TEST",
            "CreatedTime": "2016-10-26T13:45:32.120Z",
            "Scheme": "internet-facing",
            "Type": "application",
            "CanonicalHostedZoneId": "Z32O12XQLNTSW2",
            "AvailabilityZones": [
                {
                    "SubnetId": "subnet-937108e5",
                    "ZoneName": "eu-west-1a"
                },
                {                                                                                                                                                                                                                                                              
                    "SubnetId": "subnet-b4ef62ec",
                    "ZoneName": "eu-west-1b"
                }
            ]
        }
    ]
}

Добавляем теги:

$ aws ec2 create-tags --resources sg-5b03d73d --tags Key=Name,Value=API-ASG-ELB-TEST

Создаём Target Group, в которую Auto Scaling потом будет автоматически добавлять инстансы:

$ aws elbv2 create-target-group --name API-ASG-TARGETS --protocol HTTP --port 8080 --vpc-id vpc-51e78835 
{
    "TargetGroups": [
        {
            "HealthCheckPath": "/", 
            "HealthCheckIntervalSeconds": 30, 
            "VpcId": "vpc-51e78835", 
            "Protocol": "HTTP", 
            "HealthCheckTimeoutSeconds": 5, 
            "HealthCheckProtocol": "HTTP", 
            "UnhealthyThresholdCount": 2, 
            "HealthyThresholdCount": 5, 
            "TargetGroupArn": "arn:aws:elasticloadbalancing:eu-west-1:947191746595:targetgroup/API-ASG-TARGETS/9cd3f8157c9cf7eb", 
            "Matcher": {
                "HttpCode": "200"
            }, 
            "HealthCheckPort": "traffic-port", 
            "Port": 8080, 
            "TargetGroupName": "API-ASG-TARGETS"
        }
    ]
}

Добавляем Listener, который будет “слушать” порт 8080 и распредялть трафик по инстансам в Target group:

$ aws elbv2 create-listener --load-balancer-arn arn:aws:elasticloadbalancing:eu-west-1:947191746595:loadbalancer/app/API-ASG-ELB-TEST/3ab3f64400545d4b --protocol HTTP --port 8080 --default-actions Type=forward,TargetGroupArn=arn:aws:elasticloadbalancing:eu-west-1:947191746595:targetgroup/API-ASG-TARGETS/9cd3f8157c9cf7eb
{
    "Listeners": [
        {
            "Protocol": "HTTP", 
            "DefaultActions": [
                {
                    "TargetGroupArn": "arn:aws:elasticloadbalancing:eu-west-1:947191746595:targetgroup/API-ASG-TARGETS/9cd3f8157c9cf7eb", 
                    "Type": "forward"
                }
            ], 
            "LoadBalancerArn": "arn:aws:elasticloadbalancing:eu-west-1:947191746595:loadbalancer/app/API-ASG-ELB-TEST/3ab3f64400545d4b", 
            "Port": 8080, 
            "ListenerArn": "arn:aws:elasticloadbalancing:eu-west-1:947191746595:listener/app/API-ASG-ELB-TEST/3ab3f64400545d4b/93af3d3d3da3de60"
        }
    ]
}

asg_5

С помощью attach-load-balancer-target-groups (для Application Load Balncer, для Classic – используйте attach-load-balancers) – подключаем созданную Target Group нашего ELB к Auto Scale:

$ aws autoscaling attach-load-balancer-target-groups --auto-scaling-group-name API-TEST-ASG --target-group-arns arn:aws:elasticloadbalancing:eu-west-1:947191746595:targetgroup/API-ASG-TARGETS/9cd3f8157c9cf7eb

И проверяем через URL Load Balacner-а:

$ curl API-ASG-ELB-TEST-1785045986.eu-west-1.elb.amazonaws.com:8080
Test API server v1

Почитать по теме

Auto Scaling (подробное описание)

Use Auto Scaling for Everything Possible

Implementing Blue-Green Deployments with AWS (не совсем по теме – но полезно)