simplestarの技術ブログ

目的を書いて、思想と試行、結果と考察、そして具体的な手段を記録します。

AWS:はじめてのLambda⇄ElastiCache

概要

PlayFab のバックエンド処理が AWS と連携できます。
具体的には同期 http 通信が行えるので、そこを AWSAPI Gateway → Lambda → ElastiCache とつなぎます。
前回の記事
simplestar-tech.hatenablog.com
で確認できた ElastiCache と Lambda の接続を見るために、Lambda の作り方をマスターしてみましょう。

VPCアクセスできるロールを作る

いきなり Lambda から離れるなと思うところですが、Lambda を作るにはロール、つまり役割が定義されてないといけません。
ということでサービス一覧の IAM からロールを選んで新規ロール作成で以下のように LambdaVPC で検索できるポリシーを持つロールを作ります。

f:id:simplestar_tech:20190916202333p:plain
AWSLambdaVPCAccessExecutionRole

作ったロールを、今度は Lambda 新規作成時に割り当てます。
Lambda の実装は後で zip ファイルをアップロードして完了させますので、一から作成など、適当に作ります。

f:id:simplestar_tech:20190916202631p:plain
Lambda に AWSLambdaVPCAccessExecutionRole のポリシーを持つロールを設定

作った Lambda はロールの内容からデザイナー上では次の通りにビジュアライズされます。

f:id:simplestar_tech:20190916202828p:plain
デザイナーの見た目(VPCアクセス可能を意味する)

ElastiCache と Lambda のセキュリティグループを合わせる

EC2 のサービス項目にセキュリティグループというものがありますが、そこにはディフォルトのセキュリティグループがあります。
それは、インバウンドのすべての許可ソースに自身のセキュリティグループという、VPC 内に限りすべての通信を行えるセキュリティグループとなっています。
※あくまで許可対象のソースはセキュリティグループなので、外部からの入力は受け付けないので、大丈夫(IPアドレス範囲だと全公開だから危険だよ)

対象の ElastiCache を選択して変更メニューからセキュリティグループを default に設定します。

f:id:simplestar_tech:20190916203343p:plain
ElastiCache のセキュリティグループ

同じように Lambda のネットワーク設定を調べて、セキュリティグループを default に設定します。

f:id:simplestar_tech:20190916203553p:plain
Lambda のネットワーク設定

これで ElastiCache と Lambda の間で互いに通信できるようになりました。(default セキュリティグループをつけると自身のグループ内で通信がすべて許可されているので)

Lambda で ElastiCache(Redisモード)にアクセス

今回は Lambda を python で実装します。
Windows 環境なら Anaconda で python コマンドを実装できるようにし、適当なフォルダをカレントに、まずは次のファイルを作成します。
lambda_function.py

from __future__ import print_function
import redis
import uuid

#elasticache settings
r = redis.StrictRedis(host='c4096-000-000-000.xxxxxx.xxxxxx.xxxxx.cache.amazonaws.com', port="6379", db=0)

def handler(event, context):
    """
    This function puts into memcache and get from it.
    Memcache is hosted using elasticache
    """

    #Create a random UUID... this will be the sample element we add to the cache.
    uuid_inserted = uuid.uuid4().hex
    #Put the UUID to the cache.
    r.set('uuid', uuid_inserted)
    #Get item (UUID) from the cache.
    uuid_obtained = r.get('uuid')
    if uuid_obtained.decode("utf-8") == uuid_inserted:
        # this print should go to the CloudWatch Logs and Lambda console.
        print ("Success: Fetched value %s from memcache" %(uuid_inserted))
    else:
        raise Exception("Value is not the same as we put :(. Expected %s got %s" %(uuid_inserted, uuid_obtained))

    return "Fetched value from memcache: " + uuid_obtained.decode("utf-8")

このままだと redis が不足しているので、そのフォルダで

pip install redis -t . 

を実行します。-t . コマンドはカレントフォルダにパッケージを配置するというオプションです。
そのまま実行しても、接続エラーになります。

lambda_function.py が置かれているフォルダのすべてのファイル・フォルダを選択して zip 圧縮し、これを Lambda の zip としてアップロードの操作で選択します。
保存ボタンを押すと次の通り、右側の関数の指定では、ファイル名.関数名 を記述します。

f:id:simplestar_tech:20190916204554p:plain
関数の指定

あとはテストボタンを押せば…ご覧の通り redis モードの ElastiCache に uuid を詰めて、出して、値が一致していることが確認できました。

f:id:simplestar_tech:20190916204715p:plain
Lambda テスト実行結果

やりました。

まとめ

今回の勘所は次の通り
・ElastiCache にアクセスしたければ Lambda のロールには AWSLambdaVPCAccessExecutionRole ポリシーだけあればいい
・ElastiCache と Lambda は default セキュリティグループを当てる(よりキビしく TCP 6379 接続だけ許すセキュリティグループでもいいかもね)
python 実装では redis を import して使う
・Lambda で pip install が必要なときはローカルで -t . オプションで全部入りを作って zip 圧縮してアップロード

Lambda だけではなく IAMロール、セキュリティグループについても経験値がたまる入門記事になりました。