Lambda Layers를 Golang에서 구현해보기

10748 단어 5람다TerraformAWS

소개



Lambda의 공통 처리라고 하면 Lambda Layers이다.

Golang에는 공통 모듈을 다루는 몇 가지 방법이 있습니다 (Git Submodules를 사용하거나 로컬 Git 저장소를 사용합니다 (과거 기사 참조)). 를 확인하고 고찰해 보자.

Go Plugin 패키지 사용



Lambda Layers를 Golang에서 사용하는 경우 Plugin 패키지를 사용하십시오.
우선은, 이 모듈에 대해서 제대로 알아 두자.

패키지 설명은 공식을 확인하십시오.

로그 출력을 하는 mylogger인 플러그인을 만들어 보기로 하자.

mylogger.go
package main

import (
    "log"
)

func OutputLog(str string) {
    log.Printf(str)
}

이것을 .so 형식으로 출력하도록 빌드한다.
$ GOOS=linux go build -buildmode=plugin -o mylogger.so

모듈의 호출자를 구현해 보자.

main.go
package main

import (
    "log"
    "os"
    "plugin"
)

var (
    outputLog plugin.Symbol
)

func init() {
    var (
        pi  *plugin.Plugin
        err error
    )

    if pi, err = plugin.Open("mylogger.so"); err != nil {
        log.Printf("plugin Open() error: %s", err.Error())
        os.Exit(-1)
    }
    if outputLog, err = pi.Lookup("OutputLog"); err != nil {
        log.Printf("plugin Lookup() error: %s", err.Error())
        os.Exit(-1)
    }
}

func main() {
    outputLog.(func(string))("Hello Golang Plugin!!")
}

플러그인 패키지의 Open에서 공통 라이브러리를 열고 Lookup에서 공통 모듈에서 함수를로드합니다 (정확히 변수도로드 할 수 있습니다. 요컨대 변수 유형 (plugin.Symbol) 로드한다는 것이다).

그런 다음이 main을 빌드하고 mylogger.so의 디렉토리에서 실행하면,
2020/11/01 11:55:27 Hello Golang Plugin!!

로 출력된다.

Lambda Layers에서 사용하는 경우



Lambda Layers에서 사용하는 경우에도, 공통 모듈측은 특별히 무언가를 변경할 필요는 없다.

Lambda Layers는/opt에 배포 될 것 같으므로 Lambda 함수에서
    if pi, err = plugin.Open("/opt/mylogger.so"); err != nil {

라고 부르자.

또한 Lambda Layers를 Lambda 측으로 설정해야합니다.
이 예제에서는 Terraform을 사용하고,
################################################################################
# Lambda                                                                       #
################################################################################
resource "aws_lambda_function" "test" {
  depends_on = [
    aws_cloudwatch_log_group.lambda,
  ]

  function_name    = local.lambda_function_name
  filename         = data.archive_file.main.output_path
  role             = aws_iam_role.lambda.arn
  handler          = "lambda_function"
  source_code_hash = data.archive_file.main.output_base64sha256
  runtime          = "go1.x"

  memory_size = 128
  timeout     = 30

  layers = [
    aws_lambda_layer_version.test.arn,
  ]
}

################################################################################
# Lambda Layer                                                                 #
################################################################################
resource "aws_lambda_layer_version" "test" {
  layer_name       = local.lambda_layer_name
  filename         = data.archive_file.layer.output_path
  source_code_hash = data.archive_file.layer.output_base64sha256
}

느낌으로 설정한다.aws_lambda_layer_version에서 정의한 리소스를 aws_lambda_functionlayers 블록으로 설정합시다.

올바르게 설정되면 관리 콘솔의 Lambda 화면에서 ↓ 이런 식으로 표시됩니다.



관리 콘솔에서 설정하는 경우 위 화면의 "레이어 추가"에서 직접 설정합시다.

이 함수를 실행하면,



로그가 출력됩니다.
했어!

실제 사용법에 대한 고찰



글쎄, Lambda Layers를 Golang에서 구현할 수 있다는 것을 알았지 만 실제로 쓸모 없을까?
우선, 여기 으로 쓰여져 있듯이, 비정상적으로 제한 사항이 많다.
  • Layer 및 Function에서 Golang의 컴파일러 버전이 일치해야 함
  • Layer와 Function이 동일한 패키지를 사용하는 경우 버전이 일치해야 함

  • 음, 냄새와 Layer 함수를 배포 후에 적용하면 작동하지 않을 수 있습니다.

    그러한 것도 있어, Lambda Layer 는, 배치를 해도 호출원의 Lambda 함수측은 자동으로는 전환되지 않고, $LATEST 라든지 별명도 존재하지 않는 것처럼 보인다.
    그러나 공통 라이브러리는 그런 것일까? C언어의 공통 라이브러리는 심볼 정의만 맞으면 뭔가 있었을 때에는 라이브러리만 수정하여 흡수하는 것이 가능했을 것이다.

    뭐, AWS적인 사고방식으로도, Golang의 사상으로서도, 공통 처리를 고치면 확실히 호출원으로 CI/CD를 돌려 배치해라, 라고 하는 이야기일지도 모른다.
    그렇다면 역시 처음 쓴 것처럼 Git Submodules나 로컬 Git 리포지토리를 사용하는 것이 좋은 생각이 든다. 하지만 그렇다면 Golang에서 Lambda Layers의 역할이란 무엇입니까? 혹시 불필요한 것일까…

    좋은 웹페이지 즐겨찾기