将使用Terraform构建的资源信息传递给 AWS SAM
首先
本文将解释如何将使用Terraform构建的资源信息传递给AWS SAM模板。
在示例代码中,我们使用Terraform来管理VPC、子网、安全组等网络相关资源,使用AWS SAM来管理Lambda函数。
这个案例的整体构成
本案例的示例代码
文件夹结构
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
以上就是。
最后
這只是一個例子,希望能對您有所幫助。