AWS 람다 함수 관리 툴 – APEX (6)

dry-run으로 미리보기

Apex는 어떤 오퍼레이션에서도 --dry-run 플래그를 통해 AWS 반영없이 미리 결과를 확인해 볼 수 있습니다.

Notation

Dry run은 아래 심볼을 사용하여 리소스의 미래 상태를 표현합니다.

  • + 리소스는 생성될 것입니다.
  • - 리소스는 삭제될 것입니다.
  • ~ 리소스는 업데이트 될 것입니다.

예제

예를 들어 여러분이 foo, bar 함수를 작성했고, 아직 한 번도 배포한 적이 없다면 아래와 같은 응답을 보게 될 것입니다. 아래 아웃풋은 AWS에 전송되는 최종 요청을 나타냅니다. 충돌을 방지하기 위해 함수의 이름에 prefix를 붙이고 current 릴리즈 앨리어스를 유지하기 위해 추가 앨리어스를 붙이는 내용을 볼 수 있습니다.

$ apex deploy --dry-run

  + function testing_bar
    handler: _apex_index.handle
    runtime: nodejs
    memory: 128
    timeout: 5

  + alias testing_bar
    alias: current
    version: 1

  + function testing_foo
    memory: 128
    timeout: 5
    handler: _apex_index.handle
    runtime: nodejs

  + alias testing_foo
    alias: current
    version: 1

apex deploy foo 명령어를 실행한 후 apex deploy --dry-run 명령어를 실행했다면 아래와 같이 bar 함수만 디플로이된다는 내용을 확인할 수 있습니다.

Apex는 함수의 hash 값이 배포된 함수와 동일하면 배포하지 않습니다.

$ apex deploy --dry-run

  + function testing_bar
    runtime: nodejs
    memory: 128
    timeout: 5
    handler: index.handle

  + alias testing_bar
    alias: current
    version: 1

유사한 방법으로 설정이 변경된 부분을 미리 확인하는데도 사용할 수 있습니다.

$ apex deploy --dry-run

  ~ alias testing_foo
    alias: current
    version: $LATEST

  ~ config testing_foo
    memory: 128 -> 512
    timeout: 5 -> 10

아래는 함수 delete에 대한 preview입니다.

$ apex delete --dry-run -f

  - function testing_bar

  - function testing_foo

환경 변수

Apex는 KMS를 통해 암호화된 새로운 네이티브 AWS Lambda 환경 변수를 지원합니다. 이러한 변수를 설정하는 방법은 여러가지가 있는데 살펴보도록 합시다

-set 플래그

-s, --set 플래그는 함수 런타임에 노출되는 환경 변수를 설정하는데 사용됩니다. 예를 들어 node.js 환경에서의 process.env.NAME이나 go 언어에서의 os.Getenv("NAME")같은 값들을 말합니다. 이 플래그는 여러 번 설정할 수 있습니다.

예를 들어 여러분이 Loggly 로그 수집기를 사용하고 수집기 사용을 위해 API 토큰을 설정해야 한다면 아래와 같이 설정할 수 있습니다.

$ apex deploy -s LOGGLY_TOKEN=token log-collector

-env-file 플래그

-E, --env-file 플래그를 사용하여 여러 환경 변수를 담고 있는 JSON 파일을 반영할 수 있습니다.

$ apex deploy --env-file /path/to/env.json
// Sample env.json
{
  "LOGGLY_TOKEN": "12314212213123"
}

설정 파일 (project.json 혹은 function.json)

project.json 혹은 function.json 파일에 환경 변수를 설정하는 것도 가능합니다.

하지만 설정값은 반드시 string 타입이어야 합니다.

{
  "environment": {
    "LOGGLY_TOKEN": "12314212213123"
  }
}

우선 순위

적용 우선 순위는 아래와 같습니다.

  1. -s, --set 플래그
  2. -E, --env-file 플래그
  3. project.json 혹은 function.json 파일에 설정된 환경 변수 값

파일 무시(omitting)하기

부가적으로 .apexignore 파일을 프로젝트 루트나 특정 함수 디렉토리에 배치할 수 있으며 gitignore 파일과 동일한 패턴을 사용하여 파일을 무시할 수 있습니다. 기본적으로 .apexignore, function.json 파일은 무시됩니다.

무시된다 == 람다 함수 패키징 과정에서 포함되지 않는다

( 나머지 내용은 딱히 중요하지 않아서 번역하진 않겠습니다 ^^)

AWS 람다 함수 관리 툴 – APEX (5)

부끄러운 번역이지만 AWS 주간 소식 모음에 APEX 글이 링크되었습니다 🙂

로그 확인

Apex는 함수의 출력 로그를 보기 위해 CloudWatch Logs와 연동됩니다. apex logs에 함수의 이름이 지정되지 않으면 기본적으로 모든 함수의 로그가 표시됩니다. 로그 히스토리의 시간 범위를 지정할 수도 있고 (기본값: 5분) 아래와 같이 결과를 필터링할 수도 있습니다.

예제

최근 5분간 모든 함수의 로그 확인하기

$ apex logs

uppercase, lowercase 함수의 로그 확인하기

$ apex logs uppsercase lowercase

모든 함수의 로그를 추적(follow)하기 (tail처럼 보기)

$ apex logs -f

특정 함수의 로그 추적하기

$ apex logs -f foo

최근 1시간의 로그 보기

$ apex logs --since 1h
$ apex logs -s 1h

auth로 시작하는 모든 함수의 로그 보기

$ apex logs auth*

성능 지표(Metrics) 보기

apex metrics 명령어는 주어진 시간 동안의 함수의 실행 횟수, 총 실행 시간, 스로틀링, 에러에 대한 지표를 표시합니다.

예제

최근 24시간 동안의 모든 함수에 대한 성능 지표 보기

$ apex metrics

uppercase
  invocations: 1242
  duration: 65234ms
  throttles: 0
  error: 0

lowercase
  invocations: 1420
  duration: 65234ms
  throttles: 0
  error: 5

최근 15분동안의 지표보기

$ apex metrics --since 15m

uppercase
  invocations: 16
  duration: 4212ms
  throttles: 0
  error: 0

lowercase
  invocations: 23
  duration: 5200ms
  throttles: 0
  error: 5

인프라스트럭처 관리하기

Apex는 인프라스트럭쳐 관리를 위해 Terraform과 연동합니다. Apex는 현재 람다 함수에 대한 관리 기능만을 제공하고 있기 때문에 Lambda resource 같은 추가적인 자원을 Terraform이나 Cloudformation을 이용하여 관리하고 싶을 수 있습니다.

인프라스트럭쳐 관리

apex infra 명령어는 terraform 명령어에 대한 wrapper 입니다. Apex는 다수의 변수를 제공하고 복수의 Terraform 환경을 구성하는데 도움을 줍니다.

./infrastructure 디렉토리에 prodstage같은 환경이 존재한다면 아래와 같을 것입니다.

infrastructure/
├── prod
│   └── main.tf
├── stage
│   └── main.tf

예를 들어 apex infra --env prod plan 명령어는 아래 명령어와 동일한 일을 수행하면서 Apex에 설정된 여러 정보들을 여러가지 -var 플래그를 통해 전달해줍니다.

$ cd infrastructure/prod && terraform plan

환경에 대한 이름은 --env 플래그에 설정하거나 설정하지 않는다면 project.json에 설정된 defaultEnvironment 값이 사용됩니다.

Terraform 변수

현재 Terraform에 공개된 변수는 다음과 같습니다.

  • aws_region : us-west-2와 같은 AWS의 리전 명
  • apex_environment : prodstage같은 환경 명
  • apex_function_role : 람다 롤의 ARN
  • apex_function_arns : 모든 람다 함수의 ARN 매핑 정보
  • apex_function_names : 모든 람다 함수의 이름 매핑 정보

참고 사항

  • current라는 앨리어스가 참조되었다는 것을 지정하기 위해서는 ${apex_function_myfunction}:current를 명시적으로 할당해야 합니다.
  • apex_function_name 변수는 apex deploy를 통해 최소 1번은 배포되어야 참조할 수 있습니다.

AWS 람다 함수 관리 툴 – APEX (4)

함수 빌드하기

Apex는 배포를 위해 Zip 파일을 생성합니다. 그러나 가끔은 디버그를 위해서 zip 파일 내부에 어떤 내용들이 포함되어 있는지 확인하는 것이 유용할 수 있습니다. apex build 명령은 zip 파일을 생성하고 그 과정을 표준 출력 (STDOUT)으로 보냅니다.

예제

함수를 빌드해서 out.zip로 만들기

$ apex build foo > out.zip

이전 버전으로 되돌리기

함수의 버전을 이전 버전 혹은 특정 버전으로 되돌릴 수 있습니다.

예제

바로 이전 버전으로 되돌리기

$ apex rollback foo

특정 버전으로 되돌리기

$ apex rollback foo 5

--dry-run 플래그로 롤백 미리 보기

$ apex rollback --dry-run lowercase

~ alias testing_lowercase
 alias: current
 version: 2

$ apex rollback --dry-run uppercase 1

~ alias testing_uppercase
 version: 1
 alias: current

버전에 앨리어스 지정하기

aliax 명령어로 하나 혹은 그 이상의 함수 버전에 앨리어스를 설정할 수 있습니다.

예제

모든 함수의 앨리어스를 prod로 설정

$ apex alias prod

api_로 시작하는 이름을 가진 모든 함수의 앨리어스를 prod로 설정

$ apex alias prod api_*

버전이 5인 모든 함수의 앨리어스를 prod로 설정

$ apex alias -v 5 prod

특정 함수의 앨리어스를 stage로 설정

$ apex alias stage myfunction

특정 함수의 버전 10의 앨리어스를 stage로 설정

$ apex alias -v 10 stage myfunction

앨리어스가 dev인 특정 함수의 앨리어스를 stage로 변경 (dev에서 stage로 승격)

$ apex alias stage dev myfunction

함수 훅 (Function hooks)

Apex는 함수의 생명 주기에 맞춰 shell command가 실행될 수 있게 hook 개념을 지원합니다. 예를 들어 이런 hook은 배포하기 전에 문법 체크 (lint)나 테스트를 실행하도록 할 수 있으며 Babel, CoffeeScript 등의 트랜스 파일에도 연결될 수 있습니다.

Hook은 project.json 파일에 설정하며 Hook은 함수 디렉토리에서 실행됩니다. 만약 hook의 실행 결과 응답 코드가 0보다 크면 Apex는 실행을 중단하고 에러를 표시할 것입니다.

Hook 지원

  • build -> zip 파일로 함수를 빌드하기 전에 실행 (바이너리로 컴파일하거나 소스 코드의 트랜스폼에 이용)
  • deploy -> 함수가 배포되기 전에 실행 (테스트, lint 등에 이용)
  • clean -> 함수가 배포되고 난 후에 실행된다 (빌드 결과물 정리 등에 이용)

예제

아래 예제는 Apex 내부적으로 Golang 지원을 위해 설정된 hook의 내용입니다.

{
    "hooks": {
        "build": "GOOS=linux GOARCH=amd64 go build -o main main.go",
        "clean": "rm -f main"
    }
}

AWS 람다 함수 관리 툴 – APEX (3)

함수 배포하기

하나 혹은 그 이상의 함수를 배포하기 위해서 필요한 것은 apex deploy 명령어가 전부입니다. Apex의

배포는 멱등성(idempotent)을 갖습니다. 각 함수에 대한 빌드 결과가 생성되면 Apex는 Checksum을 확인하고 이미 배포된 함수와 비교해서 동일하면 배포하지 않습니다.

배포가 끝난 후 Apex는 기존 함수의 오래된 버전을 체크해서 몇 개(retainedVersion에 설정된 수만큼)만 남기고 삭제합니다.

특정 함수만 배포하고 싶다면 apex deploy 뒤에 함수 이름을 지정하면 됩니다. 함수 이름 인자는 deploy, logs, rollback 명령어에서도 사용할 수 있습니다.

예제

현재 디렉토리의 모든 함수를 배포합니다

$ apex deploy

~/dev/myapp 디렉토리에 있는 모든 함수를 배포합니다.

$ apex deploy -C ~/dev/myapp

특정 함수만 배포합니다.

$ apex deploy auth api

auth로 시작하는 모든 함수를 배포합니다.

$ apex deploy auth*

_reporter로 끝나는 모든 함수를 배포합니다.

$ apex deploy *_reporter

함수 실행하기

Apex로 command line에서 함수를 실행할 수 있으며 JSON 이벤트나 혹은 표준 입력 (STDIN) 스트림을 함께 전달할 수 있습니다. 주의할 점은 invoke 명령은 리모트의 람다를 직접 실행하는 것이며 로컬의 함수를 실행하는 것이 아닙니다. 함수는 가장 최신 버전이 실행됩니다.

예제

이벤트 없이 함수 실행하기

$ apex invoke collect-stats

JSON 이벤트를 전달해서 실행하기

$ echo -n '{ "value": "Tobi the ferret" }' | apex invoke uppercase
{ "value": "TOBI THE FERRET" }

파일의 내용으로 실행하기

$ apex invoke uppercase < event.json

클립보드의 내용을 표준 입력으로 전달하여 함수 실행하기

$ pbpaste | apex -C path/to/project invoke auth

phony를 이용해서 데이터를 생성한 후 여러 리퀘스트를 생성하여 함수 실행하기

$ echo -n '{ "user": "{{name}}" }' | phony | apex invoke uppercase
{"user":"DELMER MALONE"}
{"user":"JC REEVES"}
{"user":"LUNA FLETCHER"}
...

스트리밍으로 함수를 실행하고 로그를 출력하기

$ echo -n '{ "user": "{{name}}" }' | phony | apex invoke uppercase --logs
START RequestId: 30e826a4-a6b5-11e5-9257-c1543e9b73ac Version: $LATEST
END RequestId: 30e826a4-a6b5-11e5-9257-c1543e9b73ac
REPORT RequestId: 30e826a4-a6b5-11e5-9257-c1543e9b73ac  Duration: 0.73 ms   Billed Duration: 100 ms     Memory Size: 128 MB Max Memory Used: 10 MB
{"user":"COLTON RHODES"}
START RequestId: 30f0b23c-a6b5-11e5-a034-ad63d48ca53a Version: $LATEST
END RequestId: 30f0b23c-a6b5-11e5-a034-ad63d48ca53a
REPORT RequestId: 30f0b23c-a6b5-11e5-a034-ad63d48ca53a  Duration: 2.56 ms   Billed Duration: 100 ms     Memory Size: 128 MB Max Memory Used: 9 MB
{"user":"CAROLA BECK"}
START RequestId: 30f51e67-a6b5-11e5-8929-f53378ef0f47 Version: $LATEST
END RequestId: 30f51e67-a6b5-11e5-8929-f53378ef0f47
REPORT RequestId: 30f51e67-a6b5-11e5-8929-f53378ef0f47  Duration: 0.22 ms   Billed Duration: 100 ms     Memory Size: 128 MB Max Memory Used: 9 MB
{"user":"TOBI FERRET"}
...

함수 목록

apex list로 함수 목록을 출력할 수 있습니다.

테라폼 변수 출력도 지원합니다.

$ apex list --tfvars
apex_function_bar="arn:aws:lambda:us-west-2:293503197324:function:testing_bar"
apex_function_foo="arn:aws:lambda:us-west-2:293503197324:function:testing_foo"

함수 삭제

함수를 삭제할 때 apex는 정말 삭제할 것인지 물어볼 것입니다. -f, --force 플래그를 설정하면 이 과정을 건너뜁니다. 함수 이름을 지정하면 지정된 함수만 삭제합니다.

예제

모든 함수 삭제

$ apex delete
The following will be deleted:

  - bar
  - foo

Are you sure? (yes/no):

강제 삭제 (삭제할지 묻지 않음)

$ apex delete -f

특정 함수만 삭제

$ apex delete -f foo bar

auth로 시작하는 이름을 가진 함수만 삭제

$ apex delete auth*

Gradle dependency에 로컬 라이브러리 파일 포함시키기

사내에서 혹은 개인이 개발한 라이브러리의 경우 혹은 라이브러리 개발자가 jar 형태로만 배포하거나 소스 코드를 직접 빌드해서 사용해야 하는 경우라면 프로젝트 내부 폴더에 jar 파일을 배치한 후 include 사용하고 싶을 경우가 있다. 이 경우 gradle의 fileTree 를 이용해서 해결할 수 있다.

dependencies {
   compile fileTree (dir: 'lib', include:['**/*.jar'])
}