Outsider's Dev Story

Stay Hungry. Stay Foolish. Don't Be Satisfied.
RetroTech 팟캐스트 44BITS 팟캐스트

Apex - AWS Lambda 관리도구 #2

이 글은 Apex - AWS Lambda 관리도구 #1에서 이어진 글이다.


Lambda 함수의 배포와 실행

기능은 없지만, 설정이 완료되었다. 사용하려면 먼저 Lambda에 배포해야 한다.

$ apex deploy
  • creating function         env= function=hello
  • created alias current     env= function=hello version=1
  • function created          env= function=hello name=apex-example_hello version=1

apex deploy를 실행하면 프로젝트에 설정된 함수가 모두 배포한다. 특정 함수만 배포하고 싶다면 apex deploy hello처럼 이름을 지정하거나 apex deploy he*처럼 와일드카드를 쓸 수도 있다. 위 로그를 보면 apex-example_hello라는 이름으로 함수가 배포되었고 첫 배포이므로 버전이 1인 것을 볼 수 있다.

AWS의 Lambda에서 함수가 생성된 화면

AWS Lambda에 접속하면 함수가 만들어진 것을 볼 수 있다. AWS 웹 콘솔에서도 테스트해볼 수 있지만 apex를 이용해 보자.

$ apex invoke hello
{"hello":"world"}

apex invoke 함수명을 실행하면 바로 Lambda 함수를 테스트해 볼 수 있다. 이는 apex가 실제로 Lambda에서 함수를 실행하고 그 결과를 받아서 출력해 준 것이다. 당연히 인터넷이 연결되어 있어야 하고 속도에 따라서 호출 결과가 늦게 올 수도 있다. 처음 Lambda를 사용해 볼 때 개발이 어려워서 로컬에서 Lambda 환경과 유사하게 실행해 볼 방법을 많이 찾아봤었는데 Apex는 Lambda 환경을 에뮬레이팅하는 대신 Lambda 환경을 직접 이용한다. 그래서 인터넷이 필요한 단점은 있지만, 실제 Lambda 환경에서 직접 해볼 수 있다는 장점이 있고 명령어로 간단히 해볼 수 있으므로 별로 불편하지도 않다.

hello함수는 안 그렇지만 Lambda 함수에 입력을 전달해야 하는 때도 있다. 이런 경우 테스트를 하려면 터미널 기능을 그대로 이용하면 된다.

$ echo -n '{ "value": "Tobi the ferret" }' | apex invoke hello

$ apex invoke hello < event.json

위와 같이 하면 파이프로 전달한 JSON이나 파일의 내용이 함수의 입력으로 전달된다.

이제 index.js를 약간 수정해 보자.

// functions/hello/index.js
console.log('starting function')
exports.handle = function(e, ctx, cb) {
  console.log('processing event: %j', e)
  cb(null, e); // 수정된 부분
}

Lambda 함수에 전달된 입력은 첫 번째 인자인 e로 전달되는데 이 값을 그대로 반환하도록 수정했다. 함수를 수정했으니 다시 배포를 해야 한다.

$ apex deploy hello
  • config unchanged          env= function=hello
  • updating function         env= function=hello
  • updated alias current     env= function=hello version=2
  • function updated          env= function=hello name=apex-example_hello version=2

새로 배포가 되고 버전이 2로 올라갔다. 이제 입력값을 주어 다시 실행해 보면 변경된 것을 확인할 수 있다.

$ echo -n '{ "value": "Tobi the ferret" }' | apex invoke hello
{"value":"Tobi the ferret"}


Lamda 함수의 로그와 매트릭

index.js에서 console.log로 로그를 출력했는데 Lambda에서 이 로그 결과는 Cloudwatch에 남게 된다. 실제 Lambda 서비스에서 로그를 확인하는 건 좀 귀찮은 일인데 apex가 이 부분까지 지원하고 있다.

$ apex logs hello
/aws/lambda/apex-example_hello 2016-09-20T17:53:21.287Z undefined starting function
/aws/lambda/apex-example_hello START RequestId: 1e82d1fb-7f5b-11e6-9c79-5592aa65509c Version: 2
/aws/lambda/apex-example_hello 2016-09-20T17:53:21.299Z 1e82d1fb-7f5b-11e6-9c79-5592aa65509c  processing event: {"value":"Tobi the ferret"}
/aws/lambda/apex-example_hello END RequestId: 1e82d1fb-7f5b-11e6-9c79-5592aa65509c
/aws/lambda/apex-example_hello REPORT RequestId: 1e82d1fb-7f5b-11e6-9c79-5592aa65509c Duration: 10.93 ms  Billed Duration: 100 ms Memory Size: 128 MB Max Memory Used: 14 MB

앞에 시간과 함수명이 나와서 보기 어렵지만 끝부분을 보면 console.log로 출력된 결과를 볼 수 있다. 이 로그를 통해서 메모리 사용량과 실행시간도 알 수 있다.

$ apex logs hello -s 1h
/aws/lambda/apex-example_hello 2016-09-20T17:45:15.424Z undefined starting function
/aws/lambda/apex-example_hello START RequestId: fce399dd-7f59-11e6-af77-8300015b5dd0 Version: 1
/aws/lambda/apex-example_hello 2016-09-20T17:45:15.439Z fce399dd-7f59-11e6-af77-8300015b5dd0  processing event: {}
/aws/lambda/apex-example_hello END RequestId: fce399dd-7f59-11e6-af77-8300015b5dd0
/aws/lambda/apex-example_hello REPORT RequestId: fce399dd-7f59-11e6-af77-8300015b5dd0 Duration: 14.89 ms  Billed Duration: 100 ms Memory Size: 128 MB Max Memory Used: 14 MB
/aws/lambda/apex-example_hello 2016-09-20T17:53:21.287Z undefined starting function
/aws/lambda/apex-example_hello START RequestId: 1e82d1fb-7f5b-11e6-9c79-5592aa65509c Version: 2
/aws/lambda/apex-example_hello 2016-09-20T17:53:21.299Z 1e82d1fb-7f5b-11e6-9c79-5592aa65509c  processing event: {"value":"Tobi the ferret"}
/aws/lambda/apex-example_hello END RequestId: 1e82d1fb-7f5b-11e6-9c79-5592aa65509c
/aws/lambda/apex-example_hello REPORT RequestId: 1e82d1fb-7f5b-11e6-9c79-5592aa65509c Duration: 10.93 ms  Billed Duration: 100 ms Memory Size: 128 MB Max Memory Used: 14 MB

-s 1h와 같이 시간을 지정하면 지정된 시간 동안의 로그를 모두 볼 수 있고 -f옵션으로 로그를 추적해서 볼 수도 있다.

$ apex metrics hello

  hello
    total cost: $0.00
    invocations: 2 ($0.00)
    duration: 25ms ($0.00)
    throttles: 0
    errors: 0
    memory: 128

함수에 대한 매트릭도 바로 확인할 수 있다. 예제로 앞에서 2번 실행했으므로 2번 실행되었다고 나오는 걸 볼 수 있다.

Lambda 함수의 롤백과 제거

Lambda에는 버전 관리 기능이 없지만, apex가 배포되는 함수의 버전을 관리해 주므로 잘못되면 롤백을 할 수 있다.

$ apex rollback hello
  • rolling back              env= function=hello
  • rollback to version: 1    env= function=hello
  • function rolled back      current version=1 env= function=hello

$ apex invoke hello
{"hello":"world"}

apex rollback 함수명으로 버전이 다시 1로 돌아간 것을 볼 수 있고 실행결과도 예전으로 돌아왔다. 특정 버전으로 롤백하고 싶다면 apex rollback hello 1처럼 버전을 지정하면 된다.

$ apex delete hello
Are you sure? (yes/no) yes
  • deleting                  env= function=hello
  • function deleted          env= function=hello

함수가 필요 없어지면 apex delete 함수명으로 함수를 제거할 수 있다.

$ apex list

  hello (not deployed)
    runtime: nodejs4.3
    memory: 128mb
    timeout: 5s
    role: arn:aws:iam::410655858509:role/apex-example_lambda_function
    handler: index.handle

apex list로 프로젝트에서 관리하는 함수의 목록을 확인할 수 있다.


funcion.json

앞에서 project.json 파일로 프로젝트의 전역설정에 대해 설명을 했는데 함수별로 추가설정을 할 수 있다.

├── functions
│   └── hello
│       ├── funcion.json
│       └── index.js
└── project.json

위처럼 함수의 폴더 안에 funcion.json을 만들면 이 파일의 설정을 함수에 적용하고 설정 안 된 부분은 project.json의 설정을 사용한다. 이 파일에서 사용할 수 있는 설정은 다음과 같다.

  • description: 프로젝트에 대한 설명이다.(문자열)
  • runtime: Lambda의 런타임으로 다음 값을 사용할 수 있다.(문자열)

    • java: Java 8
    • python: Python 2.7
    • nodejs: Node.js 0.10
    • nodejs4.3: Node.js 4.3
    • golang: any version, Lambda에서는 원래 지원하지 않지만, Apex에서 지원한다.
  • handler: 이벤트 핸들러의 이름으로 다음이 기본값이다.

    • nodejs: index.handle (index.js파일에서 export로 내보낸 함수)
    • python: handle
    • java: lambda.Main::handler
  • memory: Lambda의 할당 메모리(정수, 메가바이트 단위)
  • timeout: Lambda의 함수 실행 만료시간(정수, 초 단위)
  • environment: Lambda 함수에 적용할 환경 변수이다.(객체)
  • retainedVersions: 롤백 등에 사용하기 위해 Lambda에서 유지할 함수의 버전 개수.
  • vpc: AWS의 VPC 설정(객체)
  • vpc.securityGroups: 시큐리티 그룹의 ID 목록(배열)
  • vpc.subnets: 서브넷 ID 목록(배열)

각 기능을 설명하느라 길어졌지만 실제로 약간 사용해보면 금세 익숙해질 정도로 간단하다. 써먹을 만한 함수를 작성한다면 고민할 요소가 좀 더 있는데 이 부분은 조만간 별도의 글로 올릴 예정이다.

2016/09/21 03:34 2016/09/21 03:34