

# Creación de recursos de Amazon ECS con AWS CDK
<a name="tutorial-ecs-web-server-cdk"></a>

AWS Cloud Development Kit (AWS CDK) es un marco de infraestructura como código (IAC) que le permite definir la infraestructura de nube de AWS mediante un lenguaje de programación de su elección. Para definir su propia infraestructura de nube, primero escriba una aplicación (en uno de los lenguajes compatibles con CDK) que contenga una o más pilas. Luego, sintetícela en una plantilla de CloudFormation e implemente sus recursos en suCuenta de AWS. Siga los pasos de este tema para implementar un servidor web en contenedores con Amazon Elastic Container Service (Amazon ECS) y el AWS CDK en Fargate. 

La biblioteca de construcción de AWS, incluida con el CDK, ofrece módulos que puede usar para modelar los recursos proporcionados por Servicios de AWS. Para los servicios más populares, la biblioteca proporciona construcciones seleccionadas con valores predeterminados inteligentes y prácticas recomendadas. Uno de estos módulos, `[aws-ecs-patterns](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ecs_patterns-readme.html)` en particular, proporciona abstracciones de alto nivel que le permiten definir su servicio en contenedores y todos los recursos de soporte necesarios en solo unas pocas líneas de código.

Este tema emplea la construcción [https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ecs_patterns.ApplicationLoadBalancedFargateService.html](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ecs_patterns.ApplicationLoadBalancedFargateService.html). Esta construcción implementa un servicio Amazon ECS en Fargate detrás de un equilibrador de carga de aplicación. El módulo `aws-ecs-patterns` también incluye construcciones que usan un equilibrador de carga de red y se ejecutan en Amazon EC2.

Antes de comenzar esta tarea, configure su entorno de desarrollo AWS CDK y ejecute el comando siguiente para instalar el AWS CDK. Para obtener instrucciones sobre cómo configurar su entorno de desarrollo AWS CDK, consulte [Getting Started With the AWS CDK - Prerequisites](https://docs.aws.amazon.com/cdk/v2/guide/getting_started.html#getting_started_prerequisites) (Primeros pasos con CDK: requisitos previos).

```
npm install -g aws-cdk
```

**nota**  
En estas instrucciones, se presupone que está utilizando AWS CDK v2. 

**Topics**
+ [Paso 1: Configuración del proyecto AWS CDK](#ecs-web-server-cdk-step-1)
+ [Paso 2: usar el AWS CDK para definir un servidor web en contenedores en Fargate](#ecs-web-server-cdk-step-2)
+ [Paso 3: probar el servidor web](#ecs-web-server-cdk-step-3)
+ [Paso 4: Limpiar](#ecs-web-server-cdk-step-4)
+ [Siguientes pasos](#ecs-web-server-cdk-next-steps)

## Paso 1: Configuración del proyecto AWS CDK
<a name="ecs-web-server-cdk-step-1"></a>

Cree un directorio para la nueva aplicación AWS CDK e inicialice el proyecto.

------
#### [ TypeScript ]

```
mkdir hello-ecs
cd hello-ecs
cdk init --language typescript
```

------
#### [ JavaScript ]

```
mkdir hello-ecs
cd hello-ecs
cdk init --language javascript
```

------
#### [ Python ]

```
mkdir hello-ecs
cd hello-ecs
cdk init --language python
```

Después de inicializar el proyecto, active el entorno virtual del proyecto e instale las dependencias de referencia de AWS CDK.

```
source .venv/bin/activate
python -m pip install -r requirements.txt
```

------
#### [ Java ]

```
mkdir hello-ecs
cd hello-ecs
cdk init --language java
```

Importe este proyecto de Maven a su IDE de Java. Por ejemplo, en Eclipse, use **Archivo** > **Importar** > **Maven** > **Proyectos de Maven existentes**.

------
#### [ C\$1 ]

```
mkdir hello-ecs
cd hello-ecs
cdk init --language csharp
```

------
#### [ Go ]

```
mkdir hello-ecs
cd hello-ecs
cdk init --language go
```

------

**nota**  
La plantilla de la aplicación AWS CDK utiliza el nombre del directorio del proyecto para generar nombres para los archivos y las clases fuente. En este ejemplo, el directorio se llama `hello-ecs`. Si usa otro nombre de directorio de proyecto, la aplicación no coincidirá con estas instrucciones.

AWS CDK v2 incluye construcciones estables para todos los Servicios de AWS en un solo paquete denominado `aws-cdk-lib`. Este paquete se instala como dependencia cuando inicializa el proyecto. Al trabajar con ciertos lenguajes de programación, el paquete se instala al crear el proyecto por primera vez. Este tema abarca cómo usar una construcción Amazon ECS Patterns, la cual proporciona abstracciones de alto nivel para trabajar con Amazon ECS. Este módulo se basa en construcciones de Amazon ECS y en otras para aprovisionar los recursos necesarios para su aplicación Amazon ECS.

Los nombres que usa para importar estas bibliotecas a su aplicación CDK pueden diferir ligeramente según el lenguaje de programación que use. Como referencia, estos son los nombres usados en cada lenguaje de programación CDK compatible.

------
#### [ TypeScript ]

```
aws-cdk-lib/aws-ecs
aws-cdk-lib/aws-ecs-patterns
```

------
#### [ JavaScript ]

```
aws-cdk-lib/aws-ecs
aws-cdk-lib/aws-ecs-patterns
```

------
#### [ Python ]

```
aws_cdk.aws_ecs
aws_cdk.aws_ecs_patterns
```

------
#### [ Java ]

```
software.amazon.awscdk.services.ecs
software.amazon.awscdk.services.ecs.patterns
```

------
#### [ C\$1 ]

```
Amazon.CDK.AWS.ECS
Amazon.CDK.AWS.ECS.Patterns
```

------
#### [ Go ]

```
github.com/aws/aws-cdk-go/awscdk/v2/awsecs
github.com/aws/aws-cdk-go/awscdk/v2/awsecspatterns
```

------

## Paso 2: usar el AWS CDK para definir un servidor web en contenedores en Fargate
<a name="ecs-web-server-cdk-step-2"></a>

Utilice la imagen del contenedor [https://gallery.ecr.aws/ecs-sample-image/amazon-ecs-sample](https://gallery.ecr.aws/ecs-sample-image/amazon-ecs-sample). Esta imagen contiene una aplicación web PHP que se ejecuta en Ngingx.

En el proyecto AWS CDK que ha creado, edite el archivo que contiene la definición de pila para que se parezca a uno de los siguientes ejemplos.

**nota**  
Una pila es una unidad de implementación. Todos los recursos deben estar en una pila y todos los recursos que están en una pila se implementan al mismo tiempo. Si un recurso no se puede implementar, se restaurarán todos los otros recursos ya implementados. Una aplicación AWS CDK puede contener varias pilas y los recursos de una pila pueden hacer referencia a los recursos de otra.

------
#### [ TypeScript ]

Actualice `lib/hello-ecs-stack.ts` para que se parezca a lo siguiente.

```
import * as cdk from 'aws-cdk-lib';
import { Construct } from 'constructs';
import * as ecs from 'aws-cdk-lib/aws-ecs';
import * as ecsp from 'aws-cdk-lib/aws-ecs-patterns';

export class HelloEcsStack extends cdk.Stack {
  constructor(scope: Construct, id: string, props?: cdk.StackProps) {
    super(scope, id, props);

    new ecsp.ApplicationLoadBalancedFargateService(this, 'MyWebServer', {
      taskImageOptions: {
        image: ecs.ContainerImage.fromRegistry('public.ecr.aws/ecs-sample-image/amazon-ecs-sample:latest'),
      },
      publicLoadBalancer: true
    });
  }
}
```

------
#### [ JavaScript ]

Actualice `lib/hello-ecs-stack.js` para que se parezca a lo siguiente.

```
const cdk = require('aws-cdk-lib');
const { Construct } = require('constructs');
const ecs = require('aws-cdk-lib/aws-ecs');
const ecsp = require('aws-cdk-lib/aws-ecs-patterns');

class HelloEcsStack extends cdk.Stack {
  constructor(scope = Construct, id = string, props = cdk.StackProps) {
    super(scope, id, props);

    new ecsp.ApplicationLoadBalancedFargateService(this, 'MyWebServer', {
      taskImageOptions: {
        image: ecs.ContainerImage.fromRegistry('amazon/amazon-ecs-sample'),
      },
      publicLoadBalancer: true
    });
  }
}

module.exports = { HelloEcsStack }
```

------
#### [ Python ]

Actualice `hello-ecs/hello_ecs_stack.py` para que se parezca a lo siguiente.

```
import aws_cdk as cdk
from constructs import Construct

import aws_cdk.aws_ecs as ecs
import aws_cdk.aws_ecs_patterns as ecsp

class HelloEcsStack(cdk.Stack):

    def __init__(self, scope: Construct, construct_id: str, **kwargs) -> None:
        super().__init__(scope, construct_id, **kwargs)

        ecsp.ApplicationLoadBalancedFargateService(self, "MyWebServer",
            task_image_options=ecsp.ApplicationLoadBalancedTaskImageOptions(
                image=ecs.ContainerImage.from_registry("amazon/amazon-ecs-sample")),
            public_load_balancer=True
        )
```

------
#### [ Java ]

Actualice `src/main/java/com.myorg/HelloEcsStack.java` para que se parezca a lo siguiente.

```
package com.myorg;

import software.constructs.Construct;
import software.amazon.awscdk.Stack;
import software.amazon.awscdk.StackProps;

import software.amazon.awscdk.services.ecs.ContainerImage;
import software.amazon.awscdk.services.ecs.patterns.ApplicationLoadBalancedFargateService;
import software.amazon.awscdk.services.ecs.patterns.ApplicationLoadBalancedTaskImageOptions;

public class HelloEcsStack extends Stack {
    public HelloEcsStack(final Construct scope, final String id) {
        this(scope, id, null);
    }

    public HelloEcsStack(final Construct scope, final String id, final StackProps props) {
        super(scope, id, props);

        ApplicationLoadBalancedFargateService.Builder.create(this, "MyWebServer")
        	.taskImageOptions(ApplicationLoadBalancedTaskImageOptions.builder()
        			.image(ContainerImage.fromRegistry("amazon/amazon-ecs-sample"))
        			.build())
        	.publicLoadBalancer(true)
        	.build();        
    }
}
```

------
#### [ C\$1 ]

Actualice `src/HelloEcs/HelloEcsStack.cs` para que se parezca a lo siguiente.

```
using Amazon.CDK;
using Constructs;
using Amazon.CDK.AWS.ECS;
using Amazon.CDK.AWS.ECS.Patterns;
namespace HelloEcs
{
    public class HelloEcsStack : Stack
    {
        internal HelloEcsStack(Construct scope, string id, IStackProps props = null) : base(scope, id, props)
        {
            new ApplicationLoadBalancedFargateService(this, "MyWebServer",
                new ApplicationLoadBalancedFargateServiceProps
                {
                    TaskImageOptions = new ApplicationLoadBalancedTaskImageOptions
                    {
                        Image = ContainerImage.FromRegistry("amazon/amazon-ecs-sample")
                    },
                    PublicLoadBalancer = true
                });
        }
    }
}
```

------
#### [ Go ]

Actualice `hello-ecs.go` para que se parezca a lo siguiente.

```
package main

import (
	"github.com/aws/aws-cdk-go/awscdk/v2"
	// "github.com/aws/aws-cdk-go/awscdk/v2/awssqs"
	"github.com/aws/aws-cdk-go/awscdk/v2/awsecs"
	"github.com/aws/aws-cdk-go/awscdk/v2/awsecspatterns"
	"github.com/aws/constructs-go/constructs/v10"
	"github.com/aws/jsii-runtime-go"
)

type HelloEcsStackProps struct {
	awscdk.StackProps
}

func NewHelloEcsStack(scope constructs.Construct, id string, props *HelloEcsStackProps) awscdk.Stack {
	var sprops awscdk.StackProps
	if props != nil {
		sprops = props.StackProps
	}
	stack := awscdk.NewStack(scope, &id, &sprops)

	// The code that defines your stack goes here

	// example resource
	// queue := awssqs.NewQueue(stack, jsii.String("HelloEcsQueue"), &awssqs.QueueProps{
	// 	VisibilityTimeout: awscdk.Duration_Seconds(jsii.Number(300)),
	// })
	res := awsecspatterns.NewApplicationLoadBalancedFargateService(stack, jsii.String("MyWebServer"),
		&awsecspatterns.ApplicationLoadBalancedFargateServiceProps{
			TaskImageOptions: &awsecspatterns.ApplicationLoadBalancedTaskImageOptions{
				Image: awsecs.ContainerImage_FromRegistry(jsii.String("amazon/amazon-ecs-sample"), &awsecs.RepositoryImageProps{}),
			},
		},
	)
	awscdk.NewCfnOutput(stack, jsii.String("LoadBalancerDNS"), &awscdk.CfnOutputProps{Value: res.LoadBalancer().LoadBalancerDnsName()})

	return stack
}

func main() {
	defer jsii.Close()

	app := awscdk.NewApp(nil)

	NewHelloEcsStack(app, "HelloEcsStack", &HelloEcsStackProps{
		awscdk.StackProps{
			Env: env(),
		},
	})

	app.Synth(nil)
}

// env determines the AWS environment (account+region) in which our stack is to
// be deployed. For more information see: https://docs.aws.amazon.com/cdk/latest/guide/environments.html
func env() *awscdk.Environment {
	// If unspecified, this stack will be "environment-agnostic".
	// Account/Region-dependent features and context lookups will not work, but a
	// single synthesized template can be deployed anywhere.
	//---------------------------------------------------------------------------
	return nil

	// Uncomment if you know exactly what account and region you want to deploy
	// the stack to. This is the recommendation for production stacks.
	//---------------------------------------------------------------------------
	// return &awscdk.Environment{
	//  Account: jsii.String("123456789012"),
	//  Region:  jsii.String("us-east-1"),
	// }

	// Uncomment to specialize this stack for the AWS Account and Region that are
	// implied by the current CLI configuration. This is recommended for dev
	// stacks.
	//---------------------------------------------------------------------------
	// return &awscdk.Environment{
	//  Account: jsii.String(os.Getenv("CDK_DEFAULT_ACCOUNT")),
	//  Region:  jsii.String(os.Getenv("CDK_DEFAULT_REGION")),
	// }
}
```

------

El fragmento breve anterior incluye lo siguiente:
+ El nombre lógico del servicio: `MyWebServer`.
+ La imagen del contenedor que se obtuvo de la galería pública de Amazon ECR: `amazon/amazon-ecs-sample`.
+ Otra información relevante, como el hecho de que el equilibrador de carga tiene una dirección pública y se puede acceder a él desde Internet.

 La AWS CDK creará todos los recursos necesarios para implementar el servidor web, incluidos los siguientes recursos. Estos recursos se omitieron en este ejemplo.
+ Clúster de Amazon ECS 
+ Instancias de Amazon VPC y Amazon EC2 
+  Grupo de escalado automático
+  Equilibrador de carga de aplicación 
+  Roles y políticas de IAM 

 Algunos recursos aprovisionados automáticamente se compartirán con todos los servicios de Amazon ECS definidos en la pila.

Guarde el archivo fuente y a continuación ejecute el comando `cdk synth` en el directorio principal de la aplicación. El AWS CDK ejecuta la aplicación, sintetiza una plantilla de CloudFormation a partir de ella y luego muestra la plantilla. La plantilla es un archivo YAML de aproximadamente 600 líneas. Aquí se muestra el principio del archivo. Su plantilla puede diferir de este ejemplo.

```
Resources:
  MyWebServerLB3B5FD3AB:
    Type: AWS::ElasticLoadBalancingV2::LoadBalancer
    Properties:
      LoadBalancerAttributes:
        - Key: deletion_protection.enabled
          Value: "false"
      Scheme: internet-facing
      SecurityGroups:
        - Fn::GetAtt:
            - MyWebServerLBSecurityGroup01B285AA
            - GroupId
      Subnets:
        - Ref: EcsDefaultClusterMnL3mNNYNVpcPublicSubnet1Subnet3C273B99
        - Ref: EcsDefaultClusterMnL3mNNYNVpcPublicSubnet2Subnet95FF715A
      Type: application
    DependsOn:
      - EcsDefaultClusterMnL3mNNYNVpcPublicSubnet1DefaultRouteFF4E2178
      - EcsDefaultClusterMnL3mNNYNVpcPublicSubnet2DefaultRouteB1375520
    Metadata:
      aws:cdk:path: HelloEcsStack/MyWebServer/LB/Resource
  MyWebServerLBSecurityGroup01B285AA:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupDescription: Automatically created Security Group for ELB HelloEcsStackMyWebServerLB06757F57
      SecurityGroupIngress:
        - CidrIp: 0.0.0.0/0
          Description: Allow from anyone on port 80
          FromPort: 80
          IpProtocol: tcp
          ToPort: 80
      VpcId:
        Ref: EcsDefaultClusterMnL3mNNYNVpc7788A521
    Metadata:
      aws:cdk:path: HelloEcsStack/MyWebServer/LB/SecurityGroup/Resource
# and so on for another few hundred lines
```

Para implementar el servicio en su Cuenta de AWS, ejecute el comando `cdk deploy` en el directorio principal de la aplicación. Se le pedirá que apruebe las políticas de IAM que ha generado el AWS CDK.

La implementación lleva varios minutos, durante los cuales el AWS CDK crea varios recursos. Las últimas líneas del resultado de la implementación incluyen el nombre de host público del equilibrador de carga y la dirección URL de su nuevo servidor web. Son los siguientes:

```
Outputs:
HelloEcsStack.MyWebServerLoadBalancerDNSXXXXXXX = Hello-MyWeb-ZZZZZZZZZZZZZ-ZZZZZZZZZZ.us-west-2.elb.amazonaws.com
HelloEcsStack.MyWebServerServiceURLYYYYYYYY = http://Hello-MyWeb-ZZZZZZZZZZZZZ-ZZZZZZZZZZ.us-west-2.elb.amazonaws.com
```

## Paso 3: probar el servidor web
<a name="ecs-web-server-cdk-step-3"></a>

Copie la dirección URL del resultado de la implementación y péguela en el navegador web. Se muestra el siguiente mensaje de bienvenida del servidor web.

![\[Captura de pantalla de la aplicación de ejemplo de Amazon ECS. El resultado indica “Amazon ECS”.\]](http://docs.aws.amazon.com/es_es/AmazonECS/latest/developerguide/images/simple-php-app-congrats.png)


## Paso 4: Limpiar
<a name="ecs-web-server-cdk-step-4"></a>

Cuando haya terminado con el servidor web, finalice el servicio mediante la CDK. Para ello, ejecute el comando `cdk destroy` en el directorio principal de la aplicación. Esto evita que incurra en cargos imprevistos en el futuro.

## Siguientes pasos
<a name="ecs-web-server-cdk-next-steps"></a>

Para obtener más información sobre cómo desarrollar la infraestructura de AWS mediante AWS CDK, consulte la [Guía para desarrolladores de AWS CDK](https://docs.aws.amazon.com/cdk/v2/guide/).

Para obtener información sobre cómo escribir aplicaciones de AWS CDK en el lenguaje de su elección, consulte:

------
#### [ TypeScript ]

[Utilización del AWS CDK en TypeScript](https://docs.aws.amazon.com/cdk/v2/guide/work-with-cdk-typescript.html)

------
#### [ JavaScript ]

[Utilización del AWS CDK en JavaScript](https://docs.aws.amazon.com/cdk/v2/guide/work-with-cdk-javascript.html)

------
#### [ Python ]

[Utilización del AWS CDK en Python](https://docs.aws.amazon.com/cdk/v2/guide/work-with-cdk-python.html)

------
#### [ Java ]

[Utilización del AWS CDK en Java](https://docs.aws.amazon.com/cdk/v2/guide/work-with-cdk-java.html)

------
#### [ C\$1 ]

[Utilización del AWS CDK en C\$1](https://docs.aws.amazon.com/cdk/v2/guide/work-with-cdk-csharp.html)

------
#### [ Go ]

[Uso del AWS CDK en Go](https://docs.aws.amazon.com/cdk/v2/guide/work-with-cdk-go.html)

------

Para obtener más información sobre los módulos de la biblioteca de construcción de AWS que se usan en este tema, consulte la siguiente información general de la Referencia de la API de AWS CDK.
+ [https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ecs-readme.html](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ecs-readme.html)
+  [https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ecs_patterns-readme.html](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ecs_patterns-readme.html)