Pythonで書いたシンプルなスクリプトをTerraformを用いてAWS Lambdaにデプ ロイする方法を示す。
Terraformの設定
AWS Lambdaで用いるPythonスクリプトのアーカイブ
ここが一番気になるところだろう。シンプルなPythonスクリプトの場合、わざ
わざリポジトリを分割したくないしパッケージングもしたくない。できれば
Terraformの構成と同様にPythonスクリプトも管理したい。Terraformはこの要
求にももちろん答えることができる。Terraformの archive_file
pluginを
用いてTerraformの適応と同時にZIPファイルとしてアーカイブを作成し、それ
を用いてAWS Lambdaへの展開を行う。
以下では example_lambda_functions
配下に "example.py" というファイル
を予め配置している。このファイルがAWS Lambdaに展開するPythonスクリプト
になる。 source_file
でアーカイブに含めるファイルを指定している。
output_path
で出力するアーカイブのパスを指定している。ここには
Terraformの適応毎にアーカイブが出力されるため、Gitに登録しないように
.gitignore
に指定する。
data "archive_file" "example_lambda_functions_zip" { type = "zip" source_file = "${path.module}/example_lambda_functions/example.py" output_path = "${path.module}/files/example_lambda_functions.zip" }
AWS Lambdaで用いるIAM Roleの定義
AWS Lambdaを定義する際にIAM Roleが必要になるので作成しておく。
resource "aws_iam_role" "iam_for_example_function" { name = "iam_for_example_function" assume_role_policy = <<EOF { "Version": "2012-10-17", "Statement": [ { "Action": "sts:AssumeRole", "Principal": { "Service": "lambda.amazonaws.com" }, "Effect": "Allow", "Sid": "" } ] } EOF }
AWS Lambdaの定義
上記のリソースを用いてAWS Lambdaを定義する。
resource "aws_lambda_function" "example_function" { filename = data.archive_file.example_lambda_functions_zip.output_path function_name = "example" role = aws_iam_role.iam_for_example_function.arn handler = "example.lambda_handler" source_code_hash = data.archive_file.example_lambda_functions_zip.output_base64sha256 runtime = "python3.8" memory_size = 128 timeout = 30 }
ローカルでのデプロイ
Terraformが呼び出すAWSのAPIは設定により変更できるため、AWSのAPIをエミュ レートするダミーサーバーに対して動作確認を行える。以下ではDockerを用い てlocalstackを起動し、それをダミーサーバーとして動作を確認する方法を示 す。
localstackを起動する
localstackとはAWSのAPIをエミュレートするAPIサーバーである。ローカル環 境での検証のために用いる。localstackの起動のためにDockerや docker-composeを用いることが必須というわけではないが、ここではそれを採 用する。
docker-compose.ymlを作成し、以下を記述する。
ファイルを保存したらコンテナを起動する。
$ docker-compose up
ローカルで起動しているlocalstackに対してTerraformを行う際にはこのコン
テナが起動していることが必要となる。起動したままの状態でコマンドを復帰
させたければ docker-compose up -d
とするのが良いだろう。このコンテナ
は4566番のTCPポートでリクエストを待ち受けているため、通常
http://localhost:4566
に対してリクエストを送信できる。
Terraformが呼び出すAWSのAPIエンドポイントをローカルに変更する
Terraformが呼び出したAWSのAPIがローカルに起動したlocalstackに送信されるように設定を変更する。
provider "aws" { region = "ap-northeast-1" access_key = "mock_access_key" secret_key = "mock_secret_key" s3_force_path_style = true skip_credentials_validation = true skip_metadata_api_check = true skip_requesting_account_id = true endpoints { accessanalyzer = "http://localhost:4566" acm = "http://localhost:4566" acmpca = "http://localhost:4566" amplify = "http://localhost:4566" apigateway = "http://localhost:4566" applicationautoscaling = "http://localhost:4566" applicationinsights = "http://localhost:4566" appmesh = "http://localhost:4566" appstream = "http://localhost:4566" appsync = "http://localhost:4566" athena = "http://localhost:4566" autoscaling = "http://localhost:4566" autoscalingplans = "http://localhost:4566" backup = "http://localhost:4566" batch = "http://localhost:4566" budgets = "http://localhost:4566" cloud9 = "http://localhost:4566" cloudformation = "http://localhost:4566" cloudfront = "http://localhost:4566" cloudhsm = "http://localhost:4566" cloudsearch = "http://localhost:4566" cloudtrail = "http://localhost:4566" cloudwatch = "http://localhost:4566" cloudwatchevents = "http://localhost:4566" cloudwatchlogs = "http://localhost:4566" codeartifact = "http://localhost:4566" codebuild = "http://localhost:4566" codecommit = "http://localhost:4566" codedeploy = "http://localhost:4566" codepipeline = "http://localhost:4566" codestarconnections = "http://localhost:4566" # codestarnotifications = "http://localhost:4566" cognitoidentity = "http://localhost:4566" cognitoidp = "http://localhost:4566" configservice = "http://localhost:4566" connect = "http://localhost:4566" cur = "http://localhost:4566" dataexchange = "http://localhost:4566" datapipeline = "http://localhost:4566" datasync = "http://localhost:4566" dax = "http://localhost:4566" devicefarm = "http://localhost:4566" directconnect = "http://localhost:4566" dlm = "http://localhost:4566" dms = "http://localhost:4566" docdb = "http://localhost:4566" ds = "http://localhost:4566" dynamodb = "http://localhost:4566" ec2 = "http://localhost:4566" ecr = "http://localhost:4566" ecrpublic = "http://localhost:4566" ecs = "http://localhost:4566" efs = "http://localhost:4566" eks = "http://localhost:4566" elasticache = "http://localhost:4566" elasticbeanstalk = "http://localhost:4566" elastictranscoder = "http://localhost:4566" elb = "http://localhost:4566" emr = "http://localhost:4566" emrcontainers = "http://localhost:4566" es = "http://localhost:4566" firehose = "http://localhost:4566" fms = "http://localhost:4566" forecast = "http://localhost:4566" fsx = "http://localhost:4566" gamelift = "http://localhost:4566" glacier = "http://localhost:4566" globalaccelerator = "http://localhost:4566" glue = "http://localhost:4566" guardduty = "http://localhost:4566" greengrass = "http://localhost:4566" iam = "http://localhost:4566" identitystore = "http://localhost:4566" imagebuilder = "http://localhost:4566" inspector = "http://localhost:4566" iot = "http://localhost:4566" iotanalytics = "http://localhost:4566" iotevents = "http://localhost:4566" kafka = "http://localhost:4566" kinesis = "http://localhost:4566" kinesisanalytics = "http://localhost:4566" kinesisanalyticsv2 = "http://localhost:4566" kinesisvideo = "http://localhost:4566" kms = "http://localhost:4566" lakeformation = "http://localhost:4566" lambda = "http://localhost:4566" lexmodels = "http://localhost:4566" licensemanager = "http://localhost:4566" lightsail = "http://localhost:4566" macie = "http://localhost:4566" macie2 = "http://localhost:4566" managedblockchain = "http://localhost:4566" marketplacecatalog = "http://localhost:4566" mediaconnect = "http://localhost:4566" mediaconvert = "http://localhost:4566" medialive = "http://localhost:4566" mediapackage = "http://localhost:4566" mediastore = "http://localhost:4566" mediastoredata = "http://localhost:4566" mq = "http://localhost:4566" mwaa = "http://localhost:4566" neptune = "http://localhost:4566" networkfirewall = "http://localhost:4566" networkmanager = "http://localhost:4566" opsworks = "http://localhost:4566" organizations = "http://localhost:4566" outposts = "http://localhost:4566" personalize = "http://localhost:4566" pinpoint = "http://localhost:4566" pricing = "http://localhost:4566" # prometheusservice = "http://localhost:4566" qldb = "http://localhost:4566" quicksight = "http://localhost:4566" ram = "http://localhost:4566" rds = "http://localhost:4566" redshift = "http://localhost:4566" resourcegroups = "http://localhost:4566" resourcegroupstaggingapi = "http://localhost:4566" route53 = "http://localhost:4566" route53domains = "http://localhost:4566" route53resolver = "http://localhost:4566" s3 = "http://localhost:4566" s3control = "http://localhost:4566" s3outposts = "http://localhost:4566" sagemaker = "http://localhost:4566" sdb = "http://localhost:4566" secretsmanager = "http://localhost:4566" securityhub = "http://localhost:4566" serverlessrepo = "http://localhost:4566" servicecatalog = "http://localhost:4566" servicediscovery = "http://localhost:4566" servicequotas = "http://localhost:4566" ses = "http://localhost:4566" shield = "http://localhost:4566" signer = "http://localhost:4566" sns = "http://localhost:4566" sqs = "http://localhost:4566" ssm = "http://localhost:4566" ssoadmin = "http://localhost:4566" stepfunctions = "http://localhost:4566" storagegateway = "http://localhost:4566" sts = "http://localhost:4566" swf = "http://localhost:4566" synthetics = "http://localhost:4566" timestreamwrite = "http://localhost:4566" transfer = "http://localhost:4566" waf = "http://localhost:4566" wafregional = "http://localhost:4566" wafv2 = "http://localhost:4566" worklink = "http://localhost:4566" workmail = "http://localhost:4566" workspaces = "http://localhost:4566" xray = "http://localhost:4566" } }
長くなったが必要な部分だけを設定すればよい。
Terraformの実行
実行方法は通常の方法と変わらない。
適応した際の変更内容を確認する場合には terraform plan
を実行する。
$ terraform plan
実際に適応する場合には terraform apply
を実行する。
$ terraform apply
AWS Lambdaのコンテナサポートを使う
AWS LambdaはDockerコンテナをサポートしている。AWS Lambdaのコンテナサポー トを使う ではAWS LambdaはDockerコンテナをサポートをどのように実装する かについて記述した。