20220114のAWSに関する記事は13件です。

Laravel Docker AWS EC2デプロイ⑥

今回は、AWSのサービスを使用してSSLを無料発行し、前回独自で用意したドメインをSSL化していきます! 前回 SSL証明書取得 下記の記事を参考に進めていきますが、現在のAWS画面とは少し異なるので、その部分に関してはこちらに画像を記載しますので参考にしてください。 ・Certificate Managerの開き方。 1.Certificate Managerで検索してサービスを選択。 2.証明書リクエストボタンから申請可能。 3.パブリック証明書リクエストを選択して次へ。 4.独自で用意したドメイン名を入力し、リクエスト。 5.証明書発行確認 リクエストをクリックすると、最初の画面に戻り、証明書が作成されています。 詳細に関しては、証明書IDを選択することで確認できます! 6.Route 53でレコード作成 証明書IDをクリックすると、詳細画面が開きます。 画面中央部のRoute 53でレコード作成をクリック。 7.レコード作成 内容を確認してレコード作成をクリック。 メッセージが表示されれば無事作成完了です。 一旦別画面に移動し、もう一度戻ってくると、下記のようにステータス欄が検証中→発行済みに変わっていることがわかります! これで証明書を取得できたことになりました! SSL証明書の設定 では、取得した証明書の設定をしていきます。 1.ロードバランサーの作成 EC2画面左側のメニューバーから、ロードバランサーを開き、作成をクリック。 2.タイプを選択 今回は、ALBを使用します! 3. 設定項目を入力 先ず、画面上部ではロードバランサー名を入力し、スキームやIPアドレスタイプはデフォルトのままでOKです。 下にスクロールします。 マッピングは、EC2インスタンスを設置したVPCと組み込みたいゾーンを二つ以上選択しましょう。 セキュリティグループはALB用に新規で作成します。 その際、インバウンドとアウトバウンドルールも設定します。 リスナーとルーティングはHTTPSを許可するように入力します。 セキュアリスナーでは、先ほど作成したSSL証明書を選択します。 リスナーのターゲットグループも新規で作成します。 ヘルスチェックパスにはドメインにアクセスした際のリダイレクト先を指定します。 こちらの仕組みに関しては下記記事がわかりやすく説明されているので参考にしてください。 最後に、何のロードバランサーか区別がつきやすくするようタグにNameを設定し、概要を確認して問題なければ作成ボタンを押して作成します。 無事作成できればロードバランサーの画面に表示されます! レコード設定 最後に、初めにRoute 53で作成したドメインのレコードを編集します。 EC2に関連付けさせたELPの箇所をALBのDNSに変更します。 エイリアスにチェック→ALBを選択→リージョン選択→DNS 動作確認 では、https通信でドメインからアクセス確認してみましょう! https://????.com 無事SSL化されたドメインでログイン画面が表示されました! 今回はここまでにします! 次は、Auto Scalingの設定を進めていきます!
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

AWS SAMで管理するAWS Lambda関数を、単一のAWSアカウント内の複数環境にデプロイする

Whats'? AWS SAMで管理するAWS Lambda関数を、単一AWSアカウント内の複数回(別環境として)デプロイするのにはどうすればよいのかな?ということで、試してみました。 AWS CloudFormationと複数環境 AWS SAMは、AWS CloudFormationの拡張です。 AWS SAM は AWS CloudFormation の拡張であるため、AWS CloudFormation の信頼性の高いデプロイ機能を利用できます。 このため、AWS SAMで管理している内容を複数の環境に適用するには、AWS CloudFormationの考え方に従うのが妥当でしょう。 AWS CloudFormationのドキュメントによると、テンプレートを複数環境向けに利用するには、パラメーターやマッピング、条件セクションで環境間の差異を吸収していくようです。 たとえば、開発、テスト、本番の環境を作成して、本番環境に実装する前に変更をテストすることができます。テンプレートを再利用可能にするには、パラメーター、マッピング、および条件セクションを使用してスタックの作成時にカスタマイズできるようにします。 AWS CloudFormation ベストプラクティス / テンプレートを再利用して複数の環境にスタックを複製する このあたりですね。 また、AWS SAMではパラメーターの設定は、--parameter-overrides(設定ファイルの場合はparameter_overrides)で行うようです。 これらを利用して、AWS SAMで管理するAWS Lambda関数を、複数環境にデプロイしてみます。 やってみること 今回は、以下の内容をお題にしてみます。 AWS SAMアプリケーションのデプロイ先を開発環境(development)と本番環境(production)の2つに対して行う アプリケーション自体は、AWS SAMのQuick StartからHello World Example(Node.js)をベースにして作成 AWS Lambda関数の名前は固定し、どの環境向けの関数なのかを名前でわかるようにする(※) ひとつのAWS SAMテンプレートで、複数環境にデプロイできるようにカスタマイズ 各環境で異なる構成で動作していることがわかりやすいように、アプリケーション内で環境変数を参照するようにする 参照する環境変数は、AWS SAMテンプレート内で環境別の値を設定する ※ … AWS Lambda関数名を固定しない(FunctionNameを指定しない)場合は一意の名前が生成されるので、このお題の意味があまりないかもですが 環境 今回の環境は、こちらです。 $ sam --version SAM CLI, version 1.37.0 $ aws --version aws-cli/2.4.11 Python/3.8.8 Linux/5.4.0-94-generic exe/x86_64.ubuntu.20 prompt/off $ node --version v14.18.3 $ npm --version 6.14.15 なお、AWSのクレデンシャルは今回は環境変数に指定しているものとします。 $ export AWS_ACCESS_KEY_ID=..... $ export AWS_SECRET_ACCESS_KEY=..... $ export AWS_DEFAULT_REGION=ap-northeast-1 AWS SAMアプリケーションを作成する まずは、AWS SAMアプリケーションを作成します。sam initでアプリケーション名はsam-hello-world、テンプレートはhello-world、ランタイムはNode.js 14.xとします。 $ sam init \ --name sam-hello-world \ --runtime nodejs14.x \ --app-template hello-world \ --package-type Zip ディレクトリ内へ移動。 $ cd sam-hello-world ディレクトリ内の構成は、こんな感じです。 $ tree . ├── README.md ├── events │   └── event.json ├── hello-world │   ├── app.js │   ├── package.json │   └── tests │   └── unit │   └── test-handler.js └── template.yaml 4 directories, 6 files ポイントとなるファイルだけ表示しておきましょう。 AWS Lambda関数。 hello-world/app.js // const axios = require('axios') // const url = 'http://checkip.amazonaws.com/'; let response; /** * * Event doc: https://docs.aws.amazon.com/apigateway/latest/developerguide/set-up-lambda-proxy-integrations.html#api-gateway-simple-proxy-for-lambda-input-format * @param {Object} event - API Gateway Lambda Proxy Input Format * * Context doc: https://docs.aws.amazon.com/lambda/latest/dg/nodejs-prog-model-context.html * @param {Object} context * * Return doc: https://docs.aws.amazon.com/apigateway/latest/developerguide/set-up-lambda-proxy-integrations.html * @returns {Object} object - API Gateway Lambda Proxy Output Format * */ exports.lambdaHandler = async (event, context) => { try { // const ret = await axios(url); response = { 'statusCode': 200, 'body': JSON.stringify({ message: 'hello world', // location: ret.data.trim() }) } } catch (err) { console.log(err); return err; } return response }; AWS SAMテンプレート。 template.yaml AWSTemplateFormatVersion: '2010-09-09' Transform: AWS::Serverless-2016-10-31 Description: > sam-hello-world Sample SAM Template for sam-hello-world # More info about Globals: https://github.com/awslabs/serverless-application-model/blob/master/docs/globals.rst Globals: Function: Timeout: 3 Resources: HelloWorldFunction: Type: AWS::Serverless::Function # More info about Function Resource: https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#awsserverlessfunction Properties: CodeUri: hello-world/ Handler: app.lambdaHandler Runtime: nodejs14.x Architectures: - x86_64 Events: HelloWorld: Type: Api # More info about API Event Source: https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#api Properties: Path: /hello Method: get Outputs: # ServerlessRestApi is an implicit API created out of Events key under Serverless::Function # Find out more about other implicit resources you can reference within SAM # https://github.com/awslabs/serverless-application-model/blob/master/docs/internals/generated_resources.rst#api HelloWorldApi: Description: "API Gateway endpoint URL for Prod stage for Hello World function" Value: !Sub "https://${ServerlessRestApi}.execute-api.${AWS::Region}.amazonaws.com/Prod/hello/" HelloWorldFunction: Description: "Hello World Lambda Function ARN" Value: !GetAtt HelloWorldFunction.Arn HelloWorldFunctionIamRole: Description: "Implicit IAM Role created for Hello World function" Value: !GetAtt HelloWorldFunctionRole.Arn ここから、少し変更してみます。 AWS SAMテンプレートには、FunctionNameと環境変数(Environment)を追加します。 Resources: HelloWorldFunction: Type: AWS::Serverless::Function # More info about Function Resource: https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#awsserverlessfunction Properties: CodeUri: hello-world/ Handler: app.lambdaHandler Runtime: nodejs14.x FunctionName: HelloWorldFunction Architectures: - x86_64 Environment: Variables: APPLICATION_MESSAGE: World Events: HelloWorld: Type: Api # More info about API Event Source: https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#api Properties: Path: /hello Method: get EnvironmentにAPPLICATION_MESSAGEという環境変数を追加しました。 AWS Lambda関数は、追加されたAPPLICATION_MESSAGE環境変数を参照するように修正します。 exports.lambdaHandler = async (event, context) => { try { // const ret = await axios(url); response = { 'statusCode': 200, 'body': JSON.stringify({ message: `Hello ${process.env['APPLICATION_MESSAGE']}`, // location: ret.data.trim() }) } } catch (err) { console.log(err); return err; } return response }; では、ビルドして $ sam build デプロイしてみます。 この時、最初から環境別を意識した形での実行にします。まずは開発環境(development)向けにしましょう。 $ sam deploy --guided 入力内容はこんな感じにしました。 Setting default arguments for 'sam deploy' ========================================= Stack Name [sam-app]: development-sam-hello-world AWS Region [ap-northeast-1]: #Shows you resources changes to be deployed and require a 'Y' to initiate deploy Confirm changes before deploy [y/N]: y #SAM needs permission to be able to create roles to connect to the resources in your template Allow SAM CLI IAM role creation [Y/n]: y #Preserves the state of previously provisioned resources when an operation fails Disable rollback [y/N]: n HelloWorldFunction may not have authorization defined, Is this okay? [y/N]: y Save arguments to configuration file [Y/n]: y SAM configuration file [samconfig.toml]: SAM configuration environment [default]: development ここから生成される値。 Deploying with following values =============================== Stack name : development-sam-hello-world Region : ap-northeast-1 Confirm changeset : True Disable rollback : False Deployment s3 bucket : aws-sam-cli-managed-default-samclisourcebucket-1f8pzvbjpaczp Capabilities : ["CAPABILITY_IAM"] Parameter overrides : {} Signing Profiles : {} 変更内容を確認して、進めます。 CloudFormation stack changeset --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Operation LogicalResourceId ResourceType Replacement --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + Add HelloWorldFunctionHelloWorldPermissionProd AWS::Lambda::Permission N/A + Add HelloWorldFunctionRole AWS::IAM::Role N/A + Add HelloWorldFunction AWS::Lambda::Function N/A + Add ServerlessRestApiDeployment47fc2d5f9d AWS::ApiGateway::Deployment N/A + Add ServerlessRestApiProdStage AWS::ApiGateway::Stage N/A + Add ServerlessRestApi AWS::ApiGateway::RestApi N/A --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Changeset created successfully. arn:aws:cloudformation:ap-northeast-1:[AWSアカウントID]:changeSet/samcli-deploy1642156897/137a0b76-fb85-433c-a389-7c43a9b40456 デプロイが終わりました。 2022-01-14 19:43:01 - Waiting for stack create/update to complete CloudFormation events from stack operations --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- ResourceStatus ResourceType LogicalResourceId ResourceStatusReason --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- CREATE_IN_PROGRESS AWS::IAM::Role HelloWorldFunctionRole - CREATE_IN_PROGRESS AWS::IAM::Role HelloWorldFunctionRole Resource creation Initiated CREATE_COMPLETE AWS::IAM::Role HelloWorldFunctionRole - CREATE_IN_PROGRESS AWS::Lambda::Function HelloWorldFunction - CREATE_IN_PROGRESS AWS::Lambda::Function HelloWorldFunction Resource creation Initiated CREATE_COMPLETE AWS::Lambda::Function HelloWorldFunction - CREATE_IN_PROGRESS AWS::ApiGateway::RestApi ServerlessRestApi - CREATE_IN_PROGRESS AWS::ApiGateway::RestApi ServerlessRestApi Resource creation Initiated CREATE_COMPLETE AWS::ApiGateway::RestApi ServerlessRestApi - CREATE_IN_PROGRESS AWS::Lambda::Permission HelloWorldFunctionHelloWorldPermissionProd - CREATE_IN_PROGRESS AWS::ApiGateway::Deployment ServerlessRestApiDeployment47fc2d5f9d - CREATE_IN_PROGRESS AWS::Lambda::Permission HelloWorldFunctionHelloWorldPermissionProd Resource creation Initiated CREATE_IN_PROGRESS AWS::ApiGateway::Deployment ServerlessRestApiDeployment47fc2d5f9d Resource creation Initiated CREATE_COMPLETE AWS::ApiGateway::Deployment ServerlessRestApiDeployment47fc2d5f9d - CREATE_IN_PROGRESS AWS::ApiGateway::Stage ServerlessRestApiProdStage - CREATE_IN_PROGRESS AWS::ApiGateway::Stage ServerlessRestApiProdStage Resource creation Initiated CREATE_COMPLETE AWS::ApiGateway::Stage ServerlessRestApiProdStage - CREATE_COMPLETE AWS::Lambda::Permission HelloWorldFunctionHelloWorldPermissionProd - CREATE_COMPLETE AWS::CloudFormation::Stack development-sam-hello-world - --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- アクセスして確認してみます。 $ curl https://[REST API ID].execute-api.ap-northeast-1.amazonaws.com/Prod/hello/ {"message":"Hello World"} OKですね。 この時に作成されたsamconfig.tomlは、以下のようになりました。 samconfig.toml version = 0.1 [development] [development.deploy] [development.deploy.parameters] stack_name = "development-sam-hello-world" s3_bucket = "aws-sam-cli-managed-default-samclisourcebucket-1f8pzvbjpaczp" s3_prefix = "development-sam-hello-world" region = "ap-northeast-1" confirm_changeset = true capabilities = "CAPABILITY_IAM" image_repositories = [] samconfig.tomlが生成されたので、以降は--config-envを指定することでこの環境用の設定を利用することができます。 $ sam deploy --config-env development この環境名で管理される項目一式のことを、テーブルと呼ぶみたいです。 では、このまま本番環境(production)用のものも進めてみます。 $ sam deploy --guided 先ほどはdevelopmentだった部分を、productionにして実行。 Setting default arguments for 'sam deploy' ========================================= Stack Name [sam-app]: production-sam-hello-world AWS Region [ap-northeast-1]: #Shows you resources changes to be deployed and require a 'Y' to initiate deploy Confirm changes before deploy [y/N]: y #SAM needs permission to be able to create roles to connect to the resources in your template Allow SAM CLI IAM role creation [Y/n]: y #Preserves the state of previously provisioned resources when an operation fails Disable rollback [y/N]: n HelloWorldFunction may not have authorization defined, Is this okay? [y/N]: y Save arguments to configuration file [Y/n]: y SAM configuration file [samconfig.toml]: SAM configuration environment [default]: production 〜省略〜 Deploying with following values =============================== Stack name : production-sam-hello-world Region : ap-northeast-1 Confirm changeset : True Disable rollback : False Deployment s3 bucket : aws-sam-cli-managed-default-samclisourcebucket-1f8pzvbjpaczp Capabilities : ["CAPABILITY_IAM"] Parameter overrides : {} Signing Profiles : {} 変更内容はこちら。 CloudFormation stack changeset --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Operation LogicalResourceId ResourceType Replacement --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + Add HelloWorldFunctionHelloWorldPermissionProd AWS::Lambda::Permission N/A + Add HelloWorldFunctionRole AWS::IAM::Role N/A + Add HelloWorldFunction AWS::Lambda::Function N/A + Add ServerlessRestApiDeployment47fc2d5f9d AWS::ApiGateway::Deployment N/A + Add ServerlessRestApiProdStage AWS::ApiGateway::Stage N/A + Add ServerlessRestApi AWS::ApiGateway::RestApi N/A --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- そして、このまま進めるとデプロイに失敗します。 CloudFormation events from stack operations --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- ResourceStatus ResourceType LogicalResourceId ResourceStatusReason --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- CREATE_IN_PROGRESS AWS::IAM::Role HelloWorldFunctionRole - CREATE_IN_PROGRESS AWS::IAM::Role HelloWorldFunctionRole Resource creation Initiated CREATE_COMPLETE AWS::IAM::Role HelloWorldFunctionRole - CREATE_IN_PROGRESS AWS::Lambda::Function HelloWorldFunction - CREATE_FAILED AWS::Lambda::Function HelloWorldFunction HelloWorldFunction already exists in stack arn:aws:cloudformation:ap-northeast-1:[AWSアカウントID] :stack/development-sam-hello- world/4f593cc0-7529-11ec-b829-0e71e619494f ROLLBACK_IN_PROGRESS AWS::CloudFormation::Stack production-sam-hello-world The following resource(s) failed to create: [HelloWorldFunction]. Rollback requested by user. DELETE_COMPLETE AWS::Lambda::Function HelloWorldFunction - DELETE_IN_PROGRESS AWS::IAM::Role HelloWorldFunctionRole - ROLLBACK_COMPLETE AWS::CloudFormation::Stack production-sam-hello-world - DELETE_COMPLETE AWS::IAM::Role HelloWorldFunctionRole - --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Error: Failed to create/update the stack: production-sam-hello-world, Waiter StackCreateComplete failed: Waiter encountered a terminal failure state: For expression "Stacks[].StackStatus" we matched expected path: "ROLLBACK_COMPLETE" at least once これは、すでに同一AWSアカウント内に同じ名前のAWS Lambda関数が存在しているからですね。 今回はAWS Lambda関数名を指定しつつ、この事象を回避しようといお題になっています。 なお、この時点でsamconfig.tomlの内容はこのようになっています。 samconfig.toml version = 0.1 [development] [development.deploy] [development.deploy.parameters] stack_name = "development-sam-hello-world" s3_bucket = "aws-sam-cli-managed-default-samclisourcebucket-1f8pzvbjpaczp" s3_prefix = "development-sam-hello-world" region = "ap-northeast-1" confirm_changeset = true capabilities = "CAPABILITY_IAM" image_repositories = [] [production] [production.deploy] [production.deploy.parameters] stack_name = "production-sam-hello-world" s3_bucket = "aws-sam-cli-managed-default-samclisourcebucket-1f8pzvbjpaczp" s3_prefix = "production-sam-hello-world" region = "ap-northeast-1" confirm_changeset = true capabilities = "CAPABILITY_IAM" image_repositories = [] いったん、これらのスタックを削除しておきましょう。 ## 開発環境用のリソースを削除 $ sam delete --config-env development ## 本番環境用のリソースを削除 $ sam delete --config-env production 複数環境に対応させる では、AWS CloudFormationのベストプラクティスに習って、複数環境に対応できるようにAWS SAMテンプレートを修正していきます。 AWS CloudFormation ベストプラクティス / テンプレートを再利用して複数の環境にスタックを複製する まず、環境の切り替えにはパラメーターを使うことにします。Environmentというパラメーターを定義しました。 Parameters: Environment: Type: String AllowedValues: - development - production Environmentに指定した値をキーにして、マッピングを作成します。 Mappings: EnvironmentConfig: development: FunctionNamePrefix: Dev ApplicationMessage: "World[development]" production: FunctionNamePrefix: Prd ApplicationMessage: "World[production]" 今回は、AWS Lambda関数名に付与するPrefixとAWS Lambda関数に設定する環境変数の2つにしました。 これを、AWS SAMテンプレート内のAWS Lambda関数のリソース定義に設定します。 FunctionName: !Join - "" - - !FindInMap - EnvironmentConfig - !Ref Environment - FunctionNamePrefix - "HelloWorldFunction" Architectures: - x86_64 Environment: Variables: APPLICATION_MESSAGE: !FindInMap - EnvironmentConfig - !Ref Environment - ApplicationMessage FindInMap関数の使い方は、マッピングのドキュメントを見るとわかると思います。 Join関数は文字列連結ですね。 AWS SAMテンプレート全体としては、このようになりました。 template.yaml AWSTemplateFormatVersion: '2010-09-09' Transform: AWS::Serverless-2016-10-31 Description: > sam-hello-world Sample SAM Template for sam-hello-world # More info about Globals: https://github.com/awslabs/serverless-application-model/blob/master/docs/globals.rst Globals: Function: Timeout: 3 Parameters: Environment: Type: String AllowedValues: - development - production Mappings: EnvironmentConfig: development: FunctionNamePrefix: Dev ApplicationMessage: "World[development]" production: FunctionNamePrefix: Prd ApplicationMessage: "World[production]" Resources: HelloWorldFunction: Type: AWS::Serverless::Function # More info about Function Resource: https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#awsserverlessfunction Properties: CodeUri: hello-world/ Handler: app.lambdaHandler Runtime: nodejs14.x FunctionName: !Join - "" - - !FindInMap - EnvironmentConfig - !Ref Environment - FunctionNamePrefix - "HelloWorldFunction" Architectures: - x86_64 Environment: Variables: APPLICATION_MESSAGE: !FindInMap - EnvironmentConfig - !Ref Environment - ApplicationMessage Events: HelloWorld: Type: Api # More info about API Event Source: https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#api Properties: Path: /hello Method: get Outputs: # ServerlessRestApi is an implicit API created out of Events key under Serverless::Function # Find out more about other implicit resources you can reference within SAM # https://github.com/awslabs/serverless-application-model/blob/master/docs/internals/generated_resources.rst#api HelloWorldApi: Description: "API Gateway endpoint URL for Prod stage for Hello World function" Value: !Sub "https://${ServerlessRestApi}.execute-api.${AWS::Region}.amazonaws.com/Prod/hello/" HelloWorldFunction: Description: "Hello World Lambda Function ARN" Value: !GetAtt HelloWorldFunction.Arn HelloWorldFunctionIamRole: Description: "Implicit IAM Role created for Hello World function" Value: !GetAtt HelloWorldFunctionRole.Arn 次に、samconfig.tomlでの環境と、AWS SAMテンプレートで環境を表すパラメーターを紐付けます。 これには、parameter_overridesを使うことにします。 開発環境向けのものであれば、以下のように指定します。 parameter_overrides = [ "Environment=development" ] 全体としては、こうなりました。 samconfig.toml version = 0.1 [development] [development.deploy] [development.deploy.parameters] stack_name = "development-sam-hello-world" s3_bucket = "aws-sam-cli-managed-default-samclisourcebucket-1f8pzvbjpaczp" s3_prefix = "development-sam-hello-world" region = "ap-northeast-1" confirm_changeset = true capabilities = "CAPABILITY_IAM" image_repositories = [] parameter_overrides = [ "Environment=development" ] [production] [production.deploy] [production.deploy.parameters] stack_name = "production-sam-hello-world" s3_bucket = "aws-sam-cli-managed-default-samclisourcebucket-1f8pzvbjpaczp" s3_prefix = "production-sam-hello-world" region = "ap-northeast-1" confirm_changeset = true capabilities = "CAPABILITY_IAM" image_repositories = [] parameter_overrides = [ "Environment=production" ] 設定変更したので、sam buildします。 $ sam build あとは、--config-envを指定して環境別にデプロイします。 $ sam deploy --config-env development 実行時に、parameter_overridesの内容が入るようになります。 Deploying with following values =============================== Stack name : development-sam-hello-world Region : ap-northeast-1 Confirm changeset : True Disable rollback : False Deployment s3 bucket : aws-sam-cli-managed-default-samclisourcebucket-1f8pzvbjpaczp Capabilities : ["CAPABILITY_IAM"] Parameter overrides : {"Environment": "development"} Signing Profiles : {} デプロイ後、確認。 $ curl https://[開発環境のREST API ID].execute-api.ap-northeast-1.amazonaws.com/Prod/hello/ {"message":"Hello World[development]"} 本番環境用のものもデプロイ。 $ sam deploy --config-env production parameter_overridesで、本番環境の名前が入るようになっています。 Deploying with following values =============================== Stack name : production-sam-hello-world Region : ap-northeast-1 Confirm changeset : True Disable rollback : False Deployment s3 bucket : aws-sam-cli-managed-default-samclisourcebucket-1f8pzvbjpaczp Capabilities : ["CAPABILITY_IAM"] Parameter overrides : {"Environment": "production"} Signing Profiles : {} 今度はデプロイが成功するので、動作確認もできます。 $ curl https://[本番環境のREST API ID].execute-api.ap-northeast-1.amazonaws.com/Prod/hello/ {"message":"Hello World[production]"} アプリケーションが取得している環境変数の内容も、開発環境のものと異なるものになりました。 関数名の確認。 $ aws lambda list-functions --query 'Functions[].FunctionName' | grep HelloWorld "PrdHelloWorldFunction", "DevHelloWorldFunction", OKですね。 確認できたので、最後に削除して終了。 $ sam delete --config-env development $ sam delete --config-env production これで、AWS SAMで管理するAWS Lambda関数を、単一のAWSアカウント内の複数環境にデプロイすることができました。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Cloud9環境構築

認証情報の設定(Cloud9→AWSへの接続設定) Cloud9を検索し、「Cloud9」をクリック Cloud9のTOP画面へ遷移し、「Create enviroment」をクリック Name(必須)、Description(任意)を入力し、「Next step」をクリック デフォルト(変更なし)のまま「Next step」をクリック 内容を確認し「Create enviroment」をクリック 数分後と環境ができあがります。 認証情報の設定(Cloud9→AWSへの接続設定) 右上ギア印→「AWS settings」をクリック 認証情報ファイル(Credentials)の変更モードを「不可→可」に変える為、「×→✓」へ一時的に変更する 「+」タブ→「New Terminal」をクリックし、ターミナルを開くことができます。 開発用(IAM)ユーザにダウンロードした、認証情報(CSV)ファイルを参照し、順番に入力していきましょう。 Access Key ID:自分のアクセスID Secret Access Key:自分のシークレットキー Region:ap-northeast-1(Asia/Tokyo:東京)※固定値 Output format:json $ aws configure # 設定 $ cat ~/.aws/config $ cat ~/.aws/credential # 設定内容の確認 $ vim ~/.aws/credential # plofileを[default→terraform]へ変更する # vim → iコマンド(INSERT) ~※修正~ → Escキー → :wコマンド(保存)→ :qコマンド(終了) 以上でCloud9環境でTerraformを使えるようになりました。 索引ページ 下記でTerraformに関するテーマをまとめて紹介しています。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Terraformチュートリアル

この記事について TerraformでAWSのインフラ環境を構築する手順を、チュートリアル形式でまとめてみました。 STEP1:AWSアカウント登録 まずはAWSアカウントを作成するところから始めましょう。 STEP2:Cloud9環境構築 AWSのクラウド環境(Cloud9)を使用して、Terraformを実装・実行します。 Cloud9環境の環境を構築し、セットアップをしていきましょう。 Cloud9環境自体の利用は無料であり、すべての作業をクラウド上で行える点がメリットです。 TerraformやPythonがデフォルトでインストールされており(バージョンアップは別途必要)、インストール等のセットアップをせずに作業を開始することができます。 STEP3:Terraformとは Terraformの概要についてまとめました。 STEP4:Terraformセットアップ Cloud9環境でTerraformを利用するための最低限のセットアップを行っていきます。 STEP5:Terraform基本コマンド CUI(Cloud9等)で実行するTerraformの基本コマンドを紹介します。 STEP6:Terraform構成管理 Terraformの基本的なディレクトリ構成や、各ファイルの特性、ファイル間の関係性について解説します。 STEP7:Terraform基本ブロック TerraformでAWS設定を定義する「ブロック」という概念を紹介します。 基本的なブロックについて解説します。 STEP8:Terraform基盤構築:全体概要編 今回構築したアーキテクチャの全体概要を紹介します。 STEP9:Terraform基盤構築:ETL編 今回構築したETL基盤の実装手順、定義情報等について解説します。 STEP10:Terraform基盤構築:イベントソース編 今回構築したログ管理基盤(イベントソース)の実装手順、定義情報等について解説します。 実装コード 使用したデータセット 参考サイト(HashiCorp社 Terraform公式ドキュメント) Terraform Language Documentation ※Terraform各コマンドの公式ドキュメント Terraform : AWS provider ※AWSプラットフォーム用のTerraformコマンドやパラメータの公式ドキュメント 参考資料(AWS公式ドキュメント) AWSドキュメントトップ ※いろいろなドキュメントの索引です。 AWSデベロッパーガイド(Lambda) ※Lambdaについての辞書 AWSデベロッパーガイド(Step Function) ※StepFuncitionsについての辞書
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

アーキテクチャ

アーキテクチャについて 今回は下記のアーキテクチャを構築していきます。 aws.drawio 各構成の詳しい解説は下記しています。 ①ETL・パイプライン(+モニタリング):DataLake → Glue Workflow → Data Ware House → Moniterting ②イベントソース・パイプライン:DataLake → Glue Workflow → Event Source 索引ページ 下記でTerraformに関するテーマをまとめて紹介しています。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

ディレクトリ構造

ディレクトリ構造について terraform  └main.tf  └terraform.tfvars  └variables.tf  └modules/  |└s3/  ||└s3.tf  ||└variables.tf  ||└output.tf  |└glue/  ||└glue.tf  ||└variables.tf  ||└output.tf  |└athena/  ||└athena.tf  ||└variables.tf  ||└output.tf  |└redshift/  ||└redshift.tf  ||└variables.tf  ||└output.tf  |└sfn/  ||└sfn.tf  ||└variables.tf  ||└output.tf  └src/  |└job/  |└query/  |└function/  └data/ 各ファイルの概要 s3.tf (S3の)モジュール・ファイル  ※S3の構成をまとめ、モジュールとして定義するファイル main.tf モジュールを呼び出し、変数の受け渡しを行うファイル terraform.tfvars 環境変数の定義ファイル(≒ envファイル)※値を保持している。 variables.tf 入力変数の定義ファイル(※定義のみ保持している) 他のtfファイルから受け取る変数を定義する。 output.tf 出力変数の定義ファイル ※他のモジュールへ出力する変数を定義する。 ファイル間の関係 main.tfが各モジュール(s3.tf、glue.tf)を呼び出す。 main.tfはモジュールの呼び出し時、変数を渡すことができる。 ※詳しくは「ブロック」のページで紹介します。 各モジュール内で定義したリソースを、main.tf経由で他のモジュールへ橋渡しすることができます。 ※詳しくは「ブロック」のページで紹介します。 索引ページ 下記でTerraformに関するテーマをまとめて紹介しています。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Terraformのセットアップ(Cloud9)

Terraformのインストール、およびバージョン確認 Cloud9環境は、デフォルトでTerraformがインストールされています。 terraform.tfstate(リソースの管理ファイル)の管理 terraform.tfstateファイルとは、Terraformの実行に伴って構築されるAWSのインフラ状態を逐次記録しておくためのファイルです。 terraformコマンドを実行すると自動でローカル環境(Cloud9環境)作成されます。 チームで開発を進める場合、ローカルに保存されていると、変更内容を衝突してしまうことを予想されるため、クラウド(AWSのS3など)へ保管し、変更の衝突を避け、チーム間で同時にインフラ構築が行えるようになります。 またローカルでは紛失、欠損時のリカバリーもできなくなる可能性がある為、クラウド上で保管することが望ましいでしょう。 ここではS3バケットにterraform.tfstateファイルを保管する方法を紹介します。 以後、terraformコマンド実行後、自動でクラウド環境上のtfstateファイルが更新されるようになります。 <手順> 1.S3バケットの作成 2.main.tfファイルの作成、実装 3.terraformコマンドの実行(=tfstateファイルのアップロード) S3バケットの作成 S3を検索 バケットを作成をクリック バケット名を入力 パブリックアクセス設定は変更せずそのままとする。 バケットを作成をクリック バケット名をクリック アクセス許可タブをクリック 編集をクリック チェックを一旦外す 編集をクリック 編集をクリック ポリシージェネレータをクリック 以下を入力し、ユーザ情報とバケットを結び付け、バケットに対する許可する実行アクションを選択します。 <手順> ①Select Type of Policy:S3 Bucket Policy(固定) ②Principal:自分のIAMユーザーのARN ③Actions:ALL Actioncsにチェック ※本来許可するActionは制限すべきだが、ALL Actioncsにチェック ④Amazon Resource Name (ARN):作成したS3バケットのARN ※ARNとは、AWSを一意に識別するリソースネームです。詳細は以下参照。 ③Principal iamを検索 ユーザをクリック ユーザーのARNをコピーして、そのままPrincilpal欄に入力する ④Amazon Resource Name (ARN) S3を検索 該当のバケットを選択し、「ARNをコピー」をクリック ⑤Amazon Resource Name (ARN)欄にそのまま入力する。 main.tfファイルの作成、実装 $ mkdir terraform $ cd terraform $ touch main.tf terraform/main.tf # ---------------------------------- # Terraform versions # ---------------------------------- terraform { required_version = ">=1.1" required_providers { aws = { source = "hashicorp/aws" version = "~>3.0" } } backend "s3" { bucket = "terraform-prd-tfstate-327495" key = "terraform.tfstate" region = "ap-northeast-1" profile = "terraform" } } # ---------------------------------- # Provider # ---------------------------------- provider "aws" { profile = "terraform" region = var.region access_key = var.access_key secret_key = var.secret_key } $ touch terraform.tfvars # terraform.tfvarsを編集 access_key = "自分のアクセスキー" secret_key = "自分のシークレットキー" region = "ap-northeast-1" project = "terraform" enviroment = "dev" ※注意 アクセスキー、シークレットキーの漏洩防止のため、tfvarsファイルを第三者に知れる場所に絶対に置かないこと。 terraformコマンドの実行(=tfstateファイルのアップロード) $ terraform init # 環境の初期化 $ terraform plan # 変更内容が表示されるため、確認する。 $ terraform apply # 変更予定内容を反映し、インフラ環境を構築する。 索引ページ 下記でTerraformに関するテーマをまとめて紹介しています。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

AWSアカウント登録

AWSアカウント登録 必要事項を入力していきましょう。 個人情報を入力していきましょう。 クレジットカード情報の入力が必要です。 まずは「ベーシックサポート - 無料」で良いでしょう。 最初のwelcomeページです。これからあなたもAWSユーザー! コンソール画面です。いろいろなサービスを利用できます! 開発用(IAM)ユーザー作成 IAMを検索して表示しましょう。 ユーザーをクリック ユーザーを作成をクリック 両方チェックを入れておきましょう。 後ほどアクセスIDとシークレットアクセスキーを使用します。 既存のポリシーを付与していきましょう。 大きすぎる権限のため業務では望ましくありませんが、開発(学習)目的の為、「AdministratorAccess」にチェックを付け「次のステップ:タグ」をクリック グループ管理を強いない場合などは、何も設定せずに「次のステップ」をクリック 「ユーザーの作製」をクリック 「.csvのダウンロード」をクリックし、認証情報ファイルを必ずダウンロードし、大切に保管しておきましょう。 ダウンロードしたクレデンシャルファイルに鍵設定をしておきましょう。 ExcelベースでCSVファイルを開き、「ファイル」タブをクリック 情報→ブックの保護 「パスワードを指定して暗号化」をクリック パスワードを二回入力 ブックが保護されました。保存して再度ファイルを開き、鍵設定がされていることを確認しましょう。 索引ページ 下記でTerraformに関するテーマをまとめて紹介しています。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

AWS EC2 スポットブロックは廃止されていた?

AWSで下記のような性質のバッチ処理を実行する必要が発生した。 1~2時間の処理時間。 処理が中断されると、それまでの処理結果は破棄して再実行となる。 「そういえばスポットブロックという機能(スポットリクエストで、指定した時間はインスタンス確保が約束される機能)があったなー」と思い、試してみようと思ったのだが使い方がわからない。 調べていると以下の記載にたどり着いた。 https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/spot-requests.html#fixed-duration-spot-instances つまり、スポットブロックはもう使えないらしい。 "スポットブロック 廃止"等とググってみても情報はヒットせず、ひっそりと終了していたようだ。残念。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

CloudWatchlogsからNewRelic経由でPDへ起票する

はじめに CloudWatchlogsに特定の文字列が出力された時にNewRelicを経由してPagerdutyへ起票する流れを試した時の記録です。 誰かの参考になれば幸いです。 完成イメージ 前提条件 ・Terraform v0.13.5 ・PagerdutyのService等は作成済であること ・NRとPDのインテグレーションは設定済であること ・対象のCloudWatchlogsが作成されていること Terraform ディレクトリ構成は以下 root@:~/-newrelic# tree . . ├── backend.tf ├── condition-log.tf ├── notification.tf ├── policy.tf ├── provider.tf └── variables.tf 各ファイル backend.tf backend.tf terraform { backend "s3" { bucket = "S3バケット名" key = "キー名.tfstate" acl = "bucket-owner-full-control" region = "AWSリージョン" } } notification.tf notification.tf # Add a notification channel resource "newrelic_alert_channel" "pagerduty_channel" { name = "test-pagerduty" type = "pagerduty" config { service_key = var.pd_service_key } } # Link the channel to the policy resource "newrelic_alert_policy_channel" "alert_pagerduty" { policy_id = newrelic_alert_policy.alert_policy.id channel_ids = [ newrelic_alert_channel.pagerduty_channel.id ] } policy.tf policy.tf resource "newrelic_alert_policy" "alert_policy" { name = var.project_name incident_preference = "PER_CONDITION_AND_TARGET" } provider.tf provier.tf terraform { required_version = "~> 0.13.0" required_providers { newrelic = { source = "newrelic/newrelic" version = "2.14.0" } } } # Configure the NewRelic provider provider "newrelic" { account_id = var.nr_account_id api_key = var.api_key insecure_skip_verify = true } variable.tf variable.tf #NewRelicのアカウントID variable nr_account_id { default = NRのアカウントID } #NewRelicのAPIキー variable api_key { default = "NRapiキー NRAK-xxxxxxxxxxxx" } #プロジェクト名 variable project_name{ default = "practice-pj" } #AWSアカウント variable "aws_account_id" { default = "AWSアカウントID" } #連携するPagerutyのAPIキー variable pd_service_key { default = "PagerutyのAPIキー" } #アラート有効/無効 true/false variable "alert_enabled" { default = "true" } #ロググループ variable "log_map_data" { type = map default = { log1 = { name = "practice" group = "ロググループ名" target = "例:resultCode = 200" } } } condition-log.tf condition-log.tf resource "newrelic_nrql_alert_condition" "ec2_log_map" { for_each = var.log_map_data policy_id = newrelic_alert_policy.alert_policy.id type = "static" name = "ログ監視 description = "Test Logs" runbook_url = "" enabled = var.alert_enabled value_function = "single_value" violation_time_limit_seconds = 300 aggregation_window = 60 fill_option = "none" nrql { query = "SELECT COUNT(*) FROM Log FACET aws.logGroup,aws.logStream WHERE message LIKE '%${each.value.target}%' AND aws.logGroup = '${each.value.group}'" evaluation_offset = 7 } critical { operator = "above" threshold = 0 threshold_duration = 60 threshold_occurrences = "at_least_once" } } 実行 上記、コードが配置されたディレクトリにて実行する。 terraform init terraform plan #作成されるリソースを確認 terraform apply #デプロイ AWS CloudWatchログを送信するためのAWSLambdaを作成 下記手順に従い、SAMよりLambdaをデプロイし、トリガーとして対象のCloudWatchログを設定する。 https://docs.newrelic.com/docs/logs/forward-logs/aws-lambda-sending-cloudwatch-logs/ テストしてみる 対象のロググループの[アクション]からログイベントの作成をクリック 下記、画面が表示されたらNewRelicで検知したい文字列等を入力する。 ・NewRelic側で検知され、PDへ起票されることを確認できたら以上となります。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Lambdaでrds自動起動停止

自動起動 iam role作成 AWSコンソールへログイン https://console.aws.amazon.com/iamv2 左ペインロール押下 ロールを作成押下 一般的なユースケース:lambda ポリシー:AmazonRDSFullAccess ロール名:control-rds 作成 lambda関数作成 https://console.aws.amazon.com/lambda 関数の作成押下 関数名:start-rds ランタイム:python3.9 デフォルトの実行ロールの変更 既存のロールを使用する:control-rds 関数の作成 以下コード入れる import boto3 rds = boto3.client('rds') def get_tags_for_db(db): """ get instance list """ instance_arn = db['DBInstanceArn'] instance_tags = rds.list_tags_for_resource(ResourceName=instance_arn) return instance_tags['TagList'] def start_db_instances(target_tag): """ start instances """ try: dbs = rds.describe_db_instances() except Exception as e: print(e) return { 'status': 2 } for db in dbs['DBInstances']: db_tags = get_tags_for_db(db) tag = next(iter(filter(lambda tag: tag['Key'] == target_tag and tag['Value'] == 'true', db_tags)), None) if tag and db['DBInstanceStatus'] == 'stopped': response = rds.start_db_instance(DBInstanceIdentifier=db["DBInstanceIdentifier"]) print(db['DBInstanceIdentifier']) def lambda_handler(event, context): target_tag = "autostart" start_db_instances(target_tag) return { 'status': 0 } rdsへのタグ付け 対象のrdsへ以下タグ付ける kye:autostart value:true 起動したくないときはvalueをfalseへ変更 lambdaのテスト test押下 新しいテストイベントの作成 イベントテンプレート:そのまま イベント名:適当に 作成 test押下 ちゃんと動くか確認 EventBridge +トリガーの追加 トリガーの選択 EventBridge 新規ルールの作成 ルール名:auto-start-rds ルールタイプ スケジュール式 cron(0 23 ? * SUN-THU *) #平日の朝8時起動 自動停止 lambda関数作成 https://console.aws.amazon.com/lambda 関数の作成押下 関数名:stop-rds ランタイム:python3.9 デフォルトの実行ロールの変更 既存のロールを使用する:control-rds 関数の作成 以下コード入れる import boto3 rds = boto3.client('rds') def get_tags_for_db(db): """ get instance list """ instance_arn = db['DBInstanceArn'] instance_tags = rds.list_tags_for_resource(ResourceName=instance_arn) return instance_tags['TagList'] def stop_db_instances(target_tag): """ stop instances """ try: dbs = rds.describe_db_instances() except Exception as e: print(e) return { 'status': 2 } for db in dbs['DBInstances']: db_tags = get_tags_for_db(db) tag = next(iter(filter(lambda tag: tag['Key'] == target_tag and tag['Value'] == 'true', db_tags)), None) if tag and db['DBInstanceStatus'] == 'available': response = rds.stop_db_instance(DBInstanceIdentifier=db["DBInstanceIdentifier"]) print(db['DBInstanceIdentifier']) def lambda_handler(event, context): target_tag = "autostop" stop_db_instances(target_tag) return { 'status': 0 } rdsへのタグ付け 対象のrdsへ以下タグ付ける kye:autostop value:true 停止したくないときはvalueをfalseへ変更 lambdaのテスト test押下 新しいテストイベントの作成 イベントテンプレート:そのまま イベント名:適当に 作成 test押下 ちゃんと動くか確認 EventBridge +トリガーの追加 トリガーの選択 EventBridge 新規ルールの作成 ルール名:auto-stop-rds ルールタイプ スケジュール式 cron(0 13 ? * MON-FRI *) #平日の22時停止
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Serverless Framework × TypeScript のローカル開発環境構築メモ(Serverless Offline編)

Serverless Frameworkとは、サーバーレスアーキテクチャでAPIを作る際に面倒なインフラ構築をコマンド一発でやってくれる優れもののフレームワークです!今回はこのServerless Frameworkをローカルで動かせるプラグインServerless Offineを使ってローカル開発できるようにしていきましょう。 Severless Frameworkの環境構築 まず、serverless frameworkをインストールし、typescriptテンプレートを使ってビルドします。詳しくはリンク先を参照ください。 $ npm install -g serverless $ serverless create --template aws-nodejs-typescript --path api この時のディレクトリ構成は次のようになっています。 api ├── README.md ├── package.json ├── serverless.ts ├── src │   ├── functions │   │   ├── hello │   │   │   ├── handler.ts │   │   │   ├── index.ts │   │   │   ├── mock.json │   │   │   └── schema.ts │   │   └── index.ts │   └── libs │   ├── apiGateway.ts │   ├── handlerResolver.ts │   └── lambda.ts ├── tsconfig.json └── tsconfig.paths.json serverless.tsがテンプレートファイルとなっており、このテンプレートではデフォルトでmiddyやjson-schema-to-tsといったプラグインが入っています。そのため、関数を書く際は、内部のビジネスロジックとAPIのインターフェイスにのみ注力すれば良くなります。ただし、application/json以外のContent Typeの場合は修正が必要になります。 functionsディレクトリがLambda関数のソースコードを書くディレクトリです。helloデレクトリを見ると、index.tsでLambda関数の設定を書き、handler.tsで実際のハンドラーを書く形になっています。schema.tsではhttpリクエストのスキーマを定義しており、json-schema-to-tsでtype化してハンドラの型定義に使っています。実際に次のコマンドで関数をローカルで実行できます。 $ npx sls invoke local -f hello --path ./src/functions/hello/mock.json Serverless Offlineの導入 前述のinvoke localは関数を実行するだけだったので、フロントエンドとの結合をテストするなどでAPIを立てる必要がある場合にはプラグインを導入する必要があります。そのためにローカルAPIを立ててくれるプラグインがServerless Offlineです。公式に従ってインストールしていきましょう。まず、以下のコマンドを実行します。 $ npm install -D serverless-offline あとは、serverless.ts内のpluginsの最後に"serverless-offline"を挿入するだけです。 serverless.ts plugins: ["serverless-esbuild", "serverless-offline"], ここまでできたら、次のコマンドでローカルAPIを立ててみましょう。 $ npx sls offline start 次のようなメッセージが出ていれば、localhost:3000にパス/dev/helloのAPIが立っていることになります。 ┌─────────────────────────────────────────────────────────────────────────┐ │ │ │ POST | http://localhost:3000/dev/hello │ │ POST | http://localhost:3000/2015-03-31/functions/hello/invocations │ │ │ └─────────────────────────────────────────────────────────────────────────┘ offline: [HTTP] server ready: http://localhost:3000 ? offline: offline: Enter "rp" to replay the last request ^Coffline: Got SIGINT signal. Offline Halting... offline: Halting offline server 次のコマンドで接続確認してみましょう。nameは各自の名前に変えてくださいね。 $ curl -X POST -H "Content-Type: application/json" -d "{\"name\": \"Utan\"}" localhost:3000/dev/hello 何もコードをいじってなければ次のレスポンスが返ってくるはずです。もちろんnameは各自の名前で。 {"message":"Hello Utan, welcome to the exciting Serverless world!","event":{"body":{"name":"Utan"},"headers":{"Host":"localhost:3000","User-Agent":"curl/7.77.0","Accept":"*/*","Content-Type":"application/json","Content-Length":"16"},"httpMethod":"POST","isBase64Encoded":false,"multiValueHeaders":{"Host":["localhost:3000"],"User-Agent":["curl/7.77.0"],"Accept":["*/*"],"Content-Type":["application/json"],"Content-Length":["16"]},"multiValueQueryStringParameters":null,"path":"/hello","pathParameters":null,"queryStringParameters":null,"requestContext":{"accountId":"offlineContext_accountId","apiId":"offlineContext_apiId","authorizer":{"principalId":"offlineContext_authorizer_principalId"},"domainName":"offlineContext_domainName","domainPrefix":"offlineContext_domainPrefix","extendedRequestId":"ckydl1ztx0003r28z3ftnejyj","httpMethod":"POST","identity":{"accessKey":null,"accountId":"offlineContext_accountId","apiKey":"offlineContext_apiKey","apiKeyId":"offlineContext_apiKeyId","caller":"offlineContext_caller","cognitoAuthenticationProvider":"offlineContext_cognitoAuthenticationProvider","cognitoAuthenticationType":"offlineContext_cognitoAuthenticationType","cognitoIdentityId":"offlineContext_cognitoIdentityId","cognitoIdentityPoolId":"offlineContext_cognitoIdentityPoolId","principalOrgId":null,"sourceIp":"127.0.0.1","user":"offlineContext_user","userAgent":"curl/7.77.0","userArn":"offlineContext_userArn"},"path":"/hello","protocol":"HTTP/1.1","requestId":"ckydl1ztx0004r28zdrcjbjdq","requestTime":"14/Jan/2022:08:08:26 +0900","requestTimeEpoch":1642115306660,"resourceId":"offlineContext_resourceId","resourcePath":"/dev/hello","stage":"dev"},"resource":"/hello","rawBody":"{\"name\": \"Utan\"}"}} Lambda関数を足してみる 以上で、基本的なローカルAPI開発環境は整いました!あとはfunctionsディレクトリにどんどん関数を足していくだけですね。そのやり方をメモしておきます。 関数を足す際には、まず次のようにfunctionsディレクトリに新しいディレクトリを足します。今回はhogeディレクトリを足しました。 api/src/functions ├── hello │   ├── handler.ts │   ├── index.ts │   ├── mock.json │   └── schema.ts ├── hoge │   ├── handler.ts │   ├── index.ts │   ├── mock.json │   └── schema.ts └── index.ts 次に、hoge/index.ts, handler.tsを適当に書き換えます。今回は次のように書き換えました。 hoge/index.ts import { handlerPath } from '@libs/handlerResolver'; export default { handler: `${handlerPath(__dirname)}/handler.main`, events: [ { http: { method: 'get', path: 'hoge', } } ] } hoge/handler.ts import type { ValidatedEventAPIGatewayProxyEvent } from "@libs/apiGateway"; import { formatJSONResponse } from "@libs/apiGateway"; import { middyfy } from "@libs/lambda"; const handler: ValidatedEventAPIGatewayProxyEvent<{}> = async (event) => { return formatJSONResponse(200, { message: `Hoge !!`, event, }); }; export const main = middyfy(handler); あとは、serverless.tsのfunctionsにエクスポートしたhoge関数をインポートしてやるだけです。 serverless.ts functions: { hello, hoge }, ここまでできたらnpx sls offline startで再度ローカルAPIを立てましょう。次のようにhogeのパスが追加されているはずです。 ┌─────────────────────────────────────────────────────────────────────────┐ │ │ │ POST | http://localhost:3000/dev/hello │ │ POST | http://localhost:3000/2015-03-31/functions/hello/invocations │ │ GET | http://localhost:3000/dev/hoge │ │ POST | http://localhost:3000/2015-03-31/functions/hoge/invocations │ │ │ └─────────────────────────────────────────────────────────────────────────┘ offline: [HTTP] server ready: http://localhost:3000 ? offline: offline: Enter "rp" to replay the last request 実際にGETリクエストを送って確認してみましょう。 $ curl -X GET localhost:3000/dev/hoge 次のようなレスポンスが帰ってくるはずです。 {"message":"Hoge !!","event":{"body":null,"headers":{"Host":"localhost:3000","User-Agent":"curl/7.77.0","Accept":"*/*"},"httpMethod":"GET","isBase64Encoded":false,"multiValueHeaders":{"Host":["localhost:3000"],"User-Agent":["curl/7.77.0"],"Accept":["*/*"]},"multiValueQueryStringParameters":null,"path":"/hoge","pathParameters":null,"queryStringParameters":null,"requestContext":{"accountId":"offlineContext_accountId","apiId":"offlineContext_apiId","authorizer":{"principalId":"offlineContext_authorizer_principalId"},"domainName":"offlineContext_domainName","domainPrefix":"offlineContext_domainPrefix","extendedRequestId":"ckydluco000000w8z1th29e49","httpMethod":"GET","identity":{"accessKey":null,"accountId":"offlineContext_accountId","apiKey":"offlineContext_apiKey","apiKeyId":"offlineContext_apiKeyId","caller":"offlineContext_caller","cognitoAuthenticationProvider":"offlineContext_cognitoAuthenticationProvider","cognitoAuthenticationType":"offlineContext_cognitoAuthenticationType","cognitoIdentityId":"offlineContext_cognitoIdentityId","cognitoIdentityPoolId":"offlineContext_cognitoIdentityPoolId","principalOrgId":null,"sourceIp":"127.0.0.1","user":"offlineContext_user","userAgent":"curl/7.77.0","userArn":"offlineContext_userArn"},"path":"/hoge","protocol":"HTTP/1.1","requestId":"ckydluco000010w8zh9agf16c","requestTime":"14/Jan/2022:08:30:29 +0900","requestTimeEpoch":1642116629657,"resourceId":"offlineContext_resourceId","resourcePath":"/dev/hoge","stage":"dev"},"resource":"/hoge"}} 終わりに ここまででServerless FrameworkでサーバーレスAPIのローカル開発環境の基本的な部分が整ったかと思います。あとはどんどん関数を足してリッチなAPIにしてくだけですね!!次回はDynamoDBのローカル開発環境をServerlessで立てていきます!ぜひ最高のエンジニアライフを!!
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

AWS CDKでconstructor内のthisでなぜかエラーが出る

結構ハマった部分なので共有。 状況 cdkの環境を作るところから。 ❯ cdk init --language typescript Applying project template app for typescript # Welcome to your CDK TypeScript project! This is a blank project for TypeScript development with CDK. The `cdk.json` file tells the CDK Toolkit how to execute your app. ## Useful commands * `npm run build` compile typescript to js * `npm run watch` watch for changes and compile * `npm run test` perform the jest unit tests * `cdk deploy` deploy this stack to your default AWS account/region * `cdk diff` compare deployed stack with current state * `cdk synth` emits the synthesized CloudFormation template Executing npm install... npm WARN deprecated urix@0.1.0: Please see https://github.com/lydell/urix#deprecated npm WARN deprecated resolve-url@0.2.1: https://github.com/lydell/resolve-url#deprecated npm WARN deprecated sane@4.1.0: some dependency vulnerabilities fixed, support for node < 10 dropped, and newer ECMAScript syntax/features added ✅ All done! ここで生成された/lib内で適当にコードを打つとconstructor内のthisでエラーが出ることがあります。 対処 ❯ npm install -g npm-check-updates ❯ npx ncu -u ❯ npm i これでエラーが消えるはずです。 原因 package.jsonの中身の一部です。 "dependencies": { "@aws-cdk/aws-lambda-nodejs": "^1.119.0", "@aws-cdk/core": "1.116.0", } 簡単に言うと、ここのversionが合っていないとエラーが出ます(手で書き換えてもエラーは消えません)。 上のコマンドではこのversionを揃える動作をしているので、直るというわけですね。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む