ApexでAWS Lambda Functionをデプロイする

AvatarPosted by

こんにちは。SREの川野です。
今回は、AWS Lambda Functionをデプロイする際に使用したApexというツールについてご紹介します!

Apexとは

AWS Lambda Functionを簡単に構築・デプロイ・管理するツールです。

悲しいことに2019年6月25日で「No longer maintained」となってしまいました・・・。

主な特徴は以下です。

  • ロールバック、メトリクスの確認、ログの確認、テスト実行などの機能の提供
  • Lambda Functionで公式にサポートされていない言語の使用が可能
  • AWSコンポーネントを管理するためのTerraformのラッパー機能の提供

TerraformでLambdaリソースを作成しようとすると、関数のコードをzipに固めてアップロードするので、関数のコードに変更がなくてもtfstateに差分が出てしまいます。そういった場合にApexを使うことで、tfstateの管理を適切に行うことができます。

インストール

GitHubのReleaseから使用したいバージョンと使用しているOSに合わせたバイナリをダウンロードします。
https://github.com/apex/apex/releases

例:macOS(64bit)の場合

$ wget https://github.com/apex/apex/releases/download/v0.15.0/apex_darwin_amd64
$ mv apex_darwin_amd64 /usr/local/bin/apex
$ chmod +x /usr/local/bin/apex
$ apex version
Apex version 0.15.0

補足:最新の0.16.0は認証情報の拾い方についてIssueが上がっています。そのため今回のこれから説明する手順については、0.15.0で行いました。

AWS認証情報を設定

AWS CLIをインストールして、以下の認証と設定ファイルをそれぞれ作成します。
(参考: AWS CLIのインストール https://docs.aws.amazon.com/ja_jp/cli/latest/userguide/cli-chap-install.html)

~/.aws/credenticals

[default]
aws_access_key_id=[AWSアクセスキー]
aws_secret_access_key=[AWSシークレットキー] 

~/.aws/config

[default]
output=[出力データ形式]
region=[AWSリージョン] 


次はapexコマンドの使い方の説明をします。

初期化

apex initと実行すると、
Project name:Project description:
の入力を求められるので、適当に入力します。

今回は以下のように入力しました。
Project name: apex-lambda
Project description:

すると、以下の初期化処理が実行されます。
1. Lambda Functionを実行するためのロールとポリシーを作成しそれらをアタッチ
2. Lambda Functionの環境設定ファイルproject.jsonを作成
3. サンプル(hello/index.js)を含んだ、実装コードを配置するディレクトリfunctionsを作成

実際の画面

~/apex_project$ 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-lambda

  Enter an optional description of your project.

    Project description:

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

  Setup complete, deploy those functions!

    $ apex deploy

ディレクトリ構成は以下のようになっています。

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

関数のリスト表示

apex list と入力すると、先ほどの apex init コマンドで自動作成されたサンプル関数が表示されます。

~/apex_project$ apex list
hello (not deployed)
     runtime: nodejs6.10
     memory: 128mb
     timeout: 5s
     role: arn:aws:iam::572183290275:role/test-apex_lambda_function
     handler: index.handle
~/apex_project$ cat functions/hello/index.js
 console.log('starting function')
 exports.handle = function(e, ctx, cb) {
   console.log('processing event: %j', e)
   cb(null, { hello: 'world' })
 }

Apexでは、関数ディレクトリごとに環境設定を書くことができます。
./functions/hello/function.json を作成すれば、./project.json の環境設定をオーバーライドします。

実行環境とハンドラーの設定を書く場合は以下のようにします。
(今回はPythonで関数を実装しようと思います。)
ハンドラーは、[関数ファイル名.呼び出す関数]という形式になっています。

~/apex_project$ cat functions/hello/function.json
 {
   "runtime": "python3.7",
   "handler": "lambda_function.lambda_handler"
 }

再度確認してみると、function.json の環境設定を読み込んだ関数が表示されていることがわかります。

~/apex_project$ apex list
hello (not deployed)
     runtime: python3.7
     memory: 128mb
     timeout: 5s
     role: arn:aws:iam::572183290275:role/apex-lambda_lambda_function
     handler: lambda_function.lambda_handler

実行環境とハンドラーの設定を書き換えたので、古い関数ファイル(index.js)を削除して、新しい関数ファイル(lambda_function.py)を以下のように作成します。

import json

def lambda_handler(event, context):
    # TODO implement
    return {
        'statusCode': 200,
        'body': json.dumps('Hello from Lambda!')
    }

現在のディレクトリ構成は以下のようになっています。

.
├── functions
│   └── hello
│       ├── function.json
│       └── lambda_function.py
└── project.json

関数のデプロイ

実装した関数のコードをデプロイします。

~/apex_project$ apex deploy
    • creating function         env= function=hello
    • created alias current     env= function=hello version=1
    • function created          env= function=hello name=apex-lambda_hello version=1

関数の呼び出し

AWSコンソール画面を直接操作しなくても apex invokeコマンドを使用すれば関数を呼び出すことができます。

~/apex_project$ apex invoke hello
 {"statusCode": 200, "body": "\"Hello from Lambda!\""}

AWSコンポーネントの管理

apex infraterraformコマンドのラッパーになっています。
apex_function_関数名 でARNを取得できるので、Apexで作成したLambdaFunctionをTerraformのコードから参照することができます。この参照を使用している際に、terraformコマンドを使用するとARNが取得できないエラーが表示されるので注意が必要です。
(詳細:https://github.com/apex/apex/blob/master/docs/infra.md)

Terraformのコードは、./infrastructure ディレクトリを作成してその中にtfファイルを作成します。

.
├── functions
│   └── hello
│       ├── function.json
│       └── lambda_function.py
├── infrastructure
│   ├── backend.tf
│   ├── main.tf
│   └── variables.tf
└── project.json

実行する際は、infrastructure ディレクトリに移動して下記のように行います。

~/apex_project/infrastructure$ apex infra plan
~/apex_project/infrastructure$ apex infra apply

おわりに

今回の説明は以上になります。

Apexは「No longer maintained」となってしまいましたが、Issueをみてみると2.0としてリリースされる可能性は僅かですがありそうな感じです!

また、類似ツールとしてupというものがあるようなので次の機会に使ってみたいと思います!