AWS CLI가 포함된 Lambda layer 만들기
Python으로 작성된 Lambda function이 AWS CLI를 실행할 수 있도록 AWS CLI가 포함된 Lambda layer를 만드는 방법을 공유한다. AWS CLI는 다소 특이한 Python 모듈일 뿐이기 때문에 일반적인 Python 모듈의 경우에도 활용할 수 있다.
Lambda layer
Lambda layer는 AWS Lambda 서비스에서 Lambda function이 필요로 하는 라이브러리 코드를 재활용하기 위한 도구이다. 자세한 내용은 https://docs.aws.amazon.com/lambda/latest/dg/configuration-layers.html 에서 찾을 수 있다.
Python 모듈을 Lambda function의 deployment package 안에 직접 넣는 것보다 Lambda layer를 만드는 것이 편리하다. 해당 모듈을 사용하는 여러 Lambda function에서 layer를 가져다 쓰면서 재활용할 수 있기 때문이다.
Lambda function에서 AWS CLI를 써야 하는 경우
Python runtime을 사용하는 Lambda function에서 AWS API 호출을 하려면 AWS CLI를 실행하는 것보다 AWS의 Python SDK인 boto3 mo을 사용하는 것이 더 좋은 방법이다. 코딩하기도 편하고 boto3는 Python runtime에 포함되어 있기 때문에 바로 사용할 수 있다.
AWS CLI는 아래처럼 boto3에서 해당 기능을 지원하지 않는 명령에만 사용하는 것이 좋다.
- aws eks update-kubeconfig
- aws s3 sync
aws eks update-kubeconfig 명령은 Lambda function에서 EKS 클러스터에 접속할 때 kubeconfig 설정을 위해 필요하다.
Lambda layer 용 zip 파일 생성 방법
우선 pyenv와 virutalenv를 설치해야 한다.
pyenv로 Lambda runtime에 맞는 Python 버전을 설치한다. 예를 들어 python3.8 용 layer를 생성하기 위해 3.8.11 을 설치할 수 있다.
1pyenv install 3.8.11
zip-lambda-layer-awscli.sh 스크립트를 다운로드한 후 아래처럼 layer를 구성하는 zip 파일을 만든다.
1$ sh zip-lambda-layer-awscli.sh 3.8.11
2
3# 생성되는 파일은 아래와 같다.
4$ ls *.zip
5lambda-layer-awscli-python38.zip
Terraform으로 아래처럼 Lambda layer와 function을 만들 수 있다.
1
2# 실제로는 아래처럼 aws_lambda_layer_version을 직접 만들지 말고, 이것을 생성하는 테라폼 모듈을 만들어서 재사용해야 한다.
3resource "aws_lambda_layer_version" "awscli_python38" {
4 filename = "./lambda-layer-awscli-python38.zip"
5 compatible_runtimes = ["python3.8"]
6 ...
7 }
8
9resource "aws_lambda_function" "main" {
10
11 runtime = "python3.8"
12 layers = [aws_lambda_layer_version.awscli_python38.arn]
13 ...
14}
Lambda function을 구성하는 Python 스크립트에서 아래처럼 사용하면 된다.
1# PATH 환경 변수에 포함된 /opt/bin/ 아래에 aws가 있어서 경로 지정을 하지 않아도 된다.
2subprocess.run('aws --version',shell=True,check=True)
zip-lambda-layer-awscli.sh 스크립트
zip-lambda-layer-awscli.sh의 내용은 아래와 같다.
[참고] zip 파일 구성
bin/ 아래에 aws 명령과 그것이 의존하는 Python 모듈을 설치한다.
zip 파일 내의 bin/ 디렉토리는 Lambda 실행 환경에선 /opt/bin/ 디렉토리가 된다. /opt/bin/ 디렉토리는 Lambda function의 PATH 환경 변수에 포함되어 있기 때문에 Lambda function은 aws 명령을 경로 지정 없이 실행할 수 있다.
Python은 sys.path 변수에 포함된 디렉토리에서 import하는 module들을 찾는다. Lambda function의 sys.path 변수는 /opt/ 아래 다양한 디렉토리를 포함한다. 하지만 이 layer에 포함된 모듈들은 lambda function이 아니라 /opt/bin/aws 스크립트에서 import 하기 위한 것이다. 그런데 aws 명령의 sys.path 변수에는 /opt/ 아래 디렉토리들이 포함되지 않는다. aws 명령이 awscli 모듈을 찾을 수 있게 하려면 명령과 동일한 디렉토리인 /opt/bin/ 아래에 모듈을 넣어야 한다.
Lambda는 layer를 포함한 deployment package의 크기를 제한한다. 따라서 zip 파일과 deployment package의 크기를 줄이기 위해 Python 버전별로 layer를 따로 만든다.
참고한 문서
- https://docs.aws.amazon.com/lambda/latest/dg/invocation-layers.html
- https://docs.aws.amazon.com/lambda/latest/dg/configuration-layers.html
- https://docs.aws.amazon.com/lambda/latest/dg/python-package.html
- https://bezdelev.com/hacking/aws-cli-inside-lambda-layer-aws-s3-sync/