Outsider's Dev Story

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

Apex - AWS Lambda 관리도구 #1

지난번에 AWS Lambda를 이용해서 HTTP API 만들기라는 글에서 AWS Lambda를 소개한 적이 있다. 올해 Amazon에서 Lambda 홍보를 많이 하기도 하고 주변에서 Lambda를 프로덕션에 쓰고 있는 소식도 이미 듣고 있지만 원래 저 글을 쓸 때는 3부작(?)으로 생각했던 글이었다. Lambda를 소개하고 Lambda로 쓸만한(?) 예제를 만들고 Apex라는 도구를 설명할 생각이었지만 Lambda 소개까지만 하고는 관련 글을 쓸 여유가 없었다. Apex에 관해서 써야지 써야지 하면서 이제야 쓰게 되었다.

Apex

Apex는 Lambda를 이용한 서버리스 아키텍처를 쉽게 구축할 수 있도록 도와주는 도구이다. Apex는 TJ Holowaychuk이 만들었는데 이 TJ Holowaychuk는 한때 Node.js 최고의 스타 개발자 중 한 명으로 express.js, mocha, superagent, jade, debug 등 수많은 npm 모듈을 만들었다..(지금은 Go로 갔지만)

TJ는 Lambda를 보고 서버리스 아키텍처에 꽂힌 듯 GitHub에 Apex라는 조직을 만들어서 apex라는 도구를 공개했고 1인 기업인 Apex Software Inc를 만들어서 운영하고 있다. 얼마 전에는 Apex Ping이라는 Lambda 기반의 ping 서비스를 만들어서 서비스하는 중이다.

이 모든 움직임이 Apex라는 이름 아래에서 진행되고 있지만 여기서 얘기할 apex는 Lambda를 관리해주는 CLI 도구인 apex이다.1 Lambda는 꽤 놀라운 서비스이기는 하지만 실제로 개발하려면 사용하기가 쉽지 않다. 소스를 작성하고 zip 파일로 압축해서 Lambda에 올려서 실행하거나 웹 브라우저에서 소스를 작성 해야 하는데 Lambda가 익숙한 상황이라면 모를까 처음에는 이 환경에서 개발하는 게 너무 어렵다. 개발하고 나서도 디버깅도 쉽지 않고 로그확인도 상당히 불편한데 버전 관리도 안되기 때문에 중요한 기능을 Lambda에서 사용하려면 형상관리를 따로 사용해서 소스를 관리해야 한다.

Apex를 사용하면 이 모든 과정이 아주 편리해진다. 로컬에서 소스를 작성하고 바로 배포하거나 삭제를 할 수도 있고 제대로 동작하는지 테스트를 바로 할 수 있고 로그를 확인할 수도 있다. 써본 느낌으로는 Lambda를 사용하는 경험이 확 올라가서 Lambda의 필수도구로 느껴진다.

Apex 설치

설치는 curl https://raw.githubusercontent.com/apex/apex/master/install.sh | sh 명령어로 설치할 수 있다.

$ apex version
Apex version 0.10.3

$ apex upgrade
  • current release is v0.10.3
  • latest release is v0.10.3
  • you're up to date :)

apex version이 정상적으로 동작하면 제대로 설치가 된 것이다.(현재 최신 버전은 v0.10.3이다.) 설치 이후 업그레이드를 하려면 apex upgrade를 실행하면 된다. 사용할 수 있는 명령어를 보려면 apex를 실행하면 된다. 명령어가 간단한 편이라 약간 사용해 보면 금세 익숙해질 수 있다.

$ apex

  Usage:
    apex [command]

  Available Commands:
    build        Build a function
    delete       Delete functions
    deploy       Deploy functions and config
    docs         Output documentation
    infra        Infrastructure management
    init         Initialize a project
    invoke       Invoke functions
    list         Output functions list
    logs         Output function logs
    metrics      Output function metrics
    rollback     Rollback functions
    upgrade      Upgrade apex to the latest stable release
    version      Print version of Apex

  Flags:
    -C, --chdir string       Working directory
    -D, --dry-run            Perform a dry-run
    -e, --env string         Environment name
    -h, --help               help for apex
    -l, --log-level string   Log severity level (default "info")
    -p, --profile string     AWS profile
    -r, --region string      AWS region

  Use "apex [command] --help" for more information about a command.

Apex를 Lambda를 사용하므로 AWS를 사용할 API 키가 필요하다. AWS IAM에서 사용자 밑에서 엑세스키를 생성할 수 있다.

AWS IAM의 키 생성

"Create Access Key"를 누르면 키를 Access Key와 Secret Access Key를 얻을 수 있다. 이 키를 다음과 같이 환경변수로 저장하면 된다.(bash 환경인 경우)

export AWS_ACCESS_KEY_ID=YOUR-ACCESS-KEY
export AWS_SECRET_ACCESS_KEY=YOUR-SECRET-ACCESS-KEY
export AWS_REGION=ap-northeast-1

AWS_REGION는 AWS 리전을 의미하는데 각 리전의 이름은 AWS 문서에서 볼 수 있다. 여기서 ap-northeast-1는 도쿄 리전을 의미한다.

AWS IAM의 권한 관리

apex가 Lambda 등을 관리해야 하므로 이 사용자에게 권한을 주어야 한다. 위의 IAM 콘솔에서 Permissions 부분에서 AWSLambdaFullAccessIAMFullAccess 정책을 추가한다. 이 둘의 전체권한이 다 필요한지까지는 정확히 모르겠지만, 권한이 없으면 뒤에서 사용할 때 오류가 발생한다. 이제 apex를 사용할 준비가 완료되었다.

프로젝트 설정

프로젝트 초기화는 apex init 명령어를 사용한다.

$ apex init


             _    ____  _______  __
            / \  |  _ \| ____\ \/ /
           / _ \ | |_) |  _|  \  /
          / ___ \|  __/| |___ /  \
         /_/   \_\_|   |_____/_/\_\



  Enter the name of your project. It should be machine-friendly, as this
  is used to prefix your functions in Lambda.

    Project name: apex-example

  Enter an optional description of your project.

    Project description: Apex Example

  [+] creating IAM apex-example_lambda_function role
  [+] creating IAM apex-example_lambda_logs policy
  [+] attaching policy to lambda_function role.
  [+] creating ./project.json
  [+] creating ./functions

  Setup complete, deploy those functions!

    $ apex deploy

프로젝트 이름과 프로젝트에 대한 설명을 입력하면 된다. 여기서 프로젝트 이름은 공백 등을 사용할 수 없다. 여기서 설정이 제대로 되어 있지 않으면 오류가 발생한다. 위 로그를 보면 알겠지만, 이 프로젝트(여기서는 apex-example)를 사용하기 위한 Role과 Policy를 를 만들고 Role에 Policy를 연결해서 Lambda를 사용할 준비를 맞추었다. 프로젝트별로 Role과 Policy를 따로 만들어서 사용할 다른 AWS 리소스에 대한 접근 권한을 상세하게 제어할 수 있다.

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

이렇게 만들어진 폴더 구조는 위와 같다. project.json는 이 프로젝트의 전역 설정이다. 함수(AWS Lambda에 배포하는 함수를 apex에서는 function이라고 부른다.)별로 설정을 변경할 수도 있지만, 별도로 지정하지 않으면 전역설정이 적용된다. functions 디렉터리 안에는 Lambda 함수가 폴더별로 만들어지는데 init을 하면 예시로 간단한 hello 함수를 만들어준다. 디렉터리별로 하나의 함수가 되므로 한 프로젝트에서 여러 함수를 관리할 수 있다는 의미이다.

project.json

{
  "name": "apex-example",
  "description": "Apex Example",
  "memory": 128,
  "timeout": 5,
  "role": "arn:aws:iam::410655858509:role/apex-example_lambda_function",
  "environment": {}
}

위는 project.json 파일의 내용이다. 이 파일에는 다음과 같은 설정을 지정할 수 있다.

  • name: 프로젝트명이다. 다른 프로젝트와 함수 이름이 겹치지 않도록 항상 이 이름을 함수명 등에 템플릿으로 사용한다.(문자열, 필수값)
  • 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에서 지원한다.
  • memory: Lambda의 할당 메모리(정수, 메가바이트 단위)
  • timeout: Lambda의 함수 실행 만료시간(정수, 초 단위), Lambda는 최대 5분까지를 지원한다.(300초)
  • role: AWS의 Role(문자열)
  • profile: AWS 프로파일명, 앞에서 설정한 AWS 환경변수 대신 여러 가지 AWS 환경을 바꿔가면서 사용할 때 지정하는 용도이다.(문자열)
  • defaultEnvironment: 기본 인프라 환경, 설정을 stage, production등 나누어서 할 수도 있는데 지정하지 않으면 사용할 기본 환경이다.(문자열)
  • environment: Lambda 함수에 적용할 환경 변수이다.(객체)
  • nameTemplate: 함수 이름을 만들 때 사용하는 템플릿으로 기본 템플릿은 {{.Project.Name}}_{{.Function.Name}}이다.(문자열)
  • retainedVersions: 롤백 등에 사용하기 위해 Lambda에서 유지할 함수의 버전 개수.(기본값 10)
  • vpc: AWS의 VPC 설정(객체)
  • vpc.securityGroups: 시큐리티 그룹의 ID 목록(배열)
  • vpc.subnets: 서브넷 ID 목록(배열)

예시 hello 함수

이제 기본으로 만들어진 hello 함수의 내용을 보자.

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

index.js가 hello Lambda 함수의 진입 파일이다. 이 Lambda 함수가 호출되면 exports.handle = function(e, ctx, cb) {}가 호출된다는 의미이다. 이 파일은 단순히 로그를 출력하고 { hello: 'world' }를 반환하는 함수일 뿐이다. 필요한 로직을 구현해서 이 함수 안에 넣고 결괏값은 cb로 반환하면 된다.


이 글은 Apex - AWS Lambda 관리도구 #2로 이어진다.


  1. 비슷한 도구로는 Serverless가 있다. 

2016/09/21 03:33 2016/09/21 03:33