AWSの勉強として簡易的な構成で構築を実施
今回はマネジメントコンソール経由で構成
構成
図は draw.io を利用し作成
draw.io
https://www.draw.io/
S3の静的ウェブサイトホスティングを利用し、バックエンドではAPI Gateway経由でlambdaにて処理を実施する簡易的な構成
GithubのリポジトリへpushすればCodePipelineが動作
CodeBuildが動いて処理後にアーティファクトをS3に格納され、
アーティファクトを利用してホスティングしているHTMLファイルとlambdaの更新を自動でやってくれる
ソースコード
・buildspec.yml → CodeBuild用
・index.html → S3の静的ウェブサイトホスティング用
・lambda_function.py → lambda用
※ 公開用なのでhtmlファイルのAPIエンドポイントはダミー
lambda_function.py について
なんでもよかったので以前pythonの練習用に作成したものを流用
numpyが標準ライブラリではないので、モジュールのインポート用にnumpyを含むレイヤーを作成する必要あり
参考:
レイヤーによる Lambda 依存関係の管理
https://docs.aws.amazon.com/ja_jp/lambda/latest/dg/chapter-layers.html
index.html について
試験的にChatGPTを活用して作成
ただし、作成したものをそのままローカルで動かしてみたら動かず
最終的に以下3点問題があった
(1) CORS(Cross-Origin Resource Sharing)の設定をしていなかった
API Gateway側でCORSの設定をしていなかったため実施
参考:
CORS とは-クロスオリジンリソース共有の説明
https://aws.amazon.com/jp/what-is/cross-origin-resource-sharing/
なお、最初はlambda関数側にも Access-Control-Allow-Origin": "" をヘッダーに追加していたが
今回はHTTP APIのlambda統合でAPI Gateway側でCORSのoriginをで有効化すれば、
"Access-Control-Allow-Origin": "*"が自動的にレスポンスに追加されていた
そのため、lambda関数側でのヘッダー付与は不要と確認できたので最終的に削除
Access-Control-Allow-Origin": "*" が付与されていることの確認は
python -m http.server 8080 でローカルをHTTPサーバにして
chromeの開発者ツール(F12) → Network から確認
※python -m http.server 8080 は実行した場所がHTTPのルートになるので
ちゃんとindex.htmlがある階層まで移動してから実行する
(2) ローカルでHTMLファイルを開いてテストしていた
ローカル(file://~)だとoriginは null になるらしい
"*"はnullを含まないので、Access-Control-Allow-Originが自動的に付与されても以下エラーが出る
Access to fetch at '' from origin 'null' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
上記の通りローカルをHTTPサーバにして動作検証することで解消
(3) lambdaから返されるjsonのパース処理誤り
今回のlambda関数は以下のようなオブジェクト形式ではなく
{
"statusCode": 200,
"headers": {
"Access-Control-Allow-Origin": "*"
},
"body": "\<body>"
}
以下のような配列で返してきていた
["名前=ラネコ", "element=['火']", "STR=[40]", "INT=[41]", "POW=[45]", "DEX=[55]", "HP=[54]", "MP=[62]", "APP=[61]", "family background=[69]", "gender=男", "height=[180]"]
以下のように修正して対応
修正前:
const data = await response.json();
document.getElementById("result").textContent = data.body;
修正後:
const data = await response.json();
document.getElementById("result").textContent = data.join("\n");
buildspec.yml について
CodeBuildで使われる実行コマンドなどが書かれたもの
今回は特に各ビルドで実施する処理はないのでプロセスの実行時に echo でメッセージを出力させたのみ
artifactsがS3に出力される成果物の指定場所
今回はindex.htmlとlambda_function.pyをそのまま出力
構築
・lambda関数の作成
・API Gatewayの作成
・S3で静的ウェブサイトホスティングの設定
・CodeBuild,CodePipelineの設定
lambda関数の作成
GUIからランタイムにPythonを指定して普通に作成
ただし、上述した通り、numpyがpythonの標準ライブラリではないのでレイヤー構築が必要
レイヤー構築は以下別記事で分けてまとめています
API Gatewayの作成
lambda統合で利用するlambda関数を指定し、ルートやステージなどはデフォルトで作成
S3で静的ウェブサイトホスティングの設定
バケットを作成してから以下で有効化して
以下でパブリックアクセスを許可
CodeBuild,CodePipelineの設定
CodeBuild
まずCodeBuildでプロジェクトを作成する
単に更新するだけならビルドステージの指定は省略できそうだが今回は勉強がてら指定
以下の通りソースをGithubに指定(認証はSecrets Manager経由で実施済
環境はLambdaを使用
アーティファクトの格納先となるバケットを指定
CloudWatchの部分などは一旦デフォルトのままプロジェクト作成
※CodeBuild単体で使うならpushでのウェブフック設定もここでしておく
CodePipeline
CodePipelineはカスタムで作成してソースをGithubに指定
今回はmainブランチにpushした際にCodePipelineが動作するようウェブフックを設定
ビルドステージは先ほど作成したCodeBuildのプロジェクトを指定
デプロイステージで一旦lambda関数を指定
GUIだと複数のデプロイステージを選べなかったのでS3の更新については後で追加する
パイプラインを作成後、パイプライン名を押下→編集から進みステージを追加
静的ウェブサイトホスティングの設定を実施したバケットを指定
[デプロイする前にファイルを抽出する] のチェックは必須
チェックしないとzipファイルのままCodePipelineにデータが渡されてしまう
チュートリアル: Amazon S3 をデプロイプロバイダとして使用するパイプラインを作成する
https://docs.aws.amazon.com/ja_jp/codepipeline/latest/userguide/tutorials-s3deploy.html
=======
[デプロイ前にファイルを抽出] を選択しないと、デプロイに失敗します。これは、パイプラインの AWS CodeCommit アクションがソースアーティファクトを圧縮し、ファイルが ZIP ファイルであるためです。
=======
これで一通りの設定は終了
ここからローカルでコードを更新してPush→Pull requestしてリポジトリを更新すると
CodePipelineが動作して自動で更新してくれる