4
1

More than 1 year has passed since last update.

[go] [terraform] lambdaのsource_code_hashが毎回更新される

Posted at

前提

goのバージョンとterraformのバージョンは以下
今回の記事の対象は恐らくgo 1.18以降を使っている人

go version
go version go1.19.2 darwin/arm64
terraform -v
Terraform v1.3.6

今回の問題

terraformで以下のようなコードでlambdaのリソース管理をしていた

resource "aws_lambda_function" "go_function" {
  filename         = "go_function.zip"
  function_name    = "go_function"
  handler          = "main"
  source_code_hash = filebase64sha256("go_function.zip")
  runtime          = "go1.x"
}

go_function.zip はgithub actionsのworkflow内でbuildしたbinaryをzip化していた。
その際のコマンドは以下

GOOS=linux GOARCH=amd64 go build -o dist/go-function go-function
zip -j go_function.zip dist/go-function

なおbinaryファイルとzipファイルはgitignoreしている。

lambda以外にもAWSのリソース管理を同じリポジトリでおこなっており、他のリソースをコード化しcommit後planを確認した。
goのソースコードに変更はないのだが、planでlambdaのsource_code_hashの差分が出る

 # aws_lambda_function.go_function will be updated in-place
  ~ resource "aws_lambda_function" "go_function" {
        id                             = "go_function"
      ~ last_modified                  = "2022-01-01T00:00:00.000+0000" -> (known after apply)
      ~ source_code_hash               = "old hash" -> "new hash"
        # (3 unchanged attributes hidden)

        # (3 unchanged blocks hidden)
    }

試した事

zip化する際に日付とかの余計な情報を持ってしまっているのでは?
と思い調べたが、よく分からず...
たどり着いたのがterraformの archive_fileを使えばzip化を行うことができ、output_base64sha256source_code_hashに使えば良いという記事
早速以下に変更し試してみる

data "archive_file" "go_function_zip" {
  type        = "zip"
  source_file = "../dist/go-function"
  output_path = "../dist/go_function.zip"
}

resource "aws_lambda_function" "go_function" {
  filename         = data.archive_file.go_function_zip.output_path
  function_name    = "go_function"
  handler          = "main"
  source_code_hash = data.archive_file.go_function_zip.output_base64sha256
  runtime          = "go1.x"
}

一度applyし、その後READMEだけを更新したコミットで差分を見てみる

 # aws_lambda_function.go_function will be updated in-place
  ~ resource "aws_lambda_function" "go_function" {
        id                             = "go_function"
      ~ last_modified                  = "2022-01-01T00:00:00.000+0000" -> (known after apply)
      ~ source_code_hash               = "old hash" -> "new hash"
        # (3 unchanged attributes hidden)

        # (3 unchanged blocks hidden)
    }

上手くいかず。
色々試行錯誤していくうちに気付く。あれ?build後のbinaryファイルのhashが違う
READMEのみ更新したコミットでbuildしたbinaryファイルのhashと、一つ前のコミットでbuildしたbinaryファイルのhashが違った

結論

どうやらgo1.18以降ではbinaryファイルにコミットハッシュなどのmeta情報を持っているらしい

go version -m dist/go-function
dist/go-function: go1.19.2
	...省略
	build	-compiler=gc
	build	CGO_ENABLED=0
	build	GOARCH=amd64
	build	GOOS=linux
	build	GOAMD64=v1
	build	vcs=git
	build	vcs.revision=commit hash
	build	vcs.time=2022-01-01T00:00:00Z
	build	vcs.modified=false

このvpc.revisionにcommit hashを持っていたため、goのリソースに何も変更がなくてもコミットする度に差分が出ていた模様
これはbuildする際に-buildvcs=falseをつければbinaryファイルにこの情報を含めないよう出来るとのこと
って事でbuildする際のコマンドを以下に変更

GOOS=linux GOARCH=amd64 go build -buildvcs=false -o dist/go-function go-function

無事毎回差分が出なくなりました

4
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
1