使用 AWS lambda 进行 Terraform
Terraform with AWS lamda
我真的找不到任何与我的问题相关的内容。我正在创建一个 Tf 脚本,它将触发 lambda、cloudwatch 事件和 IAM,以停止和启动我环境中的一些 ec2。请看下面我的代码,请告诉我我做错了什么!!
main.tf
#
# Test
#
provider "aws" {
region = "us-gov-west-1"
shared_credentials_file = "~/.aws/credentials"
profile = "default"
}
resource "aws_iam_policy" "stop_start_ec2_policy" {
name = "StopStartEC2Policy"
path = "/"
description = "IAM policy for stop and start EC2 from a lambda"
policy = <<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"logs:CreateLogGroup",
"logs:CreateLogStream",
"logs:PutLogEvents"
],
"Resource": "arn:aws-us-gov:logs:*:*:*"
},
{
"Effect": "Allow",
"Action": [
"ec2:Start*",
"ec2:Stop*",
"ec2:DescribeInstances*"
],
"Resource": "*"
}
]
}
EOF
}
resource "aws_iam_role" "stop_start_ec2_role" {
name = "StopStartEC2Role"
assume_role_policy = <<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Action": "sts:AssumeRole",
"Principal": {
"Service": "lambda.amazonaws.com"
},
"Effect": "Allow",
"Sid": ""
}
]
}
EOF
}
resource "aws_iam_role_policy_attachment" "lambda_role_policy" {
role = "${aws_iam_role.stop_start_ec2_role.name}"
policy_arn = "${aws_iam_policy.stop_start_ec2_policy.arn}"
}
resource "aws_lambda_function" "stop_ec2_lambda" {
filename = "ec2_lambda_handler.zip"
function_name = "stopEC2Lambda"
role = "${aws_iam_role.stop_start_ec2_role.arn}"
handler = "ec2_lambda_handler.stop"
source_code_hash = "${filebase64sha256("ec2_lambda_handler.zip")}"
runtime = "python3.7"
memory_size = "250"
timeout = "60"
}
resource "aws_cloudwatch_event_rule" "ec2_stop_rule" {
name = "StopEC2Instances"
description = "Stop EC2 nodes at 19:00 from Monday to friday"
schedule_expression = "cron(0 19 ? * 2-6 *)"
}
resource "aws_cloudwatch_event_target" "ec2_stop_rule_target" {
rule = "${aws_cloudwatch_event_rule.ec2_stop_rule.name}"
arn = "${aws_lambda_function.stop_ec2_lambda.arn}"
}
resource "aws_lambda_permission" "allow_cloudwatch_stop" {
statement_id = "AllowExecutionFromCloudWatch"
action = "lambda:InvokeFunction"
function_name = "${aws_lambda_function.stop_ec2_lambda.function_name}"
principal = "events.amazonaws.com"
}
resource "aws_lambda_function" "start_ec2_lambda" {
filename = "ec2_lambda_handler.zip"
function_name = "startEC2Lambda"
role = "${aws_iam_role.stop_start_ec2_role.arn}"
handler = "ec2_lambda_handler.start"
source_code_hash = "${filebase64sha256("ec2_lambda_handler.zip")}"
runtime = "python3.7"
memory_size = "250"
timeout = "60"
}
resource "aws_cloudwatch_event_rule" "ec2_start_rule" {
name = "StartEC2Instances"
description = "Start EC2 nodes at 6:30 from Monday to friday"
schedule_expression = "cron(30 6 ? * 2-6 *)"
}
resource "aws_cloudwatch_event_target" "ec2_start_rule_target" {
rule = "${aws_cloudwatch_event_rule.ec2_start_rule.name}"
arn = "${aws_lambda_function.start_ec2_lambda.arn}"
}
resource "aws_lambda_permission" "allow_cloudwatch_start" {
statement_id = "AllowExecutionFromCloudWatch"
action = "lambda:InvokeFunction"
function_name = "${aws_lambda_function.start_ec2_lambda.function_name}"
principal = "events.amazonaws.com"
}
我的ec2_lambda_handler.py
import boto3
region = 'eu-central-1'
ec2 = boto3.client('ec2', region_name=region)
response = ec2.describe_instances(Filters=[
{
'Name': 'tag:Auto-Start',
'Values': [
'true',
]
},
])
instances = []
for reservation in response["Reservations"]:
for instance in reservation["Instances"]:
instances.append(instance["InstanceId"])
def stop(event, context):
ec2.stop_instances(InstanceIds=instances)
print('stopped instances: ' + str(instances))
def start(event, context):
ec2.start_instances(InstanceIds=instances)
print('started instances: ' + str(instances))
我遇到的错误:
Plan: 11 to add, 0 to change, 0 to destroy.
Warning: Interpolation-only expressions are deprecated
on main.tf line 65, in resource "aws_iam_role_policy_attachment" "lambda_role_policy":
65: role = "${aws_iam_role.stop_start_ec2_role.name}"
Terraform 0.11 and earlier required all non-constant expressions to be
provided via interpolation syntax, but this pattern is now deprecated. To
silence this warning, remove the "${ sequence from the start and the }"
sequence from the end of this expression, leaving just the inner expression.
Template interpolation syntax is still used to construct strings from
expressions when the template includes multiple interpolation sequences or a
mixture of literal strings and interpolations. This deprecation applies only
to templates that consist entirely of a single interpolation sequence.
(and 9 more similar warnings elsewhere)
Do you want to perform these actions?
Terraform will perform the actions described above.
Only 'yes' will be accepted to approve.
Enter a value: yes
aws_iam_policy.stop_start_ec2_policy: Creating...
aws_cloudwatch_event_rule.ec2_start_rule: Creating...
aws_iam_role.stop_start_ec2_role: Creating...
aws_cloudwatch_event_rule.ec2_stop_rule: Creating...
aws_iam_role.stop_start_ec2_role: Creation complete after 1s [id=StopStartEC2Role]
aws_lambda_function.stop_ec2_lambda: Creating...
aws_lambda_function.start_ec2_lambda: Creating...
aws_cloudwatch_event_rule.ec2_start_rule: Creation complete after 2s [id=StartEC2Instances]
aws_cloudwatch_event_rule.ec2_stop_rule: Creation complete after 2s [id=StopEC2Instances]
aws_iam_policy.stop_start_ec2_policy: Creation complete after 2s [id=arn:aws-us-gov:iam::235856440647:policy/StopStartEC2Policy]
aws_iam_role_policy_attachment.lambda_role_policy: Creating...
aws_iam_role_policy_attachment.lambda_role_policy: Creation complete after 0s [id=StopStartEC2Role-20210211225204032900000001]
Error: Unable to load "ec2_lambda_handler.zip": open ec2_lambda_handler.zip: no such file or directory
我的目录:
$ ls
ec2_lambda_handler.py main.tf
我感觉在 Terraform 运行之前 zip 文件不存在,但不确定如何解决这个问题!!请帮忙!!!!这里的源代码:https://medium.com/better-programming/minimize-the-costs-of-running-aws-ec2-instances-using-terraform-3999c5141830
您根本没有创建 zip。你只有 ec2_lambda_handler.py
。通常,在使用 lambda 函数之前,您会使用 archive_file 对其进行压缩:
data "archive_file" "zip" {
type = "zip"
source_file = "ec2_lambda_handler.py"
output_path = "ec2_lambda_handler.zip"
}
然后在你的 lambda 中:
resource "aws_lambda_function" "stop_ec2_lambda" {
filename = data.archive_file.zip.output_path
function_name = "stopEC2Lambda"
role = "${aws_iam_role.stop_start_ec2_role.arn}"
handler = "ec2_lambda_handler.stop"
source_code_hash = data.archive_file.zip.output_base64sha256
runtime = "python3.7"
memory_size = "250"
timeout = "60"
}
这是我用的:
resource "aws_lambda_function" "lambda" {
filename = "deployment-files/lambda_logs/file.zip"
function_name = "${var.teamid}-${var.prjid}"
role = var.role
handler = var.handler
source_code_hash = base64sha256("file.zip")
runtime = var.runtime == "" ? "null" : var.runtime
memory_size = var.memory_size == "" ? "null" : var.memory_size
timeout = var.timeout == "" ? "null" : var.timeout
description = var.description == "" ? "null" : var.description
tags = merge(local.shared_tags)
environment {
variables = var.environment_vars
}
}
其中 payload_file 是 本地压缩文件路径 和
source_code_hash 是 lambda
里面的文件名
我真的找不到任何与我的问题相关的内容。我正在创建一个 Tf 脚本,它将触发 lambda、cloudwatch 事件和 IAM,以停止和启动我环境中的一些 ec2。请看下面我的代码,请告诉我我做错了什么!!
main.tf
#
# Test
#
provider "aws" {
region = "us-gov-west-1"
shared_credentials_file = "~/.aws/credentials"
profile = "default"
}
resource "aws_iam_policy" "stop_start_ec2_policy" {
name = "StopStartEC2Policy"
path = "/"
description = "IAM policy for stop and start EC2 from a lambda"
policy = <<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"logs:CreateLogGroup",
"logs:CreateLogStream",
"logs:PutLogEvents"
],
"Resource": "arn:aws-us-gov:logs:*:*:*"
},
{
"Effect": "Allow",
"Action": [
"ec2:Start*",
"ec2:Stop*",
"ec2:DescribeInstances*"
],
"Resource": "*"
}
]
}
EOF
}
resource "aws_iam_role" "stop_start_ec2_role" {
name = "StopStartEC2Role"
assume_role_policy = <<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Action": "sts:AssumeRole",
"Principal": {
"Service": "lambda.amazonaws.com"
},
"Effect": "Allow",
"Sid": ""
}
]
}
EOF
}
resource "aws_iam_role_policy_attachment" "lambda_role_policy" {
role = "${aws_iam_role.stop_start_ec2_role.name}"
policy_arn = "${aws_iam_policy.stop_start_ec2_policy.arn}"
}
resource "aws_lambda_function" "stop_ec2_lambda" {
filename = "ec2_lambda_handler.zip"
function_name = "stopEC2Lambda"
role = "${aws_iam_role.stop_start_ec2_role.arn}"
handler = "ec2_lambda_handler.stop"
source_code_hash = "${filebase64sha256("ec2_lambda_handler.zip")}"
runtime = "python3.7"
memory_size = "250"
timeout = "60"
}
resource "aws_cloudwatch_event_rule" "ec2_stop_rule" {
name = "StopEC2Instances"
description = "Stop EC2 nodes at 19:00 from Monday to friday"
schedule_expression = "cron(0 19 ? * 2-6 *)"
}
resource "aws_cloudwatch_event_target" "ec2_stop_rule_target" {
rule = "${aws_cloudwatch_event_rule.ec2_stop_rule.name}"
arn = "${aws_lambda_function.stop_ec2_lambda.arn}"
}
resource "aws_lambda_permission" "allow_cloudwatch_stop" {
statement_id = "AllowExecutionFromCloudWatch"
action = "lambda:InvokeFunction"
function_name = "${aws_lambda_function.stop_ec2_lambda.function_name}"
principal = "events.amazonaws.com"
}
resource "aws_lambda_function" "start_ec2_lambda" {
filename = "ec2_lambda_handler.zip"
function_name = "startEC2Lambda"
role = "${aws_iam_role.stop_start_ec2_role.arn}"
handler = "ec2_lambda_handler.start"
source_code_hash = "${filebase64sha256("ec2_lambda_handler.zip")}"
runtime = "python3.7"
memory_size = "250"
timeout = "60"
}
resource "aws_cloudwatch_event_rule" "ec2_start_rule" {
name = "StartEC2Instances"
description = "Start EC2 nodes at 6:30 from Monday to friday"
schedule_expression = "cron(30 6 ? * 2-6 *)"
}
resource "aws_cloudwatch_event_target" "ec2_start_rule_target" {
rule = "${aws_cloudwatch_event_rule.ec2_start_rule.name}"
arn = "${aws_lambda_function.start_ec2_lambda.arn}"
}
resource "aws_lambda_permission" "allow_cloudwatch_start" {
statement_id = "AllowExecutionFromCloudWatch"
action = "lambda:InvokeFunction"
function_name = "${aws_lambda_function.start_ec2_lambda.function_name}"
principal = "events.amazonaws.com"
}
我的ec2_lambda_handler.py
import boto3
region = 'eu-central-1'
ec2 = boto3.client('ec2', region_name=region)
response = ec2.describe_instances(Filters=[
{
'Name': 'tag:Auto-Start',
'Values': [
'true',
]
},
])
instances = []
for reservation in response["Reservations"]:
for instance in reservation["Instances"]:
instances.append(instance["InstanceId"])
def stop(event, context):
ec2.stop_instances(InstanceIds=instances)
print('stopped instances: ' + str(instances))
def start(event, context):
ec2.start_instances(InstanceIds=instances)
print('started instances: ' + str(instances))
我遇到的错误:
Plan: 11 to add, 0 to change, 0 to destroy.
Warning: Interpolation-only expressions are deprecated
on main.tf line 65, in resource "aws_iam_role_policy_attachment" "lambda_role_policy":
65: role = "${aws_iam_role.stop_start_ec2_role.name}"
Terraform 0.11 and earlier required all non-constant expressions to be
provided via interpolation syntax, but this pattern is now deprecated. To
silence this warning, remove the "${ sequence from the start and the }"
sequence from the end of this expression, leaving just the inner expression.
Template interpolation syntax is still used to construct strings from
expressions when the template includes multiple interpolation sequences or a
mixture of literal strings and interpolations. This deprecation applies only
to templates that consist entirely of a single interpolation sequence.
(and 9 more similar warnings elsewhere)
Do you want to perform these actions?
Terraform will perform the actions described above.
Only 'yes' will be accepted to approve.
Enter a value: yes
aws_iam_policy.stop_start_ec2_policy: Creating...
aws_cloudwatch_event_rule.ec2_start_rule: Creating...
aws_iam_role.stop_start_ec2_role: Creating...
aws_cloudwatch_event_rule.ec2_stop_rule: Creating...
aws_iam_role.stop_start_ec2_role: Creation complete after 1s [id=StopStartEC2Role]
aws_lambda_function.stop_ec2_lambda: Creating...
aws_lambda_function.start_ec2_lambda: Creating...
aws_cloudwatch_event_rule.ec2_start_rule: Creation complete after 2s [id=StartEC2Instances]
aws_cloudwatch_event_rule.ec2_stop_rule: Creation complete after 2s [id=StopEC2Instances]
aws_iam_policy.stop_start_ec2_policy: Creation complete after 2s [id=arn:aws-us-gov:iam::235856440647:policy/StopStartEC2Policy]
aws_iam_role_policy_attachment.lambda_role_policy: Creating...
aws_iam_role_policy_attachment.lambda_role_policy: Creation complete after 0s [id=StopStartEC2Role-20210211225204032900000001]
Error: Unable to load "ec2_lambda_handler.zip": open ec2_lambda_handler.zip: no such file or directory
我的目录:
$ ls
ec2_lambda_handler.py main.tf
我感觉在 Terraform 运行之前 zip 文件不存在,但不确定如何解决这个问题!!请帮忙!!!!这里的源代码:https://medium.com/better-programming/minimize-the-costs-of-running-aws-ec2-instances-using-terraform-3999c5141830
您根本没有创建 zip。你只有 ec2_lambda_handler.py
。通常,在使用 lambda 函数之前,您会使用 archive_file 对其进行压缩:
data "archive_file" "zip" {
type = "zip"
source_file = "ec2_lambda_handler.py"
output_path = "ec2_lambda_handler.zip"
}
然后在你的 lambda 中:
resource "aws_lambda_function" "stop_ec2_lambda" {
filename = data.archive_file.zip.output_path
function_name = "stopEC2Lambda"
role = "${aws_iam_role.stop_start_ec2_role.arn}"
handler = "ec2_lambda_handler.stop"
source_code_hash = data.archive_file.zip.output_base64sha256
runtime = "python3.7"
memory_size = "250"
timeout = "60"
}
这是我用的:
resource "aws_lambda_function" "lambda" {
filename = "deployment-files/lambda_logs/file.zip"
function_name = "${var.teamid}-${var.prjid}"
role = var.role
handler = var.handler
source_code_hash = base64sha256("file.zip")
runtime = var.runtime == "" ? "null" : var.runtime
memory_size = var.memory_size == "" ? "null" : var.memory_size
timeout = var.timeout == "" ? "null" : var.timeout
description = var.description == "" ? "null" : var.description
tags = merge(local.shared_tags)
environment {
variables = var.environment_vars
}
}
其中 payload_file 是 本地压缩文件路径 和 source_code_hash 是 lambda
里面的文件名