Help us understand the problem. What is going on with this article?

ServerlessインストールからLambdaへのデプロイ

More than 1 year has passed since last update.

はじめに

サーバーレスアプリケーション(以後SLA)の開発のためのフレームワークServerlessを使って、nodejsベースのAWS Lambda上で動く関数作成からデプロイまでやります。公式のQuick startが微妙だなと思ったので、備忘録として書いておきます。

なぜSLA開発にフレームワークを使うのか

コードの変更はローカルで、ビルドはEC2やDockerで、デプロイはS3で、ハンドラの設定はLambdaで、APIの設定はAPI Gatewayで、ログの確認はCloudWatchで、という開発プロセスは辛いので、自前で開発環境を整えるか、フレームワークを使ったほうが良いと思うからです。

小規模なアプリケーションだったり、一回書いておしまいということであれば、Lambdaのインラインエディタとテスト機能だけで用が済むかもしれません。しかし、アプリケーションが少し大きくなったり、少し手の込んだことをしようとするだけで、SLA開発の性質や、Lambdaの制限によって、CI/CDのコストが跳ね上がります。例えば、

  • コード中で外部のパッケージを利用する場合、デプロイが辛くなる。関数ファイルと外部パッケージをzipしてLambdaにアップロードする必要がある
  • その場合、Lambdaと開発環境をそろえようと思うと、EC2やDockerを利用することになる
  • アップロードするzipファイルサイズが3MBを越えた場合、インラインエディタで編集できなくなる
  • zipファイルサイズが10MBを越えた場合、コードを変更するたびにzipファイルをS3にアップロード -> S3からLambdaにインポートという手順を踏む必要がある

Serverlessを使うことによって、

  • sls deployコマンドだけでデプロイができる
  • 裏側でCloudFormationのスタックを利用することによって、S3とLambdaのコードの管理だけでなく、APIやデータベースの設定も一括してやってくれるので、開発に一貫性が生まれる

というメリットがあると思います。

流れ

  • IAM Policyの作成
  • IAM Userの作成
  • .aws/credentialsの編集
  • Serverlessのインストール
  • serverless.ymlの編集
  • デプロイ

まず、ServerlessのプロジェクトがAWS上のサービスを利用するための権限が必要です。必要な権限のセット(IAM Policy)を持ったAWSユーザー(IAM User)のcredentialをプロジェクトにひもづけてやる必要があります。これがIAM PoicyとIAM Userの作成にあたります。

次に、ひもづけるcredentialは、serverless.ymlの中にベタ書きしたくないので、ローカルの .aws/credentialsの中で管理します。

そして、serverless.ymlで.aws/credentials内の目的のcredentialを参照するよう設定します。その他、AWSリージョンや関数名、nodejsのバージョンの設定などを行い、デプロイします。

注意点

  • 公式のQuick startにある設定動画は古いし、ちゃんとしてないのであてにならない
  • AdministratorAccessを献上する必要はない

IAMでカスタムポリシーの作成

ServerlessのGithub上のQuick startでは、AdministratorAccessのポリシーを持ったIAMユーザーのcredentialをセットするように言われているのですが、AdministratorAccessを献上するのはあまり良い気分はしないですよね。別のところでは、公式にこう言われています。

In a production environment, we recommend reducing the permissions to the IAM User which the Framework uses. Unfortunately, the Framework's functionality is growing so fast, we can't yet offer you a finite set of permissions it needs (we're working on this). Consider using a separate AWS account in the interim, if you cannot get permission to your organization's primary AWS accounts.
(https://github.com/serverless/serverless/blob/master/docs/providers/aws/guide/credentials.md)

今回は、ガチガチに管理するわけでもないけど、AdministratroAccessよりは限定して、かつLambdaへのデプロイに十分なカスタムポリシーを作ります。AWSの他のサービスも使う場合は、それに応じてActionに追加します。

AWSのコンソールから、
IAM
-> Policies
-> Create policy
-> JSONタブ
と進み、以下のような形に変更します。S3、Lambdaなど、サービスは限定しつつ、それぞれのサービスのアクションについてはワイルドカードにして限定しない形です。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "Stmt20180730",
            "Effect": "Allow",
            "Action": [
                "s3:*",
                "logs:*",
                "iam:*",
                "apigateway:*",
                "lambda:*",
                "cloudformation:*",
                "events:*"
            ],
            "Resource": [
                "*"
            ]
        }
    ]
}

"Sid"は自分が識別しやすいように、任意のIDを入れます。ガチガチにしたいなら、"Action""Resource"をもっと限定します。でも個人使用では、これぐらいが手軽に管理しやすい落とし所のような気がします。

-> Review policy
-> NameServerlessFrameworkBasicと入力
-> Create policy で完了です。

IAM Userの作成

AWSコンソールで、
IAM
-> Users
-> User namemy-app-userと入力
-> Programmatic accessにチェックを入れる
-> Next:Permissions
-> Attach existing policies directly
-> 先程作成したServerlessFrameworkBasicをポリシーの中から検索してポリシー名左にチェックを入れる
-> Next:Review
-> Create user
-> Download .csvでcredentialをダウンロードしておく

ここで表示されている Access key IDSecret access keyはあとで使います。

.aws/credentialsの編集

作成したIAM Userのcredentialをローカルの~/.aws/credentialにテキストエディタで追加します。なかったら作ります。 serverlessコマンドで入れることもできるようですが、コマンドの中に直接アクセスキーを入れるのはおすすめしないです。

credentials
[任意のプロファイル名]
aws_access_key_id = 先程のAccess key IDをここに入れる
aws_secret_access_key = 先程のSecret access keyをここに入れる

例えば、こんな感じになります。すでに他のcredentialがある場合は、それを上書きするのではなく追加します。

credentials
[default]
aws_access_key_id = ...
aws_secret_access_key = ...

[my-app-user]
aws_access_key_id = 1234567890ABCDEFGHIJ
aws_secret_access_key = 1234567890abcdefghijklmnopqrstuvwxyzABCD

[another-credential]
aws_access_key_id = ...
aws_secret_access_key = ...

ただし、AWS CLIを使っていて、ここで用いるプロファイルが、AWS CLIでデフォルトで使用されているものと異なる場合、後々お気をつけください。参考までに、公式ではこう言われています。

Be aware! Due to the way AWS IAM and the local environment works, if you invoke your lambda functions locally using the CLI command serverless invoke local -f ... the IAM role/profile could be (and probably is) different from the one set in the serverless.yml configuration file. Thus, most likely, a different set of permissions will be in place, altering the interaction between your lambda functions and other AWS resources.

Serverlessのインストールとプロジェクトの作成

nodejsは入っている前提です。2018/07/30現在、AWS Lambdaでサポートされているnodejsのバージョンは主に6.10と8.10なので、8.10を入れておくと、ちょっとしたことをnodeコンソールで試せて便利だと思います。今回serverlessはグローバルにインストール、プロジェクトのルートディレクトリはホームディレクトリ直下に作るとします。

serverlessのインストール
npm i -g serverless
プロジェクト作成
# cd ~ && sls create -t aws-nodejs -p プロジェクト名
cd ~ && sls create -t aws-nodejs -p my-app

プロジェクトのルート・ディレクトリを見ると、handler.jsserverless.ymlができているのが確認できると思います。

プロジェクトディレクトリの確認
ls ~/my-app
# => handler.js     serverless.yml

serverless.ymlの編集

最低限必要な記述はこんな感じです。serverless.ymlのリファレンスを見ると良いと思います。

serverless.yml
service:
  name: プロジェクト名

provider:
  name: aws
  runtime: nodejsのバージョン
  profile: credentialのプロファイル名
  region: リージョン

functions:
 関数名:
    handler: handler.関数名

例えば、
- プロジェクト名はmy-app
- 先程作成した my-app-userのcredentialを使う
- Lambdaのnodejsのバージョンは8.10
- 以下の様なhandler.jsを持っている

handler.js
'use strict';

module.exports.main = (event, context, callback) => {
  const response = {
    statusCode: 200,
    body: JSON.stringify({
      message: 'Go Serverless v1.0! Your function executed successfully!',
      input: event,
    }),
  };

  callback(null, response);
};

とすると、serverless.ymlはこうなります。

serverless.yml
service:
  name: my-app

provider:
  name: aws
  runtime: nodejs8.10
  profile: my-app-user
  region: ap-northeast-1

functions:
  main:
    handler: handler.main

注意したいところは、
- stagedevがデフォルト。デプロイ時にLambda上では関数名にstage名がsuffixされる。
- nodejsのバージョンは6.10がデフォルトで記述されているので、8.10を使用する場合は、見間違えずに変更する。
- regionus-east-1リージョンがデフォルト。デプロイ時にCloudFormationのStackがus-east-1で作成されるので、使用するリージョンがus-east-1でない場合はちゃんと指定しないとエラーが起きる可能性がある。

デプロイ

cd ~/my-app
sls deploy -v

いまのところ、v(verbose)オプションの有無で出力があまり変わらないので、sls deployだけでも良いと思いますが、Starck Outputsを確認したいときはつけても良いと思います。

参考

https://github.com/serverless/serverless
https://serverless.com/framework/docs/providers/aws/guide/serverless.yml/

jumjamjohn
Webアプリケーション開発者。AWS, Rails, Nginx, PostgreSQL, Redis, Elasticsearch, Vue.jsをよく使っている。機械学習や画像処理とも戯れる他、セキュリティ, NLP, RaspberryPiに興味あり。
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした