将使用Terraform构建的资源信息传递给 AWS SAM

首先

本文将解释如何将使用Terraform构建的资源信息传递给AWS SAM模板。

在示例代码中,我们使用Terraform来管理VPC、子网、安全组等网络相关资源,使用AWS SAM来管理Lambda函数。

这个案例的整体构成

terraform_resource_export.png

本案例的示例代码

 

文件夹结构

aws-tf-resource-export-sample
├── main.tf
├── provider.tf
├── src
│   └── lambda_function.py
├── template.yaml
└── tf-resource-export.yml

Terraform 代码

我正在使用 AWS CloudFormation Stack 来构建一个包含资源信息(在这里是 SunbetId 和 SecurityGroupId)并嵌入到 CloudFormation 模板的 Outputs 部分的堆栈。

#
# リソースの情報をCloudformationのOutputs機能を使ってエクスポートする
# このStackでTerraformのバックエンド用のリソースを作成する
#
resource "aws_cloudformation_stack" "this" {
  name = "tf-resource-export-sample"

  template_body = templatefile("./tf-resource-export.yml", {

    # tfstateのリソース作成用
    tfstate_backend = {
      s3_bucket_name          = "tf-resource-export-sample"
      dynamodb_for_state_lock = "tf-resource-export-sample"
    },

    # サブネット情報のOutputs用
    network = {
      private_subnet_1a_name = "PrivateSubnet1a"
      private_subnet_1a_id   = module.network.private_subnets[0]
      private_subnet_1c_name = "PrivateSubnet1c"
      private_subnet_1c_id   = module.network.private_subnets[1]
    },

    # セキュリティグループ情報のOutputs用
    security_group = {
      name_for_lambda = "HelloWorldFunctionSG"
      id_for_lambda   = aws_security_group.this.id
    }
  })
}

#
# Terraformで構築するリソース
#
*** 以下、省略 ***

CloudFormation 模板

AWSTemplateFormatVersion: "2010-09-09"
Description: "Terraform Resource info Export Template"

Resources:
  TfStateBucket:
    Type: AWS::S3::Bucket
    DeletionPolicy: Retain
    Properties:
      BucketName: ${tfstate_backend["s3_bucket_name"]}
      PublicAccessBlockConfiguration:
        BlockPublicAcls: true
        BlockPublicPolicy: true
        IgnorePublicAcls: true
        RestrictPublicBuckets: true

  TfStateLockTable:
    Type: AWS::DynamoDB::Table
    Properties:
      TableName: ${tfstate_backend["dynamodb_for_state_lock"]}
      ProvisionedThroughput:
        ReadCapacityUnits: 1
        WriteCapacityUnits: 1
      AttributeDefinitions:
        - AttributeName: "LockID"
          AttributeType: "S"
      KeySchema:
        - AttributeName: "LockID"
          KeyType: "HASH"

#
# Terraform で構築したリソースの情報をこのOutputsセクションに組み込みます。
#
Outputs:
  PrivateSubnet1a:
    Description: "Id for PrivateSubnet 1a"
    Export:
      Name: ${network["private_subnet_1a_name"]}
    Value: ${network["private_subnet_1a_id"]}

  PrivateSubnet1c:
    Description: "Id for PrivateSubnet 1c"
    Export:
      Name: ${network["private_subnet_1c_name"]}
    Value: ${network["private_subnet_1c_id"]}

  HelloWorldFunctionSG:
    Description: "Security Group for HelloWorldFunction"
    Export:
      Name: ${security_group["name_for_lambda"]}
    Value: ${security_group["id_for_lambda"]}

由于CloudFormation模板必须包含Resources且不能仅包括Outputs,因此在这个示例代码中,我们构建了一个用于管理Terraform tfstate的后端资源,将其放置在Resources部分。

AWS SAM的代码

使用Fn::ImportValue内置函数,将由Terraform构建的Stack的Outputs值嵌入到AWS SAM模板中,以进行跨Stack引用。

AWSTemplateFormatVersion: "2010-09-09"
Transform: AWS::Serverless-2016-10-31
Description: "Lambda Function SAM Template"

Resources:
  HelloWorldFunction:
    Type: AWS::Serverless::Function
    Properties:
      FunctionName: HelloWorldFunction
      Handler: lambda_function.lambda_handler
      Runtime: python3.9
      CodeUri: ./src/
      Timeout: 10
      MemorySize: 128
#
# Fn::ImportValue 組み込み関数で値をインポートします。
#
      VpcConfig:
        SecurityGroupIds:
          - !ImportValue HelloWorldFunctionSG
        SubnetIds:
          - !ImportValue PrivateSubnet1a
          - !ImportValue PrivateSubnet1c
      Policies:
        - AWSLambdaVPCAccessExecutionRole
        - AWSLambdaBasicExecutionRole

Outputs:
  HelloWorldFunction:
    Description: "HelloWorldFunction ARN"
    Value: !GetAtt HelloWorldFunction.Arn

通过这样做,您可以将由Terraform构建的资源信息传递给AWS SAM。

本案例的部署步骤

我将使用Terraform和AWS SAM实际部署本案例,并提供相关步骤说明。

部署流程确认环境。

$ terraform -version
Terraform v1.4.4
on darwin_amd64
+ provider registry.terraform.io/hashicorp/aws v4.62.0

$ sam --version
SAM CLI, version 1.79.0

执行Terraform

资源的建设

使用Terraform构建网络相关资源并将其信息嵌入到输出部分的Stack。

$ export AWS_PROFILE= [ YOUR AWS ACCOUNT PROFILE NAME ]
$ terraform init
Initializing the backend...
Successfully configured the backend "local"! Terraform will automatically

$ terraform plan
Plan: 9 to add, 0 to change, 0 to destroy.

$ terraform apply
Apply complete! Resources: 9 added, 0 changed, 0 destroyed.

更改管理tfstate的后端

请将provider.tf文件内tfstate的后端从Local更改为S3。

  #backend "local" {
  #  path = "terraform.tfstate"
  #}

  backend "s3" {
    bucket         = "tf-resource-export-sample"
    key            = "terraform.tfstate"
    dynamodb_table = "tf-resource-export-sample"
    region         = "ap-northeast-1"
  }

执行下面的命令,将tfstate的管理后端从本地改为S3。

$ terraform init -migrate-state

Initializing the backend...
Terraform detected that the backend type changed from "local" to "s3".

Do you want to copy existing state to the new backend?
  Pre-existing state was found while migrating the previous "local" backend to the
  newly configured "s3" backend. No existing state was found in the newly
  configured "s3" backend. Do you want to copy this state to the new "s3"
  backend? Enter "yes" to copy and "no" to start with an empty state.

  Enter a value: yes 

请执行以下命令,以确认tfstate已保存在S3上。

$ aws s3 ls s3://tf-resource-export-sample
9999-99-99 99:99:99      13870 terraform.tfstate

执行AWS SAM

构建Lambda函数

运行以下命令,在AWS SAM模板中部署Lambda函数。

sam deploy --template-file template.yaml \
           --stack-name tf-resource-import-sample \
           --resolve-s3 \
           --capabilities CAPABILITY_IAM \
           --region ap-northeast-1

CloudFormation stack changeset
---------------------------------------------------------------------------------------------------------------------------------
Operation                        LogicalResourceId                ResourceType                     Replacement                    
---------------------------------------------------------------------------------------------------------------------------------
+ Add                            HelloWorldFunctionRole           AWS::IAM::Role                   N/A                            
+ Add                            HelloWorldFunction               AWS::Lambda::Function            N/A                            
---------------------------------------------------------------------------------------------------------------------------------

我已经部署成功了。

CloudFormation outputs from deployed stack
---------------------------------------------------------------------------------------------------------------------------------
Outputs                                                                                                                         
---------------------------------------------------------------------------------------------------------------------------------
Key                 HelloWorldFunction                                                                                          
Description         HelloWorldFunction ARN                                                                                      
Value               arn:aws:lambda:ap-northeast-1:999999999999:function:HelloWorldFunction                                      
---------------------------------------------------------------------------------------------------------------------------------

Successfully created/updated stack - tf-resource-import-sample in ap-northeast-1

确认行动

使用下面的命令来执行已部署的Lambda函数。

$ aws lambda invoke --function-name HelloWorldFunction /dev/stdout
{"statusCode": 200, "body": "{\"message\": \"Hello World!\"}"}
    "StatusCode": 200,
    "ExecutedVersion": "$LATEST"
}

清理

删除Lambda函数

使用以下命令将通过AWS SAM模板部署的Lambda函数删除。

$ sam delete --stack-name tf-resource-import-sample
        Are you sure you want to delete the stack tf-resource-import-sample in the region ap-northeast-1 ? [y/N]: y
        Do you want to delete the template file 71b91735b453182a1c33df8bceda4df3.template in S3? [y/N]: y

Deleted successfully

更改tfstate的后端管理

将provider.tf文件中的tfstate后端从S3更改为本地。

  backend "local" {
    path = "terraform.tfstate"
  }

  #backend "s3" {
  #  bucket         = "tf-resource-export-sample"
  #  key            = "terraform.tfstate"
  #  dynamodb_table = "tf-resource-export-sample"
  #  region         = "ap-northeast-1"
  #}

执行以下命令,将tfstate管理后端从S3更改为本地。

$ terraform init -migrate-state -lock=false

Initializing the backend...
Terraform detected that the backend type changed from "s3" to "local".

Do you want to copy existing state to the new backend?
  Pre-existing state was found while migrating the previous "s3" backend to the
  newly configured "local" backend. No existing state was found in the newly
  configured "local" backend. Do you want to copy this state to the new "local"
  backend? Enter "yes" to copy and "no" to start with an empty state.

  Enter a value: yes

删除资源

使用下面的命令删除每个资源。

$ terraform destroy
Destroy complete! Resources: 9 destroyed.

使用以下命令删除用于tfstate的S3存储桶。

$ aws s3 rb s3://tf-resource-export-sample --force        
delete: s3://tf-resource-export-sample/terraform.tfstate
remove_bucket: tf-resource-export-sample

以上就是。

最后

這只是一個例子,希望能對您有所幫助。

广告
将在 10 秒后关闭
bannerAds