IAM Identity Center(AWS SSO)に移行して1年たったので使い方などまとめる
TECH
2023.05.01
更新日:2022.12.23
公開日:2021.04.23
業務で使うサーバーが、いつの間にかAWSになってから、毎日AWSを業務で利用しています。 AWSには、沢山のサービスがありますが、私のお気に入りはAWS Lambdaです。
理由は、とりあえずシンプルに作れるから!
プロジェクトが始まると、切り出せそうな処理はどんどんLambda Functionとして作ってはデプロイを繰り返します。
結果、案件も終わりが見えた頃には、「Lambda Functionいっぱい問題」発生。 このパターンが日常的にあり、修正や管理のコストが大きくなることが多いです。
Lambda Function自体は便利ですが、以下の悩みがあります。
お手製ツールを用意したりなどで、なんとかごまかし運用をしていた所、弊社のアーキテクトから「Serverless Framework使えば?」とのアドバイスを受け「何やそれ?」ってなったのが、導入のきっかけになります。 (キャッチアップせーよ、頭使って仕事しろよって話ですね。。。)
Serverless Frameworkとは、お手軽に「サーバレスアーキテクチャ」を構築することができるフレームワークです。もちろん、AWSのLambda Functionにも対応しています。
簡潔にいうと、「常時起動しているサーバーを使わずにアーキテクチャ(仕組み)が実現できている状態」というニュアンスが近いです。 メリットとしては、常時起動サーバーがなくなり、以下のサーバーあるあるの問題がなくなることです。
重複しますが、そんなサーバー関連の問題を減らすことができる「サーバレスアーキテクチャ」をお手軽に構築できるのが、「Serverless Framework」となります。
Serverless Frameworkによるメリットは、以下です。
私がLambda Functionで導入した時に嬉しかった点は以下です。
メリットだけではなく、デメリットもあるにはあります。
成果物の要件を以下と定義します。
以下のコードを作成して、AWSにデプロイします。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 |
const aws = require('aws-sdk'); exports.handler = function (event, context) { (async () => { try { // Hello Worldを出力 console.log('Hello World!'); // s3にファイル出力 const s3 = new aws.S3({ endpoint: process.env.S3_BUCKET_ENDPOINT, s3ForcePathStyle: true, signatureVersion: 'v4', region: process.env.S3_BUCKET_REGION, }); // とりあえずの同期実行 await (async () => new Promise((resolve, reject) => { s3.putObject({ Bucket: process.env.S3_BUCKET_NAME, Key: 'hello.json', Body: JSON.stringify({ 'date': new Date().toISOString(), }), }, (err) => { if (!err) { resolve(); } else { reject(err); } }); }).catch((e) => { throw new Error(e); }))(); context.succeed('succeed'); } catch (e) { console.error(e); context.fail('fail'); } })(); }; |
S3の操作を行うためのロール設定
テストなので、とりあえずS3のフルアクセス権限を設定しています。
※プロダクションコードの場合は、適切な権限設定を行ってください。
以下のように環境変数も設定。
無事「Hello World」がコンソール上に出力されました。
無事、S3に「hello.json」がアップロードされました。
以下のコードを作成して、AWSにデプロイします。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
const aws = require('aws-sdk'); exports.handler = function (event, context) { (async () => { try { // s3のファイル読み込み const s3 = new aws.S3({ endpoint: process.env.S3_BUCKET_ENDPOINT, s3ForcePathStyle: true, signatureVersion: 'v4', region: process.env.S3_BUCKET_REGION, }); const data = await (async () => new Promise((resolve, reject) => { s3.getObject({ Bucket: process.env.S3_BUCKET_NAME, Key: 'hello.json', }, (err, res) => { if (!err) { resolve(JSON.parse(res.Body.toString())); } else { reject(err); } }); }).catch((e) => { throw new Error(e); }))(); // 読み込んだファイルの内容を出力 console.log(data); context.succeed('succeed'); } catch (e) { console.error(e); context.fail('fail'); } })(); }; |
無事、S3からファイルを読み込み、中身を出力できました。
envファイルを作成し、Lambda Functionに設定する環境変数情報を設定します。 envファイルは、以下のようにYAML形式でシンプルに記述できます。(リージョンやバケットは適宜書き換えてください)
1 2 3 |
S3_BUCKET_ENDPOINT: s3.ap-northeast-1.amazonaws.com S3_BUCKET_REGION: ap-northeast-1 S3_BUCKET_NAME: test-xxxxxxxxxx |
Serverless Framework本体用にYAML形式の設定ファイルを作成します。 今回は、以下のような設定ファイルを用意しました。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 |
# ServerlessFrameworkでデプロイしたLambdaFunctionの関数名に自動で追加される接頭辞 service: sfw-test provider: name: aws stage: ${opt:stage, 'dev'} region: ap-northeast-1 lambdaHashingVersion: 20201221 # LambdaFunctionで必要なポリシーを設定 iam: role: statements: - Effect: "Allow" Action: - s3:* Resource: "*" timeout: 60 memorySize: 128 custom: # 環境別にenvファイルを別々で用意する場合は、以下のリストに追加 environment: # ローカルでテスト実行するための環境変数ファイル local: ${file(./env/local.yml)} # devlop環境でテスト実行するための環境変数ファイル dev: ${file(./env/dev.yml)} # デプロイするLambdaFunctionの設定リスト functions: # helloworldを出力して、S3にファイルをアップロードするスクリプト helloworld: # 使用するランタイムのバージョン設定 runtime: nodejs14.x # 実行するハンドラーのパス handler: src/helloworld/index.handler # タイムアウト設定 timeout: 15 # 使用メモリー設定 memorySize: 128 # 環境変数の設定(* process.envで取得できる environment: S3_BUCKET_ENDPOINT: ${self:custom.environment.${self:provider.stage}.S3_BUCKET_ENDPOINT} S3_BUCKET_REGION: ${self:custom.environment.${self:provider.stage}.S3_BUCKET_REGION} S3_BUCKET_NAME: ${self:custom.environment.${self:provider.stage}.S3_BUCKET_NAME} # S3からファイルを読み込んで出力するスクリプト reader: # 使用するランタイムのバージョン設定 runtime: nodejs14.x # 実行するハンドラーのパス handler: src/reader/index.handler # タイムアウト設定 timeout: 15 # 使用メモリー設定 memorySize: 128 # 環境変数の設定(* process.envで取得できる environment: S3_BUCKET_ENDPOINT: ${self:custom.environment.${self:provider.stage}.S3_BUCKET_ENDPOINT} S3_BUCKET_REGION: ${self:custom.environment.${self:provider.stage}.S3_BUCKET_REGION} S3_BUCKET_NAME: ${self:custom.environment.${self:provider.stage}.S3_BUCKET_NAME} # イベントトリガー設定 events: # S3の指定バケットにファイルがアップされたら自動実行するように設定 - s3: bucket: ${self:custom.environment.${self:provider.stage}.S3_BUCKET_NAME} event: s3:ObjectCreated:* # # 手動で作成したバケットを使用する場合は設定が必要 # existing: true |
Serverless Frameworkでは、Lambda Functionで使用する周辺リソース(S3,SQSなど)も同時にデプロイ管理することができます。手動で作成した既存のリソースも使用しても問題ありません。
Serverless Frameworkでデプロイを行います。
serverless deploy --aws-profile ${profile指定が必要な時のみ} --verbose --stage dev
関係するLambda Functionが一括でデプロイされました。
環境変数が設定されていることを確認
今回は一括でデプロイしましたが、以下のようなコマンドで個別にデプロイすることもできます。
serverless deploy --aws-profile ${profile指定が必要な時のみ} --verbose --stage dev -f helloworld
ちゃんと動くかテストします。
無事、Serverless FrameworkでアップロードしたLambda Function 1が動作しました。
Serverless Frameworkの設定に問題がなければ、Lambda Function 1を実行した時に保存されるS3ファイルをトリガーにして、Lambda Function 2が動いているはずなので、Cloud Watchのログを確認します。
無事、Serverless FrameworkでアップロードしたLambda Function 2が動作しました。
念のため、手動での実行テストも行います。
無事、Serverless Frameworkでアップロードした、Lambda Function 2が動作しました。
実際に、Serverless Frameworkを使って便利だなぁと思った点は以下となります。
新しいことを取り入れるのは、いつも億劫になりがちですが、実際にやってみると「何でもっと早くこれにせんかったんや」と思うことが多いです。Serverless Frameworkについても、その一つです。
まだ使ってみたことがない方は、お試しいただければと思います。