

# Creación de una aplicación con escalado y equilibrio de carga
<a name="walkthrough-autoscaling"></a>

Para este tutorial, creará una pila que lo ayudará a configurar una aplicación con escalado y equilibrio de carga. El tutorial proporciona una plantilla de ejemplo que utilizará para crear la pila. La plantilla de ejemplo proporciona un grupo de escalado automático, un equilibrador de carga de aplicación, grupos de seguridad que controlan el tráfico al equilibrador de carga y al grupo de escalado automático y una configuración de notificaciones de Amazon SNS para publicar notificaciones sobre las actividades de escalado. 

Esta plantilla crea una o varias instancias de Amazon EC2 y un equilibrador de carga de aplicación. Se le facturarán los recursos de AWS que utilice si crea una pila a partir de esta plantilla. 

## Plantilla de pila completa
<a name="example-templates-autoscaling-full-stack-template"></a>

Empecemos por la plantilla.

**YAML**

```
AWSTemplateFormatVersion: 2010-09-09
Parameters:
  InstanceType:
    Description: The EC2 instance type
    Type: String
    Default: t3.micro
    AllowedValues:
      - t3.micro
      - t3.small
      - t3.medium
  KeyName:
    Description: Name of an existing EC2 key pair to allow SSH access to the instances
    Type: AWS::EC2::KeyPair::KeyName
  LatestAmiId:
    Description: The latest Amazon Linux 2 AMI from the Parameter Store
    Type: AWS::SSM::Parameter::Value<AWS::EC2::Image::Id>
    Default: '/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2'
  OperatorEmail:
    Description: The email address to notify when there are any scaling activities
    Type: String
  SSHLocation:
    Description: The IP address range that can be used to SSH to the EC2 instances
    Type: String
    MinLength: 9
    MaxLength: 18
    Default: 0.0.0.0/0
    ConstraintDescription: must be a valid IP CIDR range of the form x.x.x.x/x.
  Subnets:
    Type: 'List<AWS::EC2::Subnet::Id>'
    Description: At least two public subnets in different Availability Zones in the selected VPC
  VPC:
    Type: AWS::EC2::VPC::Id
    Description: A virtual private cloud (VPC) that enables resources in public subnets to connect to the internet
Resources:
  ELBSecurityGroup:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupDescription: ELB Security Group
      VpcId: !Ref VPC
      SecurityGroupIngress:
      - IpProtocol: tcp
        FromPort: 80
        ToPort: 80
        CidrIp: 0.0.0.0/0
  EC2SecurityGroup:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupDescription: EC2 Security Group
      VpcId: !Ref VPC
      SecurityGroupIngress:
      - IpProtocol: tcp
        FromPort: 80
        ToPort: 80
        SourceSecurityGroupId:
          Fn::GetAtt:
          - ELBSecurityGroup
          - GroupId
      - IpProtocol: tcp
        FromPort: 22
        ToPort: 22
        CidrIp: !Ref SSHLocation
  EC2TargetGroup:
    Type: AWS::ElasticLoadBalancingV2::TargetGroup
    Properties:
      HealthCheckIntervalSeconds: 30
      HealthCheckProtocol: HTTP
      HealthCheckTimeoutSeconds: 15
      HealthyThresholdCount: 5
      Matcher:
        HttpCode: '200'
      Name: EC2TargetGroup
      Port: 80
      Protocol: HTTP
      TargetGroupAttributes:
      - Key: deregistration_delay.timeout_seconds
        Value: '20'
      UnhealthyThresholdCount: 3
      VpcId: !Ref VPC
  ALBListener:
    Type: AWS::ElasticLoadBalancingV2::Listener
    Properties:
      DefaultActions:
        - Type: forward
          TargetGroupArn: !Ref EC2TargetGroup
      LoadBalancerArn: !Ref ApplicationLoadBalancer
      Port: 80
      Protocol: HTTP
  ApplicationLoadBalancer:
    Type: AWS::ElasticLoadBalancingV2::LoadBalancer
    Properties:
      Scheme: internet-facing
      Subnets: !Ref Subnets
      SecurityGroups:
        - !GetAtt ELBSecurityGroup.GroupId
  LaunchTemplate:
    Type: AWS::EC2::LaunchTemplate
    Properties: 
      LaunchTemplateName: !Sub ${AWS::StackName}-launch-template
      LaunchTemplateData:
        ImageId: !Ref LatestAmiId
        InstanceType: !Ref InstanceType
        KeyName: !Ref KeyName
        SecurityGroupIds: 
          - !Ref EC2SecurityGroup
        UserData:
          Fn::Base64: !Sub |
            #!/bin/bash
            yum update -y
            yum install -y httpd
            systemctl start httpd
            systemctl enable httpd
            echo "<h1>Hello World!</h1>" > /var/www/html/index.html
  NotificationTopic:
    Type: AWS::SNS::Topic
    Properties:
      Subscription:
        - Endpoint: !Ref OperatorEmail
          Protocol: email
  WebServerGroup:
    Type: AWS::AutoScaling::AutoScalingGroup
    Properties:
      LaunchTemplate:
        LaunchTemplateId: !Ref LaunchTemplate
        Version: !GetAtt LaunchTemplate.LatestVersionNumber
      MaxSize: '3'
      MinSize: '1'
      NotificationConfigurations:
        - TopicARN: !Ref NotificationTopic
          NotificationTypes: ['autoscaling:EC2_INSTANCE_LAUNCH', 'autoscaling:EC2_INSTANCE_LAUNCH_ERROR', 'autoscaling:EC2_INSTANCE_TERMINATE', 'autoscaling:EC2_INSTANCE_TERMINATE_ERROR']
      TargetGroupARNs:
        - !Ref EC2TargetGroup
      VPCZoneIdentifier: !Ref Subnets
```

**JSON**

```
{
  "AWSTemplateFormatVersion":"2010-09-09",
  "Parameters":{
    "InstanceType":{
      "Description":"The EC2 instance type",
      "Type":"String",
      "Default":"t3.micro",
      "AllowedValues":[
        "t3.micro",
        "t3.small",
        "t3.medium"
      ]
    },
    "KeyName":{
      "Description":"Name of an existing EC2 key pair to allow SSH access to the instances",
      "Type":"AWS::EC2::KeyPair::KeyName"
    },
    "LatestAmiId":{
      "Description":"The latest Amazon Linux 2 AMI from the Parameter Store",
      "Type":"AWS::SSM::Parameter::Value<AWS::EC2::Image::Id>",
      "Default":"/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2"
    },
    "OperatorEmail":{
      "Description":"The email address to notify when there are any scaling activities",
      "Type":"String"
    },
    "SSHLocation":{
      "Description":"The IP address range that can be used to SSH to the EC2 instances",
      "Type":"String",
      "MinLength":9,
      "MaxLength":18,
      "Default":"0.0.0.0/0",
      "ConstraintDescription":"Must be a valid IP CIDR range of the form x.x.x.x/x."
    },
    "Subnets":{
      "Type":"List<AWS::EC2::Subnet::Id>",
      "Description":"At least two public subnets in different Availability Zones in the selected VPC"
    },
    "VPC":{
      "Type":"AWS::EC2::VPC::Id",
      "Description":"A virtual private cloud (VPC) that enables resources in public subnets to connect to the internet"
    }
  },
  "Resources":{
    "ELBSecurityGroup":{
      "Type":"AWS::EC2::SecurityGroup",
      "Properties":{
        "GroupDescription":"ELB Security Group",
        "VpcId":{
          "Ref":"VPC"
        },
        "SecurityGroupIngress":[
          {
            "IpProtocol":"tcp",
            "FromPort":80,
            "ToPort":80,
            "CidrIp":"0.0.0.0/0"
          }
        ]
      }
    },
    "EC2SecurityGroup":{
      "Type":"AWS::EC2::SecurityGroup",
      "Properties":{
        "GroupDescription":"EC2 Security Group",
        "VpcId":{
          "Ref":"VPC"
        },
        "SecurityGroupIngress":[
          {
            "IpProtocol":"tcp",
            "FromPort":80,
            "ToPort":80,
            "SourceSecurityGroupId":{
              "Fn::GetAtt":[
                "ELBSecurityGroup",
                "GroupId"
              ]
            }
          },
          {
            "IpProtocol":"tcp",
            "FromPort":22,
            "ToPort":22,
            "CidrIp":{
              "Ref":"SSHLocation"
            }
          }
        ]
      }
    },
    "EC2TargetGroup":{
      "Type":"AWS::ElasticLoadBalancingV2::TargetGroup",
      "Properties":{
        "HealthCheckIntervalSeconds":30,
        "HealthCheckProtocol":"HTTP",
        "HealthCheckTimeoutSeconds":15,
        "HealthyThresholdCount":5,
        "Matcher":{
          "HttpCode":"200"
        },
        "Name":"EC2TargetGroup",
        "Port":80,
        "Protocol":"HTTP",
        "TargetGroupAttributes":[
          {
            "Key":"deregistration_delay.timeout_seconds",
            "Value":"20"
          }
        ],
        "UnhealthyThresholdCount":3,
        "VpcId":{
          "Ref":"VPC"
        }
      }
    },
    "ALBListener":{
      "Type":"AWS::ElasticLoadBalancingV2::Listener",
      "Properties":{
        "DefaultActions":[
          {
            "Type":"forward",
            "TargetGroupArn":{
              "Ref":"EC2TargetGroup"
            }
          }
        ],
        "LoadBalancerArn":{
          "Ref":"ApplicationLoadBalancer"
        },
        "Port":80,
        "Protocol":"HTTP"
      }
    },
    "ApplicationLoadBalancer":{
      "Type":"AWS::ElasticLoadBalancingV2::LoadBalancer",
      "Properties":{
        "Scheme":"internet-facing",
        "Subnets":{
          "Ref":"Subnets"
        },
        "SecurityGroups":[
          {
            "Fn::GetAtt":[
              "ELBSecurityGroup",
              "GroupId"
            ]
          }
        ]
      }
    },
    "LaunchTemplate":{
      "Type":"AWS::EC2::LaunchTemplate",
      "Properties":{
        "LaunchTemplateName":{
          "Fn::Sub":"${AWS::StackName}-launch-template"
        },
        "LaunchTemplateData":{
          "ImageId":{
            "Ref":"LatestAmiId"
          },
          "InstanceType":{
            "Ref":"InstanceType"
          },
          "KeyName":{
            "Ref":"KeyName"
          },
          "SecurityGroupIds":[
            {
              "Ref":"EC2SecurityGroup"
            }
          ],
          "UserData":{
            "Fn::Base64":{
              "Fn::Join":[
                "",
                [
                  "#!/bin/bash\n",
                  "yum update -y\n",
                  "yum install -y httpd\n",
                  "systemctl start httpd\n",
                  "systemctl enable httpd\n",
                  "echo \"<h1>Hello World!</h1>\" > /var/www/html/index.html"
                ]
              ]
            }
          }
        }
      }
    },
    "NotificationTopic":{
      "Type":"AWS::SNS::Topic",
      "Properties":{
        "Subscription":[
          {
            "Endpoint":{
              "Ref":"OperatorEmail"
            },
            "Protocol":"email"
          }
        ]
      }
    },
    "WebServerGroup":{
      "Type":"AWS::AutoScaling::AutoScalingGroup",
      "Properties":{
        "LaunchTemplate":{
          "LaunchTemplateId":{
            "Ref":"LaunchTemplate"
          },
          "Version":{
            "Fn::GetAtt":[
              "LaunchTemplate",
              "LatestVersionNumber"
            ]
          }
        },
        "MaxSize":"3",
        "MinSize":"1",
        "NotificationConfigurations":[
          {
            "TopicARN":{
              "Ref":"NotificationTopic"
            },
            "NotificationTypes":[
              "autoscaling:EC2_INSTANCE_LAUNCH",
              "autoscaling:EC2_INSTANCE_LAUNCH_ERROR",
              "autoscaling:EC2_INSTANCE_TERMINATE",
              "autoscaling:EC2_INSTANCE_TERMINATE_ERROR"
            ]
          }
        ],
        "TargetGroupARNs":[
          {
            "Ref":"EC2TargetGroup"
          }
        ],
        "VPCZoneIdentifier":{
          "Ref":"Subnets"
        }
      }
    }
  }
}
```

## Tutorial de plantilla
<a name="example-templates-autoscaling-description"></a>

La primera parte de esta plantilla especifica los `Parameters`. A cada parámetro se le debe asignar un valor en tiempo de ejecución para que CloudFormation aprovisione correctamente la pila. Los recursos especificados más adelante en la plantilla hacen referencia a estos valores y utilizan los datos.
+ `InstanceType`: el tipo de instancia de EC2 que Amazon EC2 Auto Scaling aprovisiona. Si no se especifica, se usa el valor predeterminado de `t3.micro`.
+ `KeyName`: un par de claves de EC2 existente para permitir el acceso SSH a las instancias.
+ `LatestAmiId`: el ID de imagen de máquina de Amazon (AMI) para las instancias. Si no se especifica, las instancias se lanzan con una AMI de Amazon Linux 2, mediante un parámetro AWS Systems Manager público mantenido por AWS. Para obtener más información, consulte [Buscar parámetros públicos](https://docs.aws.amazon.com/systems-manager/latest/userguide/parameter-store-finding-public-parameters.html) en la *Guía del usuario de AWS Systems Manager*.
+ `OperatorEmail`: la dirección de correo electrónico a la que desea enviar notificaciones de actividad de escalado.
+ `SSHLocation`: el intervalo de direcciones IP que se puede usar para enviar SSH a las instancias.
+ `Subnets`: al menos dos subredes en diferentes zonas de disponibilidad. 
+ `VPC`: una nube privada virtual (VPC) en su cuenta que permite a los recursos de subredes públicas conectarse a Internet. 
**nota**  
Puede usar la VPC predeterminada y las subredes predeterminadas para permitir que las instancias accedan a Internet. Si utiliza supropia VPC, asegúrese de que tiene una subred asignada a cada zona de disponibilidad de la región de en la que esté trabajando. Como mínimo, debe tener dos subredes públicas disponibles para crear el balanceador de carga.

La siguiente parte de esta plantilla especifica los `Resources`. Esta sección especifica los recursos de la pila y sus propiedades.

[https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-ec2-securitygroup.html](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-ec2-securitygroup.html) de recurso de `ELBSecurityGroup` 
+ `SecurityGroupIngress` contiene una regla de entrada TCP que permite el acceso desde *todas las direcciones IP* (“CidrIp”: “0.0.0.0/0”) en el puerto 80.

[https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-ec2-securitygroup.html](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-ec2-securitygroup.html) de recurso de `EC2SecurityGroup` 
+ `SecurityGroupIngress` contiene dos reglas de entrada: 1) una regla de entrada TCP que permite el acceso SSH (puerto 22) desde el rango de direcciones IP que usted proporciona para el parámetro de entrada de `SSHLocation` y 2) una regla de entrada TCP que permite el acceso desde el equilibrador de carga al especificar el grupo de seguridad del equilibrador de carga. La función [GetAtt](resources-section-structure.md#resource-properties-getatt) se usa para obtener el ID del grupo de seguridad con el nombre lógico `ELBSecurityGroup`.

Recurso `EC2TargetGroup` de [AWS::ElasticLoadBalancingV2::TargetGroup](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-elasticloadbalancingv2-targetgroup.html)
+ `Port`, `Protocol` y `HealthCheckProtocol` especifican el puerto de instancia de EC2 (80) y el protocolo (HTTP) a los que el `ApplicationLoadBalancer` enruta el tráfico y que Elastic Load Balancing usa para comprobar el estado de las instancias de EC2.
+ `HealthCheckIntervalSeconds` especifica que las instancias de EC2 tengan un intervalo de 30 segundos entre las comprobaciones de estado. `HealthCheckTimeoutSeconds` se define como el periodo de tiempo en el que Elastic Load Balancing espera una respuesta del destino de comprobación de estado (15 segundos en este ejemplo). Cuando termina el tiempo de espera, Elastic Load Balancing marca la comprobación de estado de las instancias de EC2 como en mal estado. Cuando una instancia de EC2 falla tres comprobaciones consecutivas (`UnhealthyThresholdCount`), Elastic Load Balancing detiene el tráfico de enrutamiento a dicha instancia de EC2 hasta que esa instancia tenga cinco comprobaciones correctas consecutivas (`HealthyThresholdCount`). En ese momento, Elastic Load Balancing considera que la instancia tiene un estado correcto y comienza a redirigir el tráfico a la instancia nuevamente.
+ `TargetGroupAttributes` actualiza el valor de retraso de anulación del registro del grupo objetivo a 20 segundos. De forma predeterminada, Elastic Load Balancing espera 300 segundos para completar el proceso de anulación del registro.

Recurso `ALBListener` de [AWS::ElasticLoadBalancingV2::Listener](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-elasticloadbalancingv2-listener.html)
+ `DefaultActions` especifica el puerto que el equilibrador de carga escucha, el grupo objetivo al que el equilibrador de carga reenvía las solicitudes y el protocolo utilizado para enrutar solicitudes.

Recurso `ApplicationLoadBalancer` de [AWS::ElasticLoadBalancingV2::LoadBalancer](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-elasticloadbalancingv2-loadbalancer.html)
+ `Subnets` toma el valor del parámetro de entrada `Subnets` como la lista de subredes públicas donde se crearán los nodos del equilibrador de carga.
+ `SecurityGroup` obtiene el ID del grupo de seguridad que funciona como un firewall virtual para los nodos del equilibrador de carga con el objetivo de controlar el tráfico entrante. La función [GetAtt](resources-section-structure.md#resource-properties-getatt) se usa para obtener el ID del grupo de seguridad con el nombre lógico `ELBSecurityGroup`.

Recurso `LaunchTemplate` de [AWS::EC2::LaunchTemplate](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-ec2-launchtemplate.html)
+ `ImageId` toma el valor del parámetro de entrada `LatestAmiId` como la AMI que se va a utilizar.
+ `KeyName` adopta el valor del parámetro de entrada `KeyName` como el par de claves de EC2 que se usará.
+ `SecurityGroupIds` obtiene el ID del grupo de seguridad con el nombre lógico `EC2SecurityGroup` que funciona como un firewall virtual para las instancias de EC2 con el objetivo de controlar el tráfico entrante.
+ `UserData` es un script de configuración que se ejecuta una vez que la instancia está operativa y en ejecución. En este ejemplo, el script instala Apache y crea un archivo index.html.

Recurso `NotificationTopic` de [AWS::SNS::Topic](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-sns-topic.html)
+ `Subscription` toma el valor del parámetro de entrada `OperatorEmail` como la dirección de correo electrónico del destinatario de las notificaciones cuando hay actividades de escalado. 

Recurso `WebServerGroup` de [AWS::AutoScaling::AutoScalingGroup](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-autoscaling-autoscalinggroup.html)
+ `MinSize` y `MaxSize` establecen el número mínimo y máximo de instancias de EC2 en el grupo de escalado automático.
+ `TargetGroupARNs` toma el ARN del grupo de destino con el nombre lógico `EC2TargetGroup`. A medida que este grupo de escalado automático escala, registra y anula automáticamente las instancias en este grupo de destino.
+ `VPCZoneIdentifier` toma el valor del parámetro de entrada `Subnets` como la lista de subredes públicas donde pueden crearse las instancias de EC2.

## Paso 1: Lance la pila
<a name="example-templates-autoscaling-launch-stack"></a>

Antes de lanzar la pila, compruebe que tiene permisos de AWS Identity and Access Management (IAM) para utilizar todos los siguientes servicios: Amazon EC2, Amazon EC2 Auto Scaling, AWS Systems Manager, Elastic Load Balancing, Amazon SNS y CloudFormation. 

El siguiente procedimiento implica cargar la plantilla de pila de ejemplo desde un archivo. Abra un editor de texto en su equipo local y agregue una de las plantillas. Guarde el archivo con el nombre `sampleloadbalancedappstack.template`.

**Para lanzar la plantilla de pila**

1. Inicie sesión en la Consola de administración de AWS y abra la consola de CloudFormation en [https://console.aws.amazon.com/cloudformation](https://console.aws.amazon.com/cloudformation/).

1. Elija **Create stack (Crear pila)**, **With new resources (standard) (Con nuevos recursos [estándar])**.

1. En **Especificar plantilla**, seleccione **Cargar un archivo de plantilla** y, a continuación, seleccione **Elegir archivo** para cargar el archivo `sampleloadbalancedappstack.template`. 

1. Elija **Siguiente**.

1. En la página **Especificar detalles de pila**, en Nombre de pila, escriba un nombre para la pila (por ejemplo, **SampleLoadBalancedAppStack**).

1. En **Parámetros**, revise los parámetros de la pila y proporcione valores para todos los parámetros que no tengan valores predeterminados, incluidos **OperatorEmail**, **SSHLocation**, **KeyName**, **VPC** y **Subnets**.

1. Seleccione **Next (Siguiente)** dos veces.

1. En la página **Revisar**, revise y confirme la configuración.

1. Elija **Enviar**.

   Puede ver el estado de la pila en la consola de CloudFormation en la columna **Estado**. Cuando CloudFormation haya creado correctamente la pila, recibirá el estado **CREATE\$1COMPLETE**.
**nota**  
Después de crear la pila, debe confirmar la suscripción antes de que la dirección de correo electrónico pueda comenzar a recibir notificaciones. Para obtener más información, consulte [Obtener notificaciones de Amazon SNS cuando su grupo de escalado automático escala](https://docs.aws.amazon.com/autoscaling/ec2/userguide/ec2-auto-scaling-sns-notifications.html) en la *Guía del usuario de Amazon EC2 Auto Scaling*.

## Paso 2: Eliminar los recursos de ejemplo
<a name="example-templates-autoscaling-clean-up"></a>

Para asegurarse de que no se cobra por recursos de ejemplo no utilizados, elimine la pila.

**Para eliminar la pila**

1. En la consola de CloudFormation, elija la pila **SampleLoadBalancedAppStack**.

1. Elija **Eliminar**.

1. En el mensaje de confirmación, elija **Eliminar pila**.

   El estado de **SampleLoadBalancedAppStack** cambia a **DELETE\$1IN\$1PROGRESS**. Cuando CloudFormation completa la eliminación de la pila, quita la pila de la lista.

Use la plantilla de ejemplo de este tutorial para crear sus propias plantillas de pila. Para obtener más información, consulte [Tutorial: Configuración de una aplicación con escalado y equilibrio de carga aplicados](https://docs.aws.amazon.com/autoscaling/ec2/userguide/tutorial-ec2-auto-scaling-load-balancer.html) en la *Guía del usuario de Amazon EC2 Auto Scaling*.