Skip to content

AWS Lambda power tuning으로 비용 효율성 개선하기

aws의 lambda function에 리소스를 할당할때 어떻게 할당해야 비용대비 성능을 최대로 뽑아낼 수 있을지 고민을 하다 이 프로젝트를 발견했다.

https://github.com/alexcasalboni/aws-lambda-power-tuning?tab=readme-ov-file

출처 – https://github.com/alexcasalboni/aws-lambda-power-tuning

해당 프로젝트를 배포해서 사용하는 방법은 여러가지가 있는데 가장 간편하고 해당 docs에서 추천하는 방식인 SAR을 이용해서 배포했다. 그냥 해당 링크로 들어가서 aws console에 로그인하고 클릭 몇번하면 배포가 끝난다.

aws application 링크

Screenshot 2024-03-16 at 11.59.05 PM.jpg
출처 – https://github.com/alexcasalboni/aws-lambda-power-tuning

실행하는 방법도 여러가지가 있는데 local에 해당 저장소를 다운로드 받은 것도 아니고 그냥 바로 console에서 배포했기 때문에 console에서 실행시키는 방법을 사용했다.
docs에 잘 설명되어있는데 aws의 step functions > state machines에 들어가면 해당 어플리케이션을 찾을 수 있다.

그리고 아래 화면에서 실행시킬 수 있다.
Screenshot 2024-03-17 at 12.16.44 AM.jpg

start excution을 클릭하면 아래 이미지처럼 옵션을 넣을 수 있는 input창이 나온다.
Screenshot 2024-03-17 at 12.18.16 AM.jpg

마찬가지로 docs를 보면서 테스트하고 싶은 함수와 옵션을 지정해준다.
https://github.com/alexcasalboni/aws-lambda-power-tuning/blob/master/README-INPUT-OUTPUT.md

event에 필요한 파라미터는 payload에 담아서 보내면 된다.
나는 대부분의 lambda function을 lambda function url로 http 요청을 통해서 사용한다. 그래서 payload에 해당 url로 http 요청을 보내는 json을 event로 담아 보내야했다.

인터넷에 찾아보니 정확하지 않은 정보들인 것 같아 그냥 직접 lambda_handler안에 받은 event정보를 출력하도록 해두고 function url로 get요청을 날렸다.

import json
def lambda_handler(event, context):

    print("event: " + json.dumps(event))
    
    print("Hello, World!")
    return {
        'statusCode': 200,
        'body': json.dumps('Hello from Lambda!')
    }

그리고 cloudwatch에서 해당 log를 확인해 보니 아래와 같이 출력되는 것을 확인할 수 있었다.

event: {
	"version": "2.0",
	"routeKey": "$default",
	"rawPath": "/",
	"rawQueryString": "",
	"headers": {
		"sec-fetch-mode": "navigate",
		"x-amzn-tls-version": "TLSv1.3",
		"sec-fetch-site": "cross-site",
		"x-forwarded-proto": "https",
		"accept-language": "en,ko;q=0.9,ko-KR;q=0.8,en-US;q=0.7",
		"x-forwarded-port": "443",
		"dnt": "1",
		"x-forwarded-for": "111.11.111.11",
		"sec-fetch-user": "?1",
		"accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7",
		"x-amzn-tls-cipher-suite": "TLS_AES_128_GCM_SHA256",
		"sec-ch-ua": "\"Chromium\";v=\"122\", \"Not(A:Brand\";v=\"24\", \"Google Chrome\";v=\"122\"",
		"x-amzn-trace-id": "Root=1-65f66188-qwerasdfewqarfd",
		"sec-ch-ua-mobile": "?0",
		"sec-ch-ua-platform": "\"macOS\"",
		"host": "eqawgasf3e31235bw.lambda-url.ap-northeast-2.on.aws",
		"upgrade-insecure-requests": "1",
		"accept-encoding": "gzip, deflate, br, zstd",
		"user-agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36",
		"sec-fetch-dest": "document"
	},
	"requestContext": {
		"accountId": "anonymous",
		"apiId": "ta34eas2w3erfs235sw34vg5sw345cfswa35",
		"domainName": "ta34eas2w3erfs235sw34vg5sw345cfswa35.lambda-url.ap-northeast-2.on.aws",
		"domainPrefix": "ta34eas2w3erfs235sw34vg5sw345cfswa35",
		"http": {
			"method": "GET",
			"path": "/",
			"protocol": "HTTP/1.1",
			"sourceIp": "111.91.175.66",
			"userAgent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36"
		},
		"requestId": "53287204-7e8d-42e2-8a50-ce8ec5ae4753",
		"routeKey": "$default",
		"stage": "$default",
		"time": "17/Mar/2024:03:20:40 +0000",
		"timeEpoch": 1710645640937
	},
	"isBase64Encoded": false
}

대강 구조를 알았으니 필요없어보이는 파라미터는 날리고 lambda function의 test탭에서 아래와 같이 Eevent JSON을 만들어서 test를 해보았다.

{
    "version": "2.0",
    "routeKey": "$default",
    "rawPath": "/health",
    "requestContext": {
        "http": {
            "method": "GET",
            "path": "/health",
            "protocol": "HTTP/1.1",
            "sourceIp": "111.11.111.11",
            "userAgent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36"
        }
    },
    "isBase64Encoded": false
}

실제로 path에 설정한 경로로 get요청이 정상적으로 가고 있었다. 이제 step functions의 state machines에 돌아가서 이걸 그대로 payload에 담아 테스트를 하면 된다.

{
  "lambdaARN": "arn:aws:lambda:ap-northeast-2:123412341234:function:funtion-name",
  "powerValues": [
    128,
    256,
    512,
    1024,
    1536
  ],
  "num": 50,
  "payload": {
    "version": "2.0",
    "routeKey": "$default",
    "rawPath": "/health",
    "requestContext": {
      "http": {
        "method": "GET",
        "path": "/health",
        "protocol": "HTTP/1.1",
        "sourceIp": "111.91.175.66",
        "userAgent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36"
      }
    },
    "isBase64Encoded": false
  }
}

하고나서야 생각난건데 Lambda function Test 탭에서 http 요청 template이 있는데 해당 템플릿을 사용하면 쉽게 EventJSON을 작성할 수 있다..

어쨌든 그렇게 실행시키고 output을 확인하면

{
  "power": 128,
  "cost": 4.2e-9,
  "duration": 2,
  "stateMachine": {
    "executionCost": 0.0003,
    "lambdaCost": 0.0000013209,
    "visualization": "https://lambda-power-tuning.show/#gAAAAQACAAQABg==;AAAAQFVVFUCrqgpAAAAAQAAAAEA=;l0+QMWN3WDJjd9gyl08QM2N3WDM="
  }
}

이렇게 결과를 볼 수 있고 visualization에서 시각화된 표를 통해 결과를 보다 직관적으로 확인할 수 있다.

출처 – https://github.com/alexcasalboni/aws-lambda-power-tuning

lambda function은 free tier가 넉넉한 편이라 사실 개인개발자들에게는 이렇게까지 테스트해가면서 체크할 것 같지는 않지만 자원을 많이 사용하게 되는 경우에는 정말 유용한 툴인듯 하다.

Leave a Reply

Your email address will not be published. Required fields are marked *