AWS初心者がAWS構築経験を積むためのハンズオン研修を実施した記録を残していきます。
この記事の作者はSEをしておりますが、本業ではAWSなどのクラウド構築できる環境になく、時代に取り残されていく危機感から(今の時代クラウド構築したことないSEってヤバイくないかと思い)、自力で学び、また学んだ事を後日復習できるようにこのような形で残していきたいと思います。
題材はAWSがオンラインで公開しているハンズオン研修からAWS初心者向きのコースを選択して実施していきます。ハンズオン研修は無料利用枠(※)を使用して行っていく予定ですが、無料利用枠で出来ない場合はクーポンなどを駆使してできるだけお金をかけずに学んでいきたいと思ってます。
アカウントを作成して1年以上経過している場合は無料利用枠ありませんが、別の新しいアカウントを作成すれば、作成から1年間無料利用枠を利用する事ができるそうですので、新規アカウント作成して以下のハンズオン試してみると勉強になるかと思まいます。
No | 題名 | 内容 | 実施日 |
1 | サーバーレスアーキテクチャで翻訳 Web API を構築する | API Gateway、Lambda、DynamoDB、TranslateのAWSサービスを使用して翻訳機能をサーバーレスで提供するシステム構築 | 2020/5/3 |
1.サーバーレスアーキテクチャで翻訳 Web API を構築する
構築するシステム構成図
今回構築するシステム構成図は以下のようになります。使用するAWSのサービスはAPI Gateway、Lambda、DynamoDB、Translateを使用します。全てサーバーを建てないサーバーレスのサービスを使用したシステム構成になります。
用語の説明
Amazon API Gateway
API (Application Programming Interface)の作成、配布、保守、監視、保護が行えるフルマネージドなサービスです。とAWSなどのサイトには書かれておりますが、よくわかりません。上の構成図を元に自分の理解で書くと、クライアントからのどんな(Get/Host?、引数はあるのかなど)リクエストがくるか定義し、バックエンドのAWS Lambdaにどんな情報を渡すか、どんあデータをクライアントに変えすかなどを定義している文字通りGatewayの役割を担っているサービスになります。
AWS Lambda
サーバを建てずにプログラムを実行できるサービスです。サーバ管理、スケーリングはAWS側で自動で実施されます。
AWS DynamoDB
フルマネージドのNoSQLデータベースサービス。とAWSのサイトでは書かれていますが、よくわかりません。自分の理解した言葉で書くと、DynamoDBが稼働しているサーバの管理不要のキー指定型データベースという理解です。データを格納する際にはプライマリキーを指定してデータ格納するようです。正直今回のシステム構築作業ではリレーショナルDBとの違いはよくわかりません。
Amazon Translate
AWS SDKの中で既存に用意されている翻訳するツール。今回のシステムでは日本語⇒英語に翻訳します。日本語、英語以外にも複数言語に対応してます。
LambdaからこのSDKを呼び出して翻訳します。
(1)AWS Lambdaの設定を実施します
①マネジメントコンソールにログインします。権限はハンズオンなので管理者などの強い権限でログインします。
②ログインしたら画面右上から東京リージョンに変更します。
もし画面の表示が英語であった場合は、画面一番下の左にスクロールして、言語選択を日本語にします。
③マネジメントコンソールからLambda設定画面に移動するため、サービスを検索するというウィンドウに「Lambda」と入力してリターンキーを押す
④Lambdaの関数画面が表示されます。まだ何も作成していないので、記載ありませんが、以前何か作成している場合は表示されます。
関数の作成をクリックします
⑤関数の作成画面で「一から作成」を選択、関数名に「translate-function」と記載、ランタイムに「Python3.7」を選択します。
ちなみに、「設計図の使用」を選択すると既に用意されている関数を使用できるようです。(例えばS3と接続するfunctionなどあるようです)
⑥画面の下に行ってアクセス権限の設定をします、今回は新しくロールを作成するので一番上の「基本的な~新しいロールを作成」を選択します。既存ロールを使用する場合は既存のロールを使用などの選択します。
ここまで入力したら右下の「関数の作成」をクリックします。
⑦暫く待つと関数が作成され以下の画面が表示されることを確認します。
⑧この関数の使用できるメモリとタイムアウト値を変更します。
画面の下の方に行って、基本設定の「編集」をクリックします。
メモリを256MBに変更し、タイムアウト値は10秒に変更し、保存をクリックします。
保存して前の画面に戻る事を確認します。
⑨この関数のテスト実行をしてみます。「event」という引数に何を渡すかを指定します。
右上の「テスト」をクリックします。
⑩イベント名に「Test」と入力し他のとりまえずそのままで「作成」をクリックします。
前の画面に戻る事を確認します。
⑪先ほど作成した「Test」イベントが選択されている状態でテストをクリックし、Statusが「Succeeded」と表示されていることを確認します。
⑫次にPythonのソースコードを変更してログ出力機能を追加してみます。
ソースを以下のように編集し、保存ボタンをクリックします。
ソースはグーグル検索で「Lambda logging」で検索ヒットした一番最初のURL(以下)にあるLambdaでのロギング関数の記載から必要なコードを取得してきました。
追加/修正したのは2、4、5、9行目になります。
https://docs.aws.amazon.com/ja_jp/lambda/latest/dg/python-logging.html
⑬前の画面に戻り、「テスト」をクリックします。テストイベントで与えた値が表示されていることを確認します。
⑭もう一つのログの確認のやり方として、画面の上に戻り、「モニタリング」⇒「CloudWatchのログを表示」をクリックします。
2回テスト実行したのでログが2件表示されており、上の最新のログをクリックします
引数で渡した値などがログに表示されていることを確認します。
(2)AWS LambdaからAWS Translate翻訳ツールを呼び出せるようにします。
Lambda関数を修正する画面に戻ります。画面左上の「AWS」のロゴをクリックすると、マネジメントコンソールの画面に戻るのでサービスを検索するでLambdaと入力しリターンキーを押します。
以下の画面が表示されるので作成した「translate-function」を選択します
①先ほどログ出力するように変更した箇所は不要で、ソースコードを以下のように書き換え、保存をクリックします。
以下のコードをコピペします。
import json
import boto3
translate = boto3.client('translate')
def lambda_handler(event, context):
input_text = 'お腹が空いた'
response = translate.translate_text(
Text=input_text,
SourceLanguageCode='ja',
TargetLanguageCode='en'
)
output_text = response.get('TranslatedText')
return {
'statusCode': 200,
'body': json.dumps({
'output_text': output_text
})
}
【補足】
上記のコードを記載する際に以下のマニュアルを参照
グーグル検索より「aws python sdk」を検索し、一番最初に表示される以下URLのマニュアルから
APIリファレンスをクリックするとBoto3の各関数が詳細が表示される。「Tracelate」を検索してコードを記載するうえでのSyntaxの記載を参照する。
https://aws.amazon.com/jp/sdk-for-python/
②この状態だとまだ実行できないので権限の割り当てを実施します。
画面上のアクセス権限⇒ロール名をクリックします。
③以下の画面が表示されるので「ポリシーをアタッチします」をクリックします。
④次の画面でポリシーのフィルターに「translate」と入力し「TranslateFullAccess」にチェックを入れ、ポリシーのアタッチをクリックします
⑤追加したポリシーがアタッチされ下の表に表示されていることを確認します。
⑥Pythonのソースを編集していた画面に戻り、テストをクリックするとinput_textで指定した日本語が英語に訳されていることを確認します。
ここまでで、AWS LambdaとAWS Translateの連携まで(図の以下点線部分)構築したことになります。
(3)Amazon API GatewayからAWS Lambdaを連携できるようにします
まずAPI Gatewayを作成する画面に移動するため、画面左上のAWSのログをクリックし、マネジメントコンソールのサービス選択画面でAPI Gatewayを入力しリターンキーを押す。
①API Gatewayを構築します。API Gateway作成画面でREST API プライベートを選択します。
②以下の画面にて「REST」、「新しいAPI」、API名とし「translate-api」を入力し、APIの作成をクリックしてAPIを作成します。
③新規で作成したのでリソースもメソッドも何もない以下の画面が表示されていることを確認する。
④アクション⇒リソース作成よりリソース名を「translate」としてリソースの作成をクリックします。
⑤次にアクション⇒メソッド作成より「GET」を選択しチェックボックスを押して、Getメソッドを作成します。
⑥統合タイプはLambda関数と連携するAPI Gatewayなので「Lambda関数」を選択します
Lambdaプロキシ統合の使用にチェックをいれます。特にこのAPI Gatewayでは何か処理するわけではなく、プロキシサーバー的にデータを左から右にパススルーだけなのでプロキシ統合にチェックを入れます。
Lambda関数として作成した「translate-function」を入力します。
Lambda関数に権限追加するか聞かれるのでOKを押します。
以下の画面が表示されることを確認します。
⑦上記の画面のメソッドリクエストを選択し、「クエリ文字列の追加」より名前「input_text」、右端のチェックボックスにチェックし登録し、必須にチェックを入れる。メソッドの詳細設定ができたら画面上のメソッドの実行を押して、前の画面に戻ります。
⑧次に「translate-funcation」をクリックすると先ほど作成したLambda関数「translate-funcation」を編集する別ウィンドウに飛びます。
⑨画面右上から「テストトイベントの設定」をクリックします。
⑩新しいテストイベントの作成より、イベントテンプレートは「Amazon API Gateway AWS Proxy」を選択し
8行目を「"input_text": "私は疲れました"」と変更します。
画面右下の作成をクリックします。
⑪translate-funcation編集画面に戻りPythoのコードを以下のように編集します。
以下コードをそのままコピーして頂ければと思まいます
赤字箇所を修正した箇所になります。
import json
import boto3
translate = boto3.client('translate')
def lambda_handler(event, context):
input_text = event['queryStringParameters']['input_text']
response = translate.translate_text(
Text=input_text,
SourceLanguageCode='ja',
TargetLanguageCode='en'
)
output_text = response.get('TranslatedText')
return {
'statusCode': 200,
'body': json.dumps({
'output_text': output_text
}),
'isBase64Encoded': False,
'headers': {}
}
修正したら右上の保存ボタンより編集の保存をします。
コード修正の補足としてグーグル検索で「API gateway 統合レスポンス」を検索し、一番最初の以下URLの情報を参考にコード修正します。
⑫画面右上のテストを実行し、テストイベントで指定した日本語「私は疲れました」が英語に訳されている事確認する。
⑬次はAPI Gatewayから作成したLambda関数(translate-funcation)が呼び出せるか確認するため、API Gatewayの画面に戻り、アクション⇒APIのデプロイを選択します。
⑭ステージ名にdevを指定してデプロイします。
⑮デプロイしたあと、Getメソッドをクリックし、URLをクリックします。
⑯引数を渡していないのでInternal server errorとなります、
⑰URLへ引数を渡して翻訳されることを確認します。
先ほどのURLの後ろに「?input_text=こんにちは」を追加します。
こんにちはが訳されて表示されていることを確認します。
ここまでで、クライアントからAPI Gateway⇒Lambda⇒Translateの連携ができたことになります。
次はこの翻訳データをDynamoDBに格納するところまでの連携になります。
(4)Amazon DynamoDBとの連携
画面右上のAWSのロゴをクリックし、マネジメントコンソールより「Amazon DynamoDB」と入力しリターンキーを押します。
①次の画面が出てきますのでテーブル作成をクリックします。
②テーブル名を「translate-history」、プライマリキーを「timestamp」と指定して、デフォルト設定の使用をチェックボックスを外し、画面下の方にいきます。
キャパシティーユニットがデフォルト5になっているので、ハンズオンなので1に変更します。
AutoScallingのチェックボックスを外します。
画面右下の作成をクリックしDynamoDBのテーブルを作成します。
③テーブル作成ができたら、手動で項目の追加をします。
以下のようにtimestamp、input_text 、output_textの項目を手動で入力し保存をクリックします。手動入力とわかりやすいように★マークを付けておきます。
カラムが追加されデータが入力された事を確認します。
次はクライアントからAPI Gatewayを経由してDynamoDBにデータを格納できるのようにしていきます。
画面右上のAWSロゴをクリックしマネジメントコンソールのサービスを検索するより「Lambda」を入力してリターンキーを押し、作成したLambda関数を修正する画面に移動します。
④クライアントから渡ってきたデータをDynamoDBに格納するために、Pythonのソースを以下のように編集し、画面右上の保存ボタンをクリックします。
今回の修正箇所は以下の赤字部分になります。
import json
import boto3
import datetime
translate = boto3.client('translate')
dynamodb_translate_history_tbl = boto3.resource('dynamodb').Table('translate-history')
def lambda_handler(event, context):
input_text = event['queryStringParameters']['input_text']
response = translate.translate_text(
Text=input_text,
SourceLanguageCode='ja',
TargetLanguageCode='en'
)
output_text = response.get('TranslatedText')
dynamodb_translate_history_tbl.put_item(
Item = {
'timestamp': datetime.datetime.now().strftime("%Y%m%d%H%M%S"),
'input_text': input_text,
'output_text': output_text
}
)
return {
'statusCode': 200,
'body': json.dumps({
'output_text': output_text
}),
'isBase64Encoded': False,
'headers': {}
}
⑤この状態だとDynamoDB更新権限がないので、作成したLambda関数(translate-function)からDynamoDBへアクセスできる権限を追加します。
⑥アクセス権限⇒ロール名をクリックします。
⑦ポリシーのアタッチしますをクリックしてポリシーを追加します。
⑧ポリシーのフィルターにDynamoDBと入力し、「AmazonDynamoDBFullAccess」のポリシーをアタッチします。今回はハンズオンなのでFullAccess権限を与えてますが、通常は必要な権限のみに絞ります。
⑨以下の画面のように「AmazonDynamoDBFullAccess」のポリシーが追加されている事を確認します
⑩ここでこのLambda関数からDynamoDBにアクセスできるかテストをします。
画面右上からテストイベントの設定をクリックします
⑪input_textの引数が「私は疲れました」などの、先ほどDBに入れて内容と違う内容が入っている事を確認する。
⑫前の画面に戻りテストをクリックしてテスト実行します。テスト結果として英語に訳されている事を確認します。
⑬DynamoDBのテーブルの中を確認して、テスト実行したデータが格納されている事を確認します。
⑭ここまで来たら、最後はクライアントからAPI Gatewayを経由して翻訳できること、そしてDynamoDBのテーブルにデータが格納されることを確認します。
API Gateway画面に移動し、「ステージ」⇒「Get」⇒URLをクリックします。
⑮引数を渡していないのでInternal server errorとなりますが、URLの後ろに「?input_text=私はお腹が減りました」を入力しリターンキーを押すと、英語に訳された結果が表示されることを確認します。
⑯次にDynamoDBテーブルの中身を確認し、訳されたデータがDynamoDBに格納されている事を確認します。
まとめ
お疲れ様でした。これで、クライアントからAPI Gateway⇒Lambda⇒Translate⇒DynamoDBの連携が完了となります。今回はハンズオンなので細かいところは省いて、まずは動くものを作成した感じです。もっといろいろ勉強する事はありますが、とりあえずお疲れさまでした。
最後に
今回作成したAWSサービスは削除します。無料利用枠で実施しておりますが、ほったらかしておくと課金される可能性がありますので忘れずに削除しましょう。
削除手順は今回使用した以下サービスの画面にて作成したオブジェクトを削除します。
API Gateway「translate-api」
Lambda「translate-function」
DynamoDB「translate-history」