BETA

serverless-frameworkの使い方

投稿日:2020-07-04
最終更新:2020-07-04

概要


この記事を読むと、こんなことがわかります

  • serverless-frameworkを使って
  • 任意のAWSアカウントに対して
  • 定時実行される
  • configファイルが外出しされた
  • 外部ライブラリも搭載したLambdaを実装+デプロイする
  • Infra as a Codeを実践できるようになる

定時刻にSlackへコメントを流すbotを作りながら、serverless-frameworkの基本的な使い方をみていきます。
トリガー設定、外部ファイル参照、外部ライブラリの搭載などが含まれるため、ご自身の状況に合わせて適宜改造しちゃってください。

最終的なソースはこちら
【GitHub】serverless-framework-call-slack

インストール+環境構築

前提

  • Mac OS X Catalina
  • 使用言語:python
  • node.jsはインストール済(v4以上を使用),
  • pythonはインストール済(3系使用)
  • AWSアカウントは作成済
  • SlackのIncomming-WebhookのURLを取得済み

なお、SlackのURLの取り方は解説記事がたくさんある
例:【Qiita】slackのIncoming webhookが新しくなっていたのでまとめてみた

serverless-frameworkをインストールする

下記コマンドで一発インストール完了。次のコマンドで正常にインストールされたかを確認する。バージョンが表示されればオッケー。
なお、自動でエイリアスが張ってあるので、以下のコマンドは全て「serverless」を「sls」に読み替えても成立する。

# インストール  
$ npm install -g serverless  

# 確認  
$ serverless --version  
1.28.0  

# あるいはこんな表示になるかも?とかくバージョン情報がでればOK  
$ serverless --version  
Framework Core: 1.74.1  
Plugin: 3.6.15  
SDK: 2.3.1  
Components: 2.31.11  

# これでも同じ結果が得られる  
$ sls --version  
1.28.0  

プロバイダーアカウントのセットアップ

serverless-frameworkはAWS内の1ユーザーとしてAWSアカウントへアクセスすることになる。ゆえに新規にユーザー発行が必要になる。
要は以下3つのことをやればよいので、コンソール画面からでも可能。

  • 新規IAMユーザーを作成する
  • アクセスキーとシークレットアクセスキーを発行する
  • 作成したユーザーにAdministratorAccessのポリシーを付与する

※もちろんXXXX....とYYYY....の部分は各環境にて異なる文字列がでているので、適宜読み替える。

# serverless-framework用専用ユーザー作成  
$ aws iam create-user --user-name serverless-framework  
$ aws iam add-user-to-group --user-name serverless-framework --group-name admin  
$ aws iam create-access-key --user-name serverless-framework  
{  
    "AccessKey": {  
        "UserName": "serverless-framework",  
        "AccessKeyId": "XXXXXXXXXXXXXXXXXXXX",  
        "Status": "Active",  
        "SecretAccessKey": "YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY",  
        "CreateDate": "2020-07-04T04:10:00Z"  
    }  
}  

$ vim ~/.aws/credentials  
# 下記を追記  
[serverless-framework]  
aws_access_key_id=XXXXXXXXXXXXXXXXXXXX  
aws_secret_access_key=YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY  

【参考資料】

※(必須ではない処理)
筆者は~/.aws/credentialsの[default]の値をわざと削除している。
AWSアカウントの指し先を指定をせずに、あるいは指定を忘れて意図しない場所に意図しない処理をかけてしまうことを防ぐため。

はじめてのデプロイ

下記コマンドでフォーマットを作成する。
するとこのような階層でディレクトリとファイルが作成される。

$ serverless create --template aws-python3 --name call-slack --path call-slack  
$ tree ./call-slack/  
call-slack  
├── .gitignore  
├── handler.py  
└── serverless.yml  

簡単にコマンドの説明を付記する。
--template
AWS Lambda用に各言語に合わせたテンプレートを用意してくれる。
詳細は公式ドキュメントへ。代表的なものはこちら

  • aws-nodejs
  • aws-nodejs-typescript
  • aws-alexa-typescript
  • aws-python
  • aws-python3
  • aws-ruby
  • aws-java-maven
  • aws-java-gradle
  • aws-scala-sbt
  • aws-csharp
  • aws-go
  • aws-go-dep
  • aws-go-mod

--name
プロジェクトの名前をつける。
call-slack/serverless.ymlの冒頭の名前にくる。
なお都合上他のリソースと同名をつけるとあとでデプロイが失敗するため注意

--path
トップのディレクトリの名前を指定する。

さて、この時点ですでにデプロイはできるが、指し先だけ設定してあげる。
serverless.ymlを開き、デフォルトででてくる余計なコメントを削除し、下記の部分にprofile: serverless-frameworkを追記

service: call-slack  

provider:  
  name: aws  
  runtime: python3.8  
  profile: serverless-framework # <-ここを追記  

functions:  
  hello:  
    handler: handler.hello  

その後、serverless.ymlがある階層で以下のコマンドを打つ。
するとバージニアリージョン(us-east-1)に「call-slack-dev-hello」という名前のLambdaができているはず。
なお、削除するときにはremoveと打てば完了。(次節から東京リージョンにLambdaを作成していくため、ここでは削除しておく)

# デプロイ  
$ serverless deploy  

# 削除  
serverless remove -v  

キックされるトリガー部分の作り方

CloudWatch のEventBridgeを使って、定時刻にLambdaを叩くトリガー部分を作成する。
(トリガーついでにリージョンを東京に修正しておく)
serverless.ymlの下記コメント欄以下を追記し、$ serverless deployをする。
コンソール画面で確認すると、トリガー部分が追加されているはずである。
※なお、このcronはUTC時刻であることに注意

service: call-slack  

provider:  
  name: aws  
  runtime: python3.8  
  profile: serverless-framework  
  region: ap-northeast-1 # <- ここも追記  

functions:  
  hello:  
    handler: handler.hello  
    # ↓<===== ここから追記 =======>↓  
    events:  
      - eventBridge:  
          schedule: cron(0 9 * * ? *)  

configファイルを外部ファイルとして読み込む方法

キー情報など、リポジトリに直接組み込みたくないファイルもある場合は、外部ファイルを読み出す設定を行う。
手始めにcronで動かす時刻を外出ししてみよう。

まず外部ファイルとしてconfig.ymlという名前のファイルをcall-slackディレクトリ内に作成し、下記の内容を書き込む。

schedule: cron(0 9 * * ? *)  

次にトリガー部分を修正する。serverless.yml下記コメントの部分を修正し、$ serverless deployでデプロイする
なお、file()のカッコ内は相対パスで指定することができる。

service: call-slack  

provider:  
  name: aws  
  runtime: python3.8  
  profile: serverless-framework  
  region: ap-northeast-1  

functions:  
  hello:  
    handler: handler.hello  
    events:  
      - eventBridge:  
          schedule: ${file(./config.yml):schedule} # <= ここを修正  

外部ライブラリを積み込む方法

slackに通知を送る部分を作成する。
今回はrequestsライブラリをpipで取得してLambdaに搭載する。
ここではserverless-frameworkのプラグインであるserverless-python-requirementsを利用する。
※なお、これはpipで呼び出したライブラリをDockerを使ってAmazon Linux内でビルドしてくれる優れモノではあるが、個人開発のOSSである。

まずcall-slackディレクトリ直下で以下のコマンドを叩くと、必要なライブラリが取得できる。
次に、requirements.txtを作り、必要なライブラリを記入する。

# プラグイン追加  
$ npm install --save serverless-python-requirements  

# 取得したいPythonライブラリを記入  
$ vim requirements.txt  
# 以下を記入  
requests  

次にconfigファイルにURLを追記する。
Your-slack-incomming-webhookの部分は各人のSlackのWebHookに読み替えること。

schedule: cron(0 9 * * ? *)  
Slack-WebHook: Your-slack-incomming-webhook  

そしてhandler.pyを以下のように書き換える。(Slackに通知する最低限の実装)
url='Your-slack-incomming-webhook'は以下略

import json  
import requests  

def post_message(url, message):  
    """Post a message to slack using a webhook url."""  
    data = {'text': message}  
    response = requests.post(url, data=json.dumps(data), headers={'Content-Type': 'application/json'})  
    return response.status_code  


def hello(event, context):  
    return post_message(  
        url='Your-slack-incomming-webhook',  
        message='This is test message from AWS Lambda and serverless-framework'  
    )  

ここで$ serverless deployしテストすれば、Slackへ通知が飛ぶはず。こんな感じで(サムネはきっと違うけど)

キー情報をssmに外出し

ssmパラメータを使えば、パラメータを安全に保持することができる。
こちらに情報を外出しし、適宜アクセスできるようにする。
serverless-frameworkには、CloudFormationのリソース定義がほぼそのまま書くことができる。
ついでssmパラメータを読み取る権限も付与する。

service: call-slack  

provider:  
  name: aws  
  runtime: python3.8  
  profile: ume-serverless-framework  
#######################################  
# ↓ここから追記↓ 権限付与  
#######################################  
region: ap-northeast-1  
  iamRoleStatements:  
    - Effect: "Allow"  
      Action:  
        - "ssm:Describe*"  
        - "ssm:Get*"  
        - "ssm:List*"  
      Resource:  
        - "*"  
#######################################  
# ↑ここまで↑  
#######################################  


functions:  
  hello:  
    handler: handler.hello  
    events:  
      - eventBridge:  
          schedule: ${file(./config.yml):schedule} # <= ここを修正  

plugins:  
  - serverless-python-requirements  

custom:  
  pythonRequirements:  
    dockerizePip: true  

#######################################  
# ↓ここから追記↓ ssmパラメータ作成  
#######################################  
resources:  
  Resources:  
    ssmParam:  
      Type: "AWS::SSM::Parameter"  
      Properties:  
        Name: Slack-WebHook  
        Type: String  
        Value: ${file(./keys.yml):Slack-WebHook}  

また、Lambda本体を以下のように書き換える。

import json  
import requests  
import boto3  

ssm = boto3.client("ssm", region_name="ap-northeast-1")  

def get_ssm_params(ssm_parameter_key):  
    param_dict = ssm.get_parameter(Name=ssm_parameter_key)  
    return param_dict.get('Parameter').get('Value')  


def post_message(url, message):  
    """Post a message to slack using a webhook url."""  
    data = {'text': message}  
    response = requests.post(url, data=json.dumps(data), headers={'Content-Type': 'application/json'})  
    return response.status_code  


def hello(event, context):  
    return post_message(  
        url=get_ssm_params('Slack-WebHook'),  
        message='This is test message from AWS Lambda and serverless-framework'  
    )  

ここで$ serverless deployしテストすれば、先ほどと同じくSlackへ通知が飛ぶはず。

最後に

Infra as a Code万歳!

参考文献

Serverless Frameworkの使い方まとめ
Serverless Frameworkのプラグインを利用した外部モジュールの管理

技術ブログをはじめよう Qrunch(クランチ)は、プログラマの技術アプトプットに特化したブログサービスです
駆け出しエンジニアからエキスパートまで全ての方々のアウトプットを歓迎しております!
or 外部アカウントで 登録 / ログイン する
クランチについてもっと詳しく

この記事が掲載されているブログ

@editechの技術ブログ

よく一緒に読まれる記事

0件のコメント

ブログ開設 or ログイン してコメントを送ってみよう