昨日刚刚体验了 Terraform 是一个什么鬼东西 Terraform 使用 - 从最简单例子开始,今天再进一步。将来尝试的是使用 Terraform 来部署一个 Lambda 应用,并创建相关的资源。
本例中的 Lambda 要由 Kinesis 来触发,并写数据到 S3 Bucket 中去,所以需要做的事情大致如下:
- 创建 IAM Role, 该 Role 要能访问 S3, Kinesis 和 CloudWatch
- 创建一个 Kinesis Stream (指定 Shard 数目)
- 创建一个 S3 Bucket
- 部署 Lambda (要指定能访问 S3 Bucket 的 Role, 并其他参数,如环境变量)
- 设置 Lambda 的 Kinesis 触发器 (指定源 Kinesis Stream 和 batchSize)
以下是 Lambda 的实现代码,从 Kinesis 读出字符串,逗号分割,第一部分作为 S3 Key, 第二部分作为文件内容写入到 S3 Bucket 中去。S3 Bucket 名称从环境变量中读取。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
public class Handler implements RequestHandler<KinesisEvent, String> { @Override public String handleRequest(KinesisEvent event, Context context) { LambdaLogger logger = context.getLogger(); event.getRecords().forEach(record -> { String data = new String(record.getKinesis().getData().array()); logger.log("Received data: " + data); String[] keyAndContent = data.split(","); ObjectMetadata objectMetadata = new ObjectMetadata(); objectMetadata.setContentLength(keyAndContent[1].getBytes().length); AmazonS3 s3Client = AmazonS3ClientBuilder.defaultClient(); s3Client.putObject(System.getenv("BUCKET_NAME"), keyAndContent[0], new ByteArrayInputStream(keyAndContent[1].getBytes()), objectMetadata); }); return null; } } |
接下来的事情全部要交给 Terraform 来完成了,在于怎么写那个 tf 文件,为方便起见我们直接在这个 Java 项目根目录下创建一个 main.tf
文件。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 |
provider "aws" { region = "us-east-1" shared_credentials_file = "/Users/Yanbin/.aws/credentials" //默认就是 ~/.aws/credentials profile = "yanbin" //默认是 default } resource "aws_s3_bucket" "test-bucket" { bucket = "yanbin-test-bucket" acl = "private" tags { Environment = "test" } } //resource 后第二个字符串 name "test-stream" 还是很有用的,后面引用就靠它 resource "aws_kinesis_stream" "test-stream" { name = "yanbin-test-stream" shard_count = 2 tags { Environment = "test" } } resource "aws_iam_role" "role_for_lambda" { name = "yanbin_lambda_role" //特别要注意这里的格式 <<EOF 是一整体,其中的 JSON 在下行一定要顶格写 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" "s3-access-policy-attachment" { role = "${aws_iam_role.role_for_lambda.name}" policy_arn = "arn:aws:iam::aws:policy/AmazonS3FullAccess" } resource "aws_iam_role_policy_attachment" "kinesis-access-policy-attachment" { role = "${aws_iam_role.role_for_lambda.name}" policy_arn = "arn:aws:iam::aws:policy/AmazonKinesisFullAccess" } resource "aws_iam_role_policy_attachment" "cloudWatch-access-policy-attachment" { role = "${aws_iam_role.role_for_lambda.name}" policy_arn = "arn:aws:iam::aws:policy/CloudWatchLogsFullAccess" } resource "aws_lambda_function" "yanbin-test-lambda" { filename = "target/hello-1.0.jar" function_name = "yanbin-test-lambda" role = "${aws_iam_role.role_for_lambda.arn}" handler = "cc.unmi.Handler" source_code_hash = "${base64sha256(file("target/hello-1.0.jar"))}" runtime = "java8" timeout = 300 memory_size = 512 description = "Test Lambda created by Terraform" environment { variables = { BUCKET_NAME = "yanbin-test-bucket" } } } resource "aws_lambda_event_source_mapping" "kinesis_trigger" { batch_size = 3 event_source_arn = "${aws_kinesis_stream.test-stream.arn}" enabled = true function_name = "${aws_lambda_function.yanbin-test-lambda.arn}" starting_position = "LATEST" } |
由于贴代码有些问题,所以直接截的图。main.tf
文件创建好,照例要在当前目录中运行 terraform init
先初始,而后才能执行 terraform plan|apply
等命令。编写好的 mail.tf
文件可以用 terraform fmt
帮我们格式化,在运行 terraform apply
之前最好运行一下 terraform plan
, 好知道将要发生什么事。
terraform apply
执行上面的配置,Terraform 将会做以下事情
- 创建 Bucket
yanbin-test-bucket
, 访问规则是 private, 设定 TagEnvironment = "test"
- 创建 Kinesis Stream
yanbin-test-stream
, Shard 数目是 2,设定 TagEnvironment = "test"
- 创建 IAM Role
yanbin-lambda_role
, 并赋予 S3, Kinesis, CloudWatch 的完全访问权限 - 上传程序包部署 Lambda
yanbin-test-lambda
, 并设置 role 为上一步创建的 role, 设置其他属性,及环境变量BUCKET
. 以后运行terraform plan
只有发现hello-1.0.jar
包的哈稀值变了才会更新 Lambda 程序包 - 为上面的 Lambda 创建一个 Kinesis Trigger, batchSize 为 3, 监听第 2 步创建的 Kinesis Stream
现在一切准备就绪,可以登陆到 AWS 的控制台看下 Terraform 是不是为我们创建好了应有的东西。一切正常的就可以发送 Kinesis 消息到我们新创建的 Kinesis Stream 了,看看在 Bucket 里是不是有了 Lambda 生成的文件。
上面创建的东西不想要了,想统统干掉,那就更简单了 terraform destroy
就行了,简值是键删除。