はじめる前に
- 必須AWS アカウントを持ち、マネジメントコンソールにサインインできること
- 必須Lambda 関数をコンソールで作り、テストイベントで実行した経験があること
- あると良い「データベース(データをためておく場所)」「表(テーブル)」のイメージ
- あると良いLambda の権限(実行ロール)に、操作したいサービスの許可を足す、という考え方
※ このハンズオンは すべてコンソールだけで完結します。保存できたかどうかは、DynamoDB の画面で表(テーブル)を開いて確認します。
🌱 プログラミングがはじめての人へ
コードはこのページにすべて用意してあります。コピーして貼り付けるだけで動きます。書いてある内容は 1 行ずつ日本語で説明するので、いま意味が分からなくても大丈夫。「プログラムでデータを保存する」体験が目的です。
参照する公式ドキュメント
手順に迷ったときや、用語の意味を確かめたいときに開きましょう。
event から入力を受け取る、という Python のお作法を確認できます。
docs.aws.amazon.com/ja_jp/lambda/latest/dg/python-handler.html
※ リンク切れの場合は、ページタイトルで検索してください。
背景・シナリオ
プログラムは、動いている間はデータを覚えていますが、終わると忘れてしまいます。「受け取った内容をあとで見返したい」「貯めておきたい」となると、どこかに保存しておく場所が必要です。それがデータベースです。
AWS の DynamoDB は、サーバーの用意や管理が要らないサーバーレスのデータベースです。テーブル(表)を作っておき、そこへ項目(1 件分のデータ)を書き込んだり読み出したりします。今回は、Lambda が受け取ったデータを DynamoDB のテーブルに保存し、保存された内容を画面で確かめます。これで「処理する Lambda」と「貯めておく DynamoDB」が組み合わさり、サーバーレスで小さなアプリの土台ができます。
DynamoDB の「テーブル」「項目」って何?
テーブルはデータをためる表、項目はその1 行ぶんのデータです。各項目には「id」などの目印(キー)を付けて区別します。今回は、id と message(メッセージ)を持つ項目を保存します。
Lambda が DynamoDB を操作するのに、特別な準備は要る?
はい。Lambda には「DynamoDB に書き込んでよい」という権限を持たせる必要があります。Lambda の実行ロールに、その許可を足します(手順の中で行います)。「やってよいことだけを許可する」という、AWS 共通の考え方です。
Lambda 関数から DynamoDB のテーブルへデータを書き込み、DynamoDB の画面で、保存された項目(id とメッセージ)が表示されることを確認する。テストを変えて実行すると、項目が増えることも確かめる。
つくる構成
Lambda に入力(id とメッセージ)を渡すと、Lambda がそれを DynamoDB のテーブルに書き込みます。書き込まれた項目は、テーブルにどんどん貯まっていきます。
message = はじめての保存
| id | message |
|---|---|
| 1 | はじめての保存 |
| 2 | 2 件目のメッセージ |
保存された内容は、DynamoDB の画面でいつでも見返せます。
要件
以下の要件を満たし、保存された項目が DynamoDB の画面に現れることを確認してください。
| No | 要件 |
|---|---|
| 1 | リージョンは「東京(ap-northeast-1)」を使用する。 |
| 2 | DynamoDB テーブルを 1 つ作成する。テーブル名は messages、パーティションキーは id(文字列)。 |
| 3 | Lambda 関数を 1 つ作成する。ランタイムは Python(最新版でよい)。本文のサンプル(受け取った id とメッセージを保存する)に置き換えて保存(デプロイ)する。 |
| 4 | Lambda の実行ロールに DynamoDB を操作できる権限を追加する(学習用に、例:マネージドポリシー AmazonDynamoDBFullAccess)。 |
| 5 | テストイベントに {"id": "1", "message": "はじめての保存"} を設定してテスト実行する。 |
| 6 | DynamoDB のテーブルの項目を表示し、保存された項目が現れていることを確認する(id を変えて再実行すると項目が増える)。 |
構築の進め方
「テーブルを作る → 保存するコードを貼る → 権限を足す → 実行して画面で確認」の順に進みます。コードは貼り付けるだけ。意味は 1 行ずつ説明します。
-
リージョンを合わせ、DynamoDB テーブルを作る
リージョンが東京であることを確認し、
DynamoDBコンソールで「テーブルの作成」を押します。テーブル名にmessages、パーティションキーにid(タイプは文字列)を指定し、ほかは初期設定のまま作成します。読み込み/書き込みキャパシティモード
オンデマンド使った分だけ課金。容量の事前設定が不要プロビジョンド読み込み・書き込みの容量を自分で確保↳学習用の少量アクセスなので「オンデマンド」を選びます
パーティションキーとは各項目を区別するための主な目印(キー)です。今回は
idをキーにするので、項目ごとに違う id を付けます。コードでもこのidという名前を使うので、つづりをそろえておきましょう。 -
保存するコードを貼り付ける
Lambdaコンソールで「関数の作成」→「一から作成」を選び、関数名save-message、ランタイム Python(最新版)で作成します。「コードソース」の中身をすべて消して、次のコードを貼り付け、「Deploy」で保存します。ざっくり言うと:受け取った id とメッセージを、DynamoDB の表(テーブル)に 1 件保存するプログラムです。(細かい意味は、コードの下で 1 行ずつ説明します)
import boto3 table = boto3.resource("dynamodb").Table("messages") def lambda_handler(event, context): table.put_item(Item={ "id": event["id"], "message": event["message"] }) return "保存しました"
- import boto3Python から AWS のサービス(今回は DynamoDB)を操作するための道具(ライブラリ)を読み込んでいます。Lambda には最初から入っています。
- table = boto3.resource("dynamodb").Table("messages")
messagesという名前のテーブルを操作する準備をして、tableという入れ物に入れています。以降はtableを通じて読み書きします。 - def lambda_handler(event, context):関数の「入口」です。
eventに、保存したいデータ(id とメッセージ)が渡されてきます。 - table.put_item(Item={ "id": ..., "message": ... })テーブルに1 件のデータ(項目)を書き込む命令です。
eventから取り出した id とメッセージを、項目として保存しています。 - return "保存しました"処理が終わったことを表すために「保存しました」を返しています。
テーブル名・キー名をそろえるコードの
"messages"と"id"は、手順 1 で作ったテーブル名・キー名と同じつづりでなければなりません。違うと保存に失敗します。 -
Lambda に「DynamoDB を操作できる権限」を足す
関数の画面で「設定」タブ →「アクセス権限」を開き、表示されている実行ロールのリンクをクリックします(IAM の画面が開きます)。そこで「許可を追加」→「ポリシーをアタッチ」を選び、
AmazonDynamoDBFullAccessを検索してアタッチします。なぜ権限が要るの?Lambda は初期状態では、ログを書く程度の権限しか持っていません。DynamoDB に書き込むには、その許可を実行ロールに足す必要があります。今回は学習のため操作全般を許可しますが、本番では「このテーブルへの書き込みだけ」のように絞るのが安全です(最小権限)。
-
テストイベントを用意して実行する
関数の「テスト」を押し、テストイベントの内容を次に置き換えて保存し、もう一度「テスト」で実行します。「実行結果: 成功」と表示され、結果に「保存しました」が返れば、書き込みの呼び出しは成功です。
{ "id": "1", "message": "はじめての保存" }id を変えて何度か試すid を
"2"、"3"…と変えて実行すると、別々の項目として増えていきます。同じ id で実行すると、その項目は上書きされる点も、あとで画面で確かめてみましょう。 -
DynamoDB の画面で保存された項目を確認する
DynamoDBコンソールでmessagesテーブルを開き、「テーブルアイテムの操作」→「項目を返す(スキャン)」などで項目一覧を表示します。保存した id とメッセージの項目が現れているはずです。id を変えて実行したぶん、項目が増えていることも確認しましょう。これで「保存」が完成サーバーを 1 台も立てずに、「受け取って → 保存する」ができました。ここに前段の受付(API)を足せば、外から送られたデータを保存するアプリにも発展できます。
つまずきポイント
初学者がよく引っかかる箇所を先回りでまとめました。答えそのものは載せていませんが、「どこを見直せばよいか」の手がかりとして使ってください。
「保存しようとすると、権限がないと怒られる」
Lambda の実行ロールに DynamoDB の権限が足りていない可能性が高いです。①手順 3 で、実行ロールに DynamoDB のポリシー(AmazonDynamoDBFullAccess など)をアタッチしたか、②アタッチ後に少し待ってから再実行したかを見直しましょう。権限の反映に少し時間がかかることがあります。
「ResourceNotFound や ValidationException が出る」
名前やキーの食い違いが原因のことが多いです。①コードのテーブル名 "messages" が、作ったテーブル名と一致しているか、②パーティションキーの名前 "id" が、テーブルのキー名と一致しているか、③テスト実行と同じリージョンにテーブルがあるかを確認しましょう。つづりの違いや、別リージョンでの作成がよくある原因です。
完了チェック
要件の再確認ではなく、画面のどこを見れば達成を確認できるかをまとめました。DynamoDB・Lambda のコンソールを開いて、次を順に確かめましょう。
- DynamoDB に
messagesテーブルがあり、パーティションキーがidになっている。 - Lambda 関数
save-messageがあり、コードが Deploy 済みになっている。 - その関数の実行ロールに、DynamoDB を操作できる権限が付いている。
- テスト実行が 「成功」し、結果に「保存しました」が返る。
- DynamoDB のテーブルに、保存した項目(id とメッセージ)が表示される(id を変えると項目が増える)。
考えてみよう
手を動かすことに加えて、次の問いに自分の言葉で答えられるようにしておくと、理解がより深まります。
- プログラムは終わるとデータを忘れてしまうのに、DynamoDB に保存すると残りました。「プログラムの中で覚えておく」のと「データベースに保存する」のは、どう違うのでしょうか。
ヒント
プログラムが覚えているのは、動いている間だけの一時的なものです。終われば消えます。データベースに保存すると、プログラムが終わっても・別の実行からでも、同じデータを読み出せます。「一時的」と「ずっと残る」の違い、という観点で考えてみましょう。 - 今回は学習のため、Lambda に「DynamoDB の操作全般」を許可しました。実際の運用では、これをどう絞るとより安全でしょうか。
ヒント
「すべての DynamoDB」ではなく「このmessagesテーブルだけ」「書き込みだけ(削除は不可)」のように絞れます。許可を狭くするほど、間違いや乗っ取りのときにできることも限られます。「必要な操作・必要なテーブルだけ」を許可する、という観点で考えてみましょう。 - 今回は「テスト」ボタンからデータを保存しました。外から送られてきたデータを保存するアプリにするには、この関数の前に何を足せばよさそうでしょうか。
ヒント
URL にアクセスされたら動く受付(API)を前に置けば、外から送られたデータを受け取って、この関数で DynamoDB に保存できます。「受付(API)+ 処理(Lambda)+ 保管(DynamoDB)」という組み合わせを思い浮かべてみましょう。
後片づけ
学習で作ったものを片づけます。DynamoDB のテーブルは、置いておくだけでも少額の料金がかかる場合があるため、使い終わったら削除しましょう。
- DynamoDB テーブルを削除する:DynamoDB コンソールで
messagesテーブルを選び、削除します(保存した項目も一緒に消えます)。 - Lambda 関数を削除する:「関数」一覧で
save-messageを選び、「アクション」→「削除」で消します。 - ログを削除する(任意):CloudWatch の「ロググループ」から、この関数のログを削除できます。
消す前に、残したいデータがないか確認
テーブルを削除すると、中に保存した項目もすべて消え、元に戻せません。残したいデータがある場合は、消す前に内容を控えておきましょう。学習用のデータだけなら、そのまま削除して大丈夫です。
コストに関する注意: DynamoDB は、保存しているデータ量と読み書きの量に応じて課金されます(オンデマンドの場合、使った分だけ)。新規アカウントには無料利用枠があり、今回のように少数の項目を保存して試す程度なら、ごく少額か無料の範囲に収まることが多いです。Lambda も呼び出し回数・実行時間に応じた課金で、毎月かなりの回数までの無料枠があります。IAM ロール・ポリシーの利用に料金はかかりません。使い終えたら、上の「後片づけ」でテーブルと関数を削除しておきましょう(テーブルを置いたままにすると、わずかでも料金が続くことがあります)。最新の料金は AWS の公式料金ページで確認してください。