Passo a passo: como pesquisar os IDs de AMI com um recurso personalizado baseado no Lambda
Esta orientação passo a passo mostra como usar o Lambda e um recurso personalizado para pesquisar dinamicamente os IDs de imagem de máquina da Amazon (AMI) no modelo do CloudFormation. Isso pode ajudar você a simplificar a atualização dos IDs de AMI nos modelos do CloudFormation.
Ao criar um modelo do CloudFormation para iniciar uma instância do Amazon EC2, você deve especificar um ID da AMI, que é similar a um modelo para o sistema operacional e para o software que serão instalados na instância. O ID da AMI mais adequado depende do tipo de instância e da Região da AWS em que você está iniciando a instância. Esses IDs podem ser alterados regularmente, por exemplo, quando uma AMI é atualizada com atualizações de software.
Normalmente, você especifica o ID da AMI em uma seção de mapeamento que mapeia os IDs de AMI para regiões e para tipos de instância específicos. Isso significa que, para atualizar os IDs, você deve alterá-los manualmente em cada um dos seus modelos. Porém, usando os recursos personalizados e o Lambda, é possível criar uma função que obtenha os IDs das AMIs mais recentes para o tipo de instância e para a região que você está usando. Dessa forma, não é necessário manter, de forma manual, os mapeamentos entre IDs da AMI, tipos de instância e regiões nos modelos de pilha.
Esta descrição mostra como criar um recurso personalizado e associar uma função Lambda a ele para pesquisar IDs de AMI. O pressuposto é de que você esteja familiarizado com os recursos personalizados e com as funções do Lambda. Para obter uma introdução aos recursos personalizados e como eles funcionam, consulte Recursos personalizados. Para obter mais informações sobre o Lambda, consulte o Guia do desenvolvedor do AWS Lambda.
nota
O CloudFormation é um serviço gratuito; no entanto, você incorre em cobranças pelo uso dos recursos da AWS, como a função do Lambda e a instância do EC2, que são inclusos em suas pilhas, na taxa de cobrança atual para cada um deles. Para obter mais informações sobre o preço da AWS, consulte a página de detalhes de cada produto em http://aws.amazon.com
Tópicos
Visão geral
As etapas a seguir fornecem uma visão geral dessa implementação.
-
Salve um exemplo de pacote contendo o código da função do Lambda em um bucket do Amazon S3 na mesma Região da AWS em que você deseja criar a instância do EC2.
-
Use o exemplo de modelo para criar a pilha com um recurso personalizado, uma função do Lambda, uma instância do EC2 e um perfil do IAM que o Lambda usa para fazer chamadas para o Amazon EC2.
-
A pilha associa a função do Lambda ao recurso personalizado. Quando a pilha é criada, o CloudFormation invoca a função e envia a ela informações, como o tipo de solicitação, os dados de entrada e uma URL do Amazon S3 pré-assinada.
-
A função do Lambda usa os dados de entrada para pesquisar o ID da AMI mais recente e o envia como resposta à URL pré-assinada.
-
Depois que o CloudFormation obtém uma resposta no local da URL pré-assinada, ele prossegue com a criação da pilha. Quando o CloudFormation cria a instância, ele usa o ID da AMI fornecido pela função do Lambda para criar a instância do EC2 com a AMI mais recente.
Demonstração do modelo
Para visualizar todo o modelo de amostra, consulte:
Os seguintes trechos explicam relevantes partes do modelo de amostra para ajudá-lo a entender como associar uma função Lambda a um recurso personalizado e como usar a resposta da função.
AMIInfoFunction
do resource AWS::Lambda::Function
O recurso AWS::Lambda::Function
especifica o código-fonte, o nome do handler, o ambiente de runtime e o nome do recurso da Amazon (ARN) do perfil de execução da função.
-
A propriedade
Code
especifica o local do Amazon S3 (nome do bucket e nome de arquivo) onde você fez upload do pacote de amostra. O modelo de amostra usa parâmetros de entrada ("Ref": "S3Bucket"
e"Ref": "S3Key"
) para definir o bucket e nomes de arquivos para que você possa especificar os nomes quando criar a pilha. Da mesma forma, o nome do manipulador, que corresponde ao nome do arquivo de origem (o arquivo JavaScript) no pacote.zip
, também usa um parâmetro de entrada ("Ref": "ModuleName"
). Como o arquivo de origem é código JavaScript, o runtime é especificado comonodejs18.x
. -
Para o código usado neste tutorial passo a passo, o tempo de execução para a função excede o valor padrão de
3
segundos, então, o tempo limite é definido como30
segundos. Se você não especificar um timeout suficientemente longo, o Lambda poderá atingi-lo antes de a função ser concluída e fazer com que a criação da pilha falhe. -
A propriedade
Role
usa a funçãoFn::GetAtt
para obter o ARN do perfil de execuçãoLambdaExecutionRole
que é declarado em outro ponto no modelo.
JSON
"AMIInfoFunction": { "Type": "AWS::Lambda::Function", "Properties": { "Code": { "S3Bucket": { "Ref": "S3Bucket" }, "S3Key": { "Ref": "S3Key" } }, "Handler": { "Fn::Join" : [ "", [{ "Ref": "ModuleName" },".handler"] ] }, "Runtime": "nodejs18.x", "Timeout": "30", "Role": { "Fn::GetAtt" : ["LambdaExecutionRole", "Arn"] } } }
YAML
AMIInfoFunction: Type: AWS::Lambda::Function Properties: Code: S3Bucket: !Ref S3Bucket S3Key: !Ref S3Key Handler: !Sub "${ModuleName}.handler" Runtime: nodejs18.x Timeout: 30 Role: !GetAtt LambdaExecutionRole.Arn
LambdaExecutionRole
do recurso AWS::IAM::Role
A função de execução concede permissão à função do Lambda para enviar logs à AWS e chamar a API DescribeImages
do EC2.
JSON
"LambdaExecutionRole": { "Type": "AWS::IAM::Role", "Properties": { "AssumeRolePolicyDocument": { "Version": "2012-10-17", "Statement": [{ "Effect": "Allow", "Principal": {"Service": ["lambda.amazonaws.com"]}, "Action": ["sts:AssumeRole"] }] }, "Path": "/", "Policies": [{ "PolicyName": "root", "PolicyDocument": { "Version": "2012-10-17", "Statement": [{ "Effect": "Allow", "Action": ["logs:CreateLogGroup","logs:CreateLogStream","logs:PutLogEvents"], "Resource": "arn:aws:logs:*:*:*" }, { "Effect": "Allow", "Action": ["ec2:DescribeImages"], "Resource": "*" }] } }] } }
YAML
LambdaExecutionRole: Type: AWS::IAM::Role Properties: AssumeRolePolicyDocument: Version: '2012-10-17' Statement: - Effect: Allow Principal: Service: - lambda.amazonaws.com Action: - sts:AssumeRole Path: "/" Policies: - PolicyName: root PolicyDocument: Version: '2012-10-17' Statement: - Effect: Allow Action: - logs:CreateLogGroup - logs:CreateLogStream - logs:PutLogEvents Resource: arn:aws:logs:*:*:* - Effect: Allow Action: - ec2:DescribeImages Resource: "*"
AMIInfo
do recurso Custom::AMIInfo
Para os modelos do Linux e do Windows, o recurso personalizado invoca a função do Lambda correspondente. Para associar uma função a um recurso personalizado, especifique o ARN da função para a propriedade ServiceToken
, usando a função intrínseca Fn::GetAtt
. O CloudFormation envia as propriedades adicionais incluídas na instrução do recurso personalizado, como Region
e Architecture
, para a função do Lambda como entradas. A função Lambda determina os nomes e valores corretos para essas propriedades de entrada.
JSON
"AMIInfo": { "Type": "Custom::AMIInfo", "Properties": { "ServiceToken": { "Fn::GetAtt" : ["AMIInfoFunction", "Arn"] }, "Region": { "Ref": "AWS::Region" }, "Architecture": { "Fn::FindInMap" : [ "AWSInstanceType2Arch", { "Ref" : "InstanceType" }, "Arch" ] } } }
YAML
AMIInfo: Type: Custom::AMIInfo Properties: ServiceToken: !GetAtt AMIInfoFunction.Arn Region: !Ref "AWS::Region" Architecture: Fn::FindInMap: - AWSInstanceType2Arch - !Ref InstanceType - Arch
Para o Windows, o recurso personalizado fornece a versão do Windows à função Lambda, em vez da arquitetura da instância.
JSON
"AMIInfo": { "Type": "Custom::AMIInfo", "Properties": { "ServiceToken": { "Fn::GetAtt": ["AMIInfoFunction", "Arn"] }, "Region": { "Ref": "AWS::Region" }, "OSName": { "Ref": "WindowsVersion" } } }
YAML
AMIInfo: Type: Custom::AMIInfo Properties: ServiceToken: !GetAtt AMIInfoFunction.Arn Region: !Ref "AWS::Region" OSName: !Ref "WindowsVersion"
Quando o CloudFormation invoca a função do Lambda, a função chama a API DescribeImages
do EC2 usando a Região da AWS e a arquitetura da instância ou o nome do sistema operacional para filtrar a lista de imagens. Em seguida, a função classifica a lista de imagens por data e retorna o ID da AMI mais recente.
Ao retornar o ID da AMI mais recente, a função envia o ID para um pre-signed URL na propriedade Data
do objeto de resposta. Os dados são estruturados como um par nome-valor, como mostrado no exemplo a seguir:
"Data": { "Id": "ami-02354e95b3example" }
SampleInstance
do recurso AWS::EC2::Instance
O seguinte trecho mostra como obter os dados de uma função Lambda. Ele usa a função intrínseca Fn::GetAtt
, fornecendo o nome do recurso personalizado e o nome de atributo do valor a ser obtido. Nessas descrição, o nome do recurso personalizado é AMIInfo
e o nome do atributo é Id
.
JSON
"SampleInstance": { "Type": "AWS::EC2::Instance", "Properties": { "InstanceType" : { "Ref": "InstanceType" }, "ImageId": { "Fn::GetAtt": [ "AMIInfo", "Id" ] } } }
YAML
SampleInstance: Type: AWS::EC2::Instance Properties: InstanceType: !Ref InstanceType ImageId: !GetAtt AMIInfo.Id
Pré-requisitos
Antes de concluir as etapas para criar a pilha, você já deve ter um bucket do Amazon S3. Quando você criar uma pilha com uma função Lambda, especifique o local do bucket do Amazon S3 que contém o código-fonte da função. O bucket deve estar na mesma Região da AWS em que você criou a pilha. Para obter mais informações sobre como criar um bucket, consulte Criar um bucket, no Guia do usuário do Amazon Simple Storage Service.
Deve ter também as permissões do IAM para usar todos os serviços correspondentes, como o Lambda, o Amazon EC2 e o CloudFormation.
Etapa 1: salvar o exemplo de pacote do Lambda no Amazon S3
Nesta etapa, você carrega o exemplo de pacote do Lambda (um arquivo .zip
) no bucket do Amazon S3.
Esse pacote do Lambda contém o código-fonte da função do Lambda e as bibliotecas necessárias. Para esta descrição, a função não exige bibliotecas adicionais.
Para salvar o exemplo de pacote no Amazon S3
-
Faça download do pacote de amostra do Amazon S3. Quando você salvar o arquivo, use o mesmo nome de arquivo que a amostra,
amilookup.zip
ouamilookup-win.zip
.- Pesquisar IDs de AMI do Linux
-
https://s3.amazonaws.com/cloudformation-examples/lambda/amilookup.zip
- Pesquisar IDs de AMI do Windows
-
https://s3.amazonaws.com/cloudformation-examples/lambda/amilookup-win.zip
-
Abra o console do Amazon S3 em https://console.aws.amazon.com/s3/home
. -
Na barra de navegação no alto da tela, escolha a Região da AWS em que você criou o bucket do Amazon S3.
-
Na lista Buckets, escolha o nome do bucket. Anote o nome do bucket, pois você o usará quando criar a pilha.
-
Escolha Carregar.
-
Em Carregar, para Arquivos e pastas, carregue o exemplo de pacote no bucket. Para obter mais informações, consulte Fazer upload de objetos no Guia do usuário do Amazon Simple Storage Service.
Etapa 2: iniciar a pilha
Nesta etapa, você inicia uma pilha a partir de um exemplo de modelo. A pilha inclui uma função do Lambda, um perfil do IAM (perfil de execução), um recurso personalizado que invoca a função e uma instância do EC2 que usa os resultados da função.
Durante a criação da pilha, o recurso personalizado invoca a função Lambda e espera ela enviar uma resposta para o pre-signed URL do Amazon S3. Na resposta, a função retornará o ID da AMI mais recente que corresponde ao tipo de instância do EC2 e à Região da AWS na qual a instância está sendo criada. Os dados de resposta da função são armazenados como um atributo do recurso personalizado, que é usado para especificar o ID da AMI da instância EC2.
Para criar a pilha
-
Abra o console do CloudFormation em https://console.aws.amazon.com/cloudformation/
. -
Selecione Create Stack (Criar pilha).
-
Na seção Template (Modelo), selecione Specify an Amazon S3 template URL (Especificar um URL de modelo do &S3;) e, em seguida, copie e cole o seguinte URL na caixa de texto:
- Modelo do Linux
-
https://s3.amazonaws.com/cloudformation-examples/lambda/LambdaAMILookupSample.template
- Modelo do Windows
-
https://s3.amazonaws.com/cloudformation-examples/lambda/LambdaAMILookupSample-win.template
-
Escolha Próximo.
-
No campo Stack name (Nome da pilha), digite
SampleEC2Instance
. -
Na seção Parameters (Parâmetros), especifique o nome do bucket do Amazon S3 que você criou e, em seguida, escolha Next (Próximo).
Os valores padrão dos outros parâmetros são os mesmos nomes usados no pacote
.zip
de amostra. -
Para esta demonstração, você não precisa adicionar tags ou especificar configurações avançadas, portanto escolha Próximo.
-
Certifique-se de que o nome da pilha e o modelo de URL estão corretos e, em seguida, escolha Criar.
Pode levar alguns minutos para que o CloudFormation crie a pilha. Para monitorar o progresso, visualize os eventos da pilha. Para ter mais informações, consulte Visualizar dados e recursos da pilha do AWS CloudFormation no AWS Management Console.
Se a criação da pilha for bem-sucedida, todos os recursos na pilha, como a função Lambda, o recurso personalizado e a instância EC2, terão sido criados. Você usou com êxito uma função Lambda e um recurso personalizado para especificar o ID da AMI e uma instância EC2. Não é preciso criar e manter um mapeamento de IDs de AMI neste modelo.
Para visualizar qual ID da AMI o CloudFormation usou para criar a instância do EC2, confira as saídas da pilha.
Se a função do Lambda retornar um erro, visualize os logs da função no console
Etapa 3: Limpar os recursos
Exclua a pilha para limpar todos os recursos de pilha criados; assim, você não será cobrado por recursos desnecessários.
Para excluir a pilha
-
No console do CloudFormation, escolha a pilha SampleEC2Instance.
-
Escolha Ações e, em seguida, Excluir pilha.
-
Na mensagem de confirmação, escolha Sim, excluir.
Todos os recursos que você criou serão excluídos.
Agora que você compreende como criar e usar as funções do Lambda com o CloudFormation, é possível usar o modelo e o código de amostra do presente passo a passo para desenvolver outras pilhas e funções.