Criar recursos do Amazon ECS usando o AWS CDK - Amazon Elastic Container Service

Criar recursos do Amazon ECS usando o AWS CDK

O AWS Cloud Development Kit (AWS CDK) é um framework de infraestrutura como código (IAC) que pode ser usado para definir a infraestrutura da nuvem AWS usando uma linguagem de programação completa. Para definir sua própria infraestrutura de nuvem, primeiro é necessário criar uma aplicação (em uma das linguagens aceitas pelo CDK) que contenha uma ou mais pilhas. Em seguida, sintetize-a em um modelo do AWS CloudFormation e implante seus recursos na Conta da AWS. Siga as etapas descritas neste tópico para implantar um servidor Web em contêiner com o Amazon Elastic Container Service (Amazon ECS) e o AWS CDK no Fargate.

A AWS Construct Library, incluída no CDK, fornece módulos que podem ser usados para modelar os recursos fornecidos por cada serviço da Serviços da AWS. Para serviços populares, a biblioteca fornece construções selecionadas com padrões inteligentes e práticas recomendadas. Um desses módulos, especificamente o aws-ecs-patterns, fornece abstrações de alto nível que permitem definir o serviço em contêineres e todos os recursos de suporte necessários em algumas linhas de código.

Este tópico usa a construção ApplicationLoadBalancedFargateService. A construção implanta um serviço do Amazon ECS no Fargate por trás de um Application Load Balancer. O módulo aws-ecs-patterns também inclui construções que usam um network load balancer e são executadas no Amazon EC2.

Antes de iniciar esta tarefa, configure o ambiente de desenvolvimento do AWS CDK e instale o AWS CDK executando o comando a seguir. Para obter instruções sobre como configurar o ambiente de desenvolvimento do AWS CDK, consulte Conceitos básicos do AWS CDK: pré-requisitos.

npm install -g aws-cdk
nota

Essas instruções pressupõem que você está usando o AWS CDK v2.

Etapa 1: configurar o projeto do AWS CDK

Crie um diretório para a nova aplicação do AWS CDK e inicialize o projeto.

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

Iniciado o projeto, ative o ambiente virtual do projeto e instale as dependências de linha de base do 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 esse projeto do Maven para seu Java IDE. Por exemplo, no Eclipse, use File (Arquivo) > Import (Importar) > Maven > Existing Maven Projects (Projetos do Maven existentes).

C#
mkdir hello-ecs cd hello-ecs cdk init --language csharp
Go
mkdir hello-ecs cd hello-ecs cdk init --language go
nota

O modelo de aplicação do AWS CDK usa o nome do diretório do projeto para gerar nomes para arquivos e classes de origem. Neste exemplo, o diretório se chama hello-ecs. Se você escolher outro nome de diretório de projeto, sua aplicação não corresponderá a estas instruções.

O AWS CDK v2 inclui construções estáveis para todos os Serviços da AWS em um único pacote chamado aws-cdk-lib. Esse pacote é instalado como uma dependência quando o projeto é inicializado. Quando determinadas linguagens de programação são usadas, o pacote é instalado quando o projeto é compilado pela primeira vez. Este tópico descreve como usar construção de padrões do Amazon ECS que fornece abstrações de alto nível para trabalhar com o Amazon ECS. Esse módulo depende de construções do Amazon ECS e de outras construções para provisionar os recursos necessários para sua aplicação do Amazon ECS.

Os nomes usados para importar essas bibliotecas para a aplicação do CDK podem diferir ligeiramente dependendo da linguagem de programação utilizada. Para referência, estes são os nomes usados em cada linguagem de programação aceita pelo CDK.

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#
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

Etapa 2: usar o AWS CDK para definir um servidor Web em contêiner no Fargate

Use a imagem de contêiner amazon-ecs-sample do DockerHub. Essa imagem contém uma aplicação Web PHP que é executada no Amazon Linux 2.

No projeto AWS CDK criado por você, edite o arquivo que contém a definição de pilha de modo que ele se pareça com um dos exemplos a seguir.

nota

Uma pilha é uma unidade de implantação. Todos os recursos devem estar em uma pilha, e todos os recursos que estão em uma pilha são implantados ao mesmo tempo. Se a implantação de um recurso falhar, todos os demais recursos já implantados serão revertidos. Uma aplicação do AWS CDK pode conter várias pilhas, e os recursos de uma pilha podem se referir aos recursos de outra pilha.

TypeScript

Atualize lib/hello-ecs-stack.ts de modo que ele seja semelhante ao seguinte.

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('amazon/amazon-ecs-sample'), }, publicLoadBalancer: true }); } }
JavaScript

Atualize lib/hello-ecs-stack.js de modo que ele seja semelhante ao seguinte.

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

Atualize hello-ecs/hello_ecs_stack.py de modo que ele seja semelhante ao seguinte.

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

Atualize src/main/java/com.myorg/HelloEcsStack.java de modo que ele seja semelhante ao seguinte.

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#

Atualize src/HelloEcs/HelloEcsStack.cs de modo que ele seja semelhante ao seguinte.

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

Atualize hello-ecs.go de modo que ele seja semelhante ao seguinte.

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")), // } }

O snippet curto anterior inclui o seguinte:

  • O nome lógico do serviço: MyWebServer.

  • A imagem do contêiner obtida do DockerHub: amazon/amazon-ecs-sample.

  • Outras informações relevantes, como o fato de que o balanceador de carga tem um endereço público e é acessível via Internet.

O AWS CDK criará todos os recursos necessários para implantar o servidor Web, incluindo os seguintes recursos. Esses recursos foram omitidos neste exemplo.

  • Cluster do Amazon ECS

  • Instâncias do Amazon VPC e do Amazon EC2

  • Auto Scaling group (Grupo do Auto Scaling)

  • Application Load Balancer

  • Perfis e políticas do IAM

Alguns recursos provisionados automaticamente serão compartilhados por todos os serviços do Amazon ECS definidos na pilha.

Salve o arquivo de origem e, em seguida, execute o comando cdk synth no diretório principal da aplicação. O AWS CDK executa a aplicação e sintetiza um modelo do AWS CloudFormation baseado nela. Em seguida, exibe o modelo. O modelo é um arquivo YAML com aproximadamente 600 linhas. O início do arquivo é mostrado aqui. Seu modelo pode ser diferente deste exemplo.

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 implantar o serviço na Conta da AWS, execute cdk deploy no diretório principal da aplicação. Você será avisado para aprovar as políticas do IAM que geradas pelo AWS CDK.

A implantação demora vários minutos, período durante o qual o AWS CDK cria diversos recursos. As últimas linhas da saída da implantação incluem o nome de host público do balanceador de carga e o URL do novo servidor Web. Eles são os seguintes:

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

Etapa 3: testar o serviço da Web

Copie o URL da saída da implantação e cole no navegador da Web. A mensagem de boas-vindas a seguir do servidor Web é exibida.

Captura de tela da aplicação de exemplo do Amazon ECS. A saída indica: “Your application is now running on Amazon ECS” (Sua aplicação agora está em execução no Amazon ECS).

Etapa 4: limpar

Após terminar com o servidor Web, encerre o serviço usando o CDK ao executar o comando cdk destroy no diretório principal da aplicação. Isso evita incorrer em cobranças não intencionais no futuro.

Próximas etapas

Para saber mais sobre como desenvolver a infraestrutura da AWS usando o AWS CDK, consulte o Guia do desenvolvedor do AWS CDK.

Para obter informações sobre como criar aplicações do AWS CDK em sua linguagem preferida, consulte:

TypeScript

Trabalhar com o AWS CDK no TypeScript

JavaScript

Trabalhar com o AWS CDK no JavaScript

Python

Trabalhar com o AWS CDK no Python

Java

Trabalhar com o AWS CDK no Java

C#

Trabalhar com o AWS CDK em C#

Go

Working with the AWS CDK in Go

Para obter mais informações sobre os módulos da AWS Construct Library usados neste tópico, consulte as visões gerais da Referência da API do AWS CDK a seguir.