20220109のAWSに関する記事は19件です。

API Gateway から SQS に連携してみた

はじめに API Gateway には、AWS Service の Integrate 機能があります。例えば、フロントエンドから API Gateway を通じて SQS にデータを格納した場合、API Gateway → Lambda → SQS という構成が考えられます。この構成でも問題はないのですが、よりシンプルに API Gateway → SQS といった形で直接 SQS にデータを格納できます。シンプルなアーキテクチャにすることで、より堅牢で安定したサービス提供に貢献できるメリットがあります。 今回の記事では、直接 API Gateway → SQS へデータを格納する構築手順を確認してみましょう。 IAM Role の作成 まず、API Gateway に設定する IAM Role を作成していきます。IAM Role の作成画面で API Gateway を選択します。 そのまま Next を押します。 また Next を押します。 Role Name を入力して Create Role を押します。 Add inline policy を押します。 入力するポリシーは次のものを入れます。SQS へ SendMessage を出来るようにします。 { "Version": "2012-10-17", "Statement": [ { "Sid": "VisualEditor0", "Effect": "Allow", "Action": "sqs:SendMessage", "Resource": "*" } ] } Create を押して、IAM Role を作成します。 作成した IAM Role ARN は後ほど使うので、メモっておきます。 arn:aws:iam::xxxxxxxxxxxx:role/apigateway-sqs-test-role SQS キューの作成 次に SQS キューを作成します。 パラメータを入力 type : standard 名前 Default のまま 作成した IAM Role を指定して、API Gateway からこの Queue にデータを格納できるように指定 そのほかは Default のまま Create を押します。 SQS キューが作成されました。 API Gateway の作成 API Gateway を作成していきます。 REST API を選びます。 API Gateway の名前を入れます。 apigateway-sqs-test API Gateway の編集画面で、 Create Resource を押します。 適当な名前で Create を押します。 作成したリソースに対して、Create Method を押します。 今回は POST を選択します。 パラメータを入れます。 Integration Type : AWS Service を選ぶ AWS Service : SQS を選択 Path override : [AWSアカウントID/SQSキューの名前] を入力 Path Override に何を入力するべきか調べる方法を説明します。今回の記事は、SQS にデータを格納する SendMessage API を使っていくため、次の APO Reference Document を参照します。 https://docs.aws.amazon.com/ja_jp/AWSSimpleQueueService/latest/APIReference/API_SendMessage.html#API_SendMessage_Examples この Document に、SendMessage を実行するSample が書かれています。この Sample の中に、123456789012/MyQueue と記載されていますが、この部分を Path Override で入力しています。SQS の場合は今回の記事の内容で問題ないですが、他のサービスの場合は、そのサービスに合わせた文字列を入力する必要があるので、適宜調べていきましょう。 設定後、 Integration Request を選びます。 HTTP Headers に次のパラメータを入れます。 Content-Type 'application/x-www-form-urlencoded' Mapping Templates の add を押します。 application/json を入れます。 Mapping Template の値に、次の文字列を入れます。 Action : SQS で sendMessage の API を使う MessageBody : $input.body を指定。API Gateway に渡された Body を、そのまま SQS に格納する Action=SendMessage&MessageBody=$input.body この Mapping Template に入力する文字列ですが、該当する API の Document を見ながら組み立てることが出来ます。 https://docs.aws.amazon.com/ja_jp/AWSSimpleQueueService/latest/APIReference/API_SendMessage.html この Document に Sample があり、URL クエリーパラメータが載っています。この中に、Action=SendMessage だとか、MessageBody=this+is と書かれています。この部分を Mapping Template として文字列を組み立てていきます。 API Gateway で TEST ここまで設定すると、TEST が出来ます。TEST をクリックします。 Request Body に次の文字列を入れます。ここに入れた文字列が SQS に格納されます。 { "data" : "test" } Test を押して、実際に SQS にデータを格納します。 Response が 200 になります。 SQS側でデータを確認していきましょう。SQS キューの画面で Send and receive messages を押します。 Poll for messages を押して、SQS 上のメッセージを受信します。 画像はいくつかのメッセージが表示されていますが、複数回 TEST しているためです。どれか適当に選びます。 Body に、テストで入力した文字列が表示されていることが確認できます。 API Gateway Deploy API Gateway で Deploy API を押して、実行できるようにしていきます。 適当に名前を入れて Deploy を押します。 Deploy 完了です。Invoke URL が生成されています。 curl で TEST これで外部から REST API 経由で SQS にデータを格納できるようになりました。今回は、curl コマンドでやっていきます。 curl -s -H 'Content-Type:application/json' \ -X POST \ https://uuy6eahto0.execute-api.ap-northeast-1.amazonaws.com/prod/sqs-queue \ -d '{"test1":"data1", "test2":"data2"}' 実行例 > curl -s -H 'Content-Type:application/json' \ -X POST \ https://uuy6eahto0.execute-api.ap-northeast-1.amazonaws.com/prod/sqs-queue \ -d '{"test1":"data1", "test2":"data2"}' | jq . { "SendMessageResponse": { "ResponseMetadata": { "RequestId": "4d17bbed-9166-5b96-adf1-e1b94eb7c5e4" }, "SendMessageResult": { "MD5OfMessageAttributes": null, "MD5OfMessageBody": "58fdfbfc48f868b6b9c50b3e8aa09894", "MD5OfMessageSystemAttributes": null, "MessageId": "c21a633e-d8dc-4b0e-9f33-7b2b2d7595f9", "SequenceNumber": null } } } 実行した結果を SQS 上でも確認できます。 curl で与えた body が確認できました。 検証を通じてわかったこと API Gateway で AWS Service Integrate をした時に、どういった API を呼びだすのか指定するのが、Mapping Template Mapping Template の指定は、各サービスの API Reference を参照しながら埋めていくのがわかりやすい 参考URL
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

ImageBuilderでカスタムAMIを作成

ImageBuilderでカスタムAMIを作成 はじめに 昔、IaCの先駆けといいますか、PapetやChefを使用したことがあります。 その後、Ansibleが主流となった経緯を体験してきました。 PapetやChefでは自動構築する処理を書くのですが、それを「レシピ」と呼んでいました。 Ansibleではプレイブックと呼ぶようになったので、しばらく「レシピ」という言葉は聞かなくなりました。 今回、AWSでもAnsibleのようなIaCサービス、ImageBuilderを使用する必要があり、事前検証を行いました。 ここで久々に「レシピ」という言葉に出会ったのですが、Chefの頃のレシピとは少々位置づけが違っているように感じ、ImageBuilderの理解に時間がかかってしまいました。 最終的にはこのImageBuilderの検証で行った手順をTerraform化し、マネジメントコンソールから設定するのではなく、IaC(Terraform)でIaC(imageBuilder)を構成することも検討予定ですが、まずはImageBuilderとはどのようなサービスなのか、どんなものが作成されるのか、こちらを検証してみることにしました。 どこから手を付ける? ImageBuilderへアクセスするとこのような画面が表示されます。 「イメージパイプラインを作成する」というボタンが目立ちますが、闇雲に試してみたところ、ここからスタートするのは少々難しいと感じました。 ではどこから構築するか。 イメージパイプラインはイメージレシピと、イメージレシピを構成するコンポーネントが必要になることがわかりました。 下から攻める、まずはコンポーネントから用意していくことにしました。 コンポーネント コンポーネントはその名の通り、どのようなコンポーネントをどのように準備するのかを記載します。 今回はAMIにZabbix AgentとSplunkをインストールした状態で作成したいので、Zabbix Agent用とSplunk用の2つのコンポーネントを作成します。 「コンポーネントを作成する」をクリックします。 コンポーネントの各パラメータですが、以下のように指定しました。 タイプ=ビルド 互換性のあるOSバージョン=Amazon Linux 2 コンポーネント名=ZabbixAgent コンポーネントのバージョン=1.0.0 実際の処理はこの下にある、「定義ドキュメント」に記載します。 どのように書くべきか、まずは記述イメージを沸かせるために、「例を使用する」をクリックしてみます。 AWSが用意しているサンプルが表示されます。 このサンプルを見つつ、自分がどのような処理でコンポーネント(今回はZabbixAgent)をインストールするのかを記述します。 (以下、さらっと書いていますが、何度も何度も試行錯誤して出来上がった定義ドキュメントです) 同様の手順で、Splunk用のコンポーネントも作成しておきます。 イメージレシピ 次に、どのコンポーネントを使用するのかを定義するイメージレシポを作成します。 「イメージレシピを作成」をクリックします。 イメージレシピの基本的な情報となる名前とバージョンを指定します。 ベースとなるイメージを指定します。 今回はAmazon Linux 2を使用します。 Amazon Linux 2をどのような状態で使用するのかを指定できます。 常に最新の状態のAIMを使用したい場合もあるでしょうが、以下のように、バージョンを指定しておくことも可能です。 業務で使用する場合は常に最新のものというよりは、動作検証のとれた、確実に動くバージョンを使用したい場合もあると思いますので、そういう場合にとても役に立つ設定だと思います。 インスタンスの設定は今回は利用しませんでしたので未指定で進めます。 (SSMエージェントの削除は指定しても良かったかもしれません) 作業ディレクトリも特に理由がなければ変更せずこのままで進めます。 次に、肝となるコンポーネントの指定です。 ここで、AWSが用意しているコンポーネントや、事前に作成したコンポーネントを選択します。 選択肢から、「ユーザ所有」を選択します。 すると、事前に作成したコンポーネントが表示されるので、カスタムAMIにどのコンポーネントをインストールするのかを指定します。 今回はZabbixAgentとSplunkHFを選択します。 テストコンポーネントも同様にAWSが用意されたコンポーネントなどが選択可能です。 今回はテストコンポーネントは使用しませんので、コンポーネントの選択は行わずに進めます。 ストレージボリューム、タグについても必要に応じて設定します。 設定が終わったら、最後に「レシピを作成する」をクリックします。 イメージパイプライン コンポーネント、イメージレシピの準備ができましたので、いよいよイメージパイプラインを作成します。 イメージパイプライン名を入力し、 ビルドスケジュールは今回は検証のため「手動」とし、 必要に応じてタグを入力し、「次へ」をクリックします。 イメージレシピの指定になりますが、事前に作成してあるので、「既存のレシピを使用する」を選択します。 ここで新しいレシピを作成することも可能です。 ImageBuilderに慣れていればここから作成したほうが楽かもしれません。 事前に作成しておいたイメージレシピを選択します。 すると、画面には、選択したイメージレシピの情報が表示されます。 先程設定したように、ZabbixAgentとSplunkHFの2つのコンポーネントが含まれていることがわかります。 内容を確認し、「次へ」をクリックします。 インフラストラクチャ設定では今回は便宜上、「サービスデフォルトを使用」とします。 なお、このインフラストラクチャ設定は後ほど変更します。 ディストリビューション設定もデフォルトのまま進めます。 以上の設定の内容を最後に確認し、「パイプラインを作成する」をクリックします。 インフラストラクチャ設定の変更 作成したイメージパイプラインですが、このままでは実行時にエラーになる箇所と、少々カスタマイズしたほうが良い箇所がありますので、そちらを変更します。 IAMロールの変更 この変更は、どのようなコンポーネントを定義しているのかに左右されます。 今回の検証ではZabbixAgentで必要な媒体はインターネットから取得しています。 SplunkHFは特定のバージョンを利用したいこともあり、S3バケット内に媒体を保管しておき、コンポーネント内でS3から媒体を取得する処理にしています。 このイメージパイプラインのインフラストラクチャ設定で定義されているIAMロールはS3へのアクセス権限が不足していますので、このまま実行するとエラーになります。 インフラストラクチャの「編集」をクリックし、IAMロールの下にある、「新しいロールを作成する」をクリックします。 ロール名の検索欄に「EC2」と入力すると、現在インフラストラクチャ設定で使用されている「EC2InstanceProfileForImageBuilder」が現れますので、ロール名をクリックします。 このロールにS3のアクセスポリシーをアタッチします。 余計な権限は与えないのがAWSのポリシー。 今回はS3バケットから情報が取り出せれば良いので、「AmazonS3ReadOnlyAccess」を選択します。 これでS3へのアクセス権限が付与されました。 インスタンスタイプの変更 イメージパイプラインのインフラストラクチャ設定に戻ります。 ここにある、インスタンスタイプが未指定の状態です。 このままでも問題はないのですが実際に実行すると4xlargeなど、高スペックのインスタンスが使用されます。 パイプラインの実行が終われば自動的にインスタンスは終了するのでそこまで費用にこだわらなくてもよいのかもしれませんが、少しでも費用を抑えるために、低スペックのインスタンスを指定しておきます。 動作確認 以上で基本的なImageBuilderの設定が終わりました。 実際に実行し、カスタムAMIが作成されるか確認してみます。 今回のイメージパイプラインは手動で設定していますので、イメージパイプラインを画面から実行します。 しばらく時間がかかりますが、エラーがなければ出力イメージのステータスが「使用可能」になります。 あとは、完成したこのAMIを使用して、EC2インスタンスを起動するだけです。 実際に起動したEC2インスタンスを確認すると、ZabbixAgentが起動していますし、S3から取得したSplunkHFの媒体も/tmpに存在しています。 おわりに ImageBuilderの構成の理解に少々時間がかかりました。 あとはコンポーネントの中身。 こちらは何度か試行錯誤しながら形にしていくことになりますので、こちらも少々時間がかかります。 それでも、一度カスタムAMIが完成してしまえば、あとは安定して同じ状態のAMIを使用してEC2のインスタンスやコンテナを起動することができます。 これまで、ChefやAnsibleで自動構築を経験してきましたが、AWSでも同じようなことができるということを実際に経験することができました。 Ansible等に触れたことがある方であれば理解は早いと思います。 AnsibleのRoleのように、コンポーネントを分割して構成する構成が良いです。 コンポーネントをバージョンアップしたのであれば、それに付随してイメージレシピもどのバージョンのコンポーネントを使用するのかを設定変更すれう必要がありますが、関係のないコンポーネントに影響が及ぶことにはなりません。 例えば、SplunkHFのコンポーネントを修正し、バージョンを「1.0.1」に変更した場合、イメージレシピ内のコンポーネントのバージョン指定も変更する必要があります。 修正したコンポーネントはイメージレシピンはすべてバージョン管理されて保存されているため、いつでも過去のバージョンを使用してカスタムAMIを作成することもできます。 一度使い方を理解してしまえば、かなり面白いサービスだなと感じることができました。 これはImageBuilderにだけ言える話ではなく、AWSの他のサービスについても同じようなことが言えると思います。 サービス数が多いのですべてを検証してみることはできませんが、今後も積極的に検証し理解を深めていき、有志とも情報を共有して行きたいと感じた、今回の検証でした。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

AWS SAM - Black Belt

背景 下記記事で Step Functions の構築には SAM がかなり便利ということを実感したので、もう少し深堀りして学習すべく、Black Belt の資料を見てみる。 読んでみる AWS SAM とは Serverless な Application ... 何らかの「イベント」に応じて Lambda 関数を起動し処理を行う性質を持つ サーバーレスを取り巻く主なコンポーネント 外部 I/F REST API: Amazon API Gateway GraphQL: AWS AppSync ストリーム 流入データ: Amazon Kinesis Data Streams 処理ロジック Pythonなど: AWS Lambda データ保持/管理 NoSQL: Amazon DynamoDB Queue: Amazon SQS File: Amazon S3 AWS Serverless Application Model (SAM) イベント駆動の性質を持つサーバーレス アプリケーションのデプロイに特化した、AWS CloudFormation の拡張機能 CloudFormation 同様に YAML もしくは JSON 形式で、 SAM テンプレートを記述する サーバーレス アプリケーションの開発を支援する AWS SAM コマンドライン インターフェイス (CLI) が提供されている GitHub 上でオープンソースで開発が行われている SAM テンプレートの特徴 SAM を利用すると、より簡潔にサーバーレスなアプリケーションを定義できる CloudFormation でデプロイする際に、本来の CloudFormation の文法に変換される より直感的にわかりやすくサーバーレスなアプリケーションを定義できる 変換の仕組み もともと、 CloudFormation には Transform というセクションを定義でき、CloudFormationテンプレートの 変換方式 (マクロ) を用意できる 'AWS::Serverless-2016-10-31' というマクロが、 あらかじめ CloudFormation 側で用意されている AWS::Serverless というプレフィックスの Type のリソースを、 CloudFormation の本来の文法に変換する 自身で定義した CloudFormation マクロとの共存も可能 通常の CloudFormation テンプレートとの統合 SAM は CloudFormation の拡張なので、通常の CloudFormation の文法と共存できる AWS SAM の機能と文法 SAM テンプレート - ヘッダー 用意する SAM テンプレートのバージョンや、デプロイする内容について説明を書く。 AWSTemplateFormatVersion Transform Description SAM テンプレート - リソース Resources の配下に、実際にデプロイするリソースの詳細を定義していく。 Type に指定する値によって、どのようなリソースを配置数rのかが決まる。 Type に指定可能な値は、次の 5 種類 AWS::Serverless::Function AWS Lambda をデプロイ AWS::Serverless::Api Amazon API Gateway をデプロイ AWS::Serverless::SimpleTable Amazon DynamoDB のテーブルをデプロイ AWS::Serverless::LayerVersion Lambda Layer をデプロイ AWS::Serverless::Application Serverless Application Repository に存在するアプリケーションをデプロイ AWS::ServerlessFunction リソースタイプ AWS Lambda 関数をデプロイすると同時に、 Lambda を起動するイベントを設定する。 イベントの種類によっては、イベント発生元となるリソースも同時にデプロイされる。 Properties の中にこの 2 種類を記載することが基本 AWS Lambda の実装や設定値 Lambda を起動するイベント AWS::ServerlessFunction で紹介するプロパティ Handler, Runtime プロパティ CodeUri, InlineCode プロパティ Events プロパティ AutoPublishAlias プロパティ DeploymentPreference プロパティ Policies プロパティ Handler, Runtime プロパティ Lambda 関数で利用するランタイムと、実行する関数の位置 (ハンドラ) を指定する。 CodeUri, InlineCode プロパティ Lambda 関数の実装内容は CodeUri もしくは InlineCode プロパティに指定する。 そのため、CodeUri か InlineCode プロパティいずれかの指定が必須となる。 CodeUri の場合 S3 に事前にアップロードした ZIP ファイルの URI を指定する (ZIP ファイルに関数の実装を固めておく) InlineCode の場合 テンプレートの中に直接コードを書く Events プロパティ Lambda 関数が実行されるトリガー を Events プロパティ配下に指定する (複数可)。 Type プロパティに AWS のどのサービスをイベントソースにするかを指定する。 対応する AWS のサービス S3 Amazon API Gateway Amazon DynamoDB SNS SQS Amazon Kinesis Data Stremas Amazon CloudWatch Events (スケジュール) Amazon CloudWatch Events (イベント) Amazon CloudWatch Logs AWS IoT ルール Amazon Alexa スキル AutoPublishAlias プロパティ AutoPublishAlias を指定すると、 SAM が Lambda 関数の更新をバージョン管理する。 Lambda 関数にデプロイする内容が変化すると、新しいバージョンを発行し、指定したエイリアスを最新版に変更する。 DeploymentPreference プロパティ DeploymentPreference と AutoPublishAlias を指定すると、 AWS CodeDeploy と自動で連携する。 最新のコードを一部だけデプロイし、段階的にデプロイを完了させること (カナリアリリース) が可能。 DeploymentPreference の Type に指定できる値は以下の通り。 指定した内容により、どのように最新バージョンがリリースされるか動作が変わる。 Canary10Percent30Minutes Canary10Percent5Minutes Canary10Percent10Minutes Canary10Percent15Minutes AllAtOnce Linear10percentEvery10Minutes Linear10percentEvery1Minutes Linear10percentEvery2Minutes Linear10percentEvery3Minutes Policies プロパティ よく利用されるポリシーについて簡単に設定できるよう、あらかじめ用意されているポリシーがある。 AWS::Serverless::Api リソースタイプ API Gateway をデプロイする。 AWS::serverless::Function の API イベントタイプと組み合わせて使う 場合が多く、より詳細な API Gateway の設定を行いたい場合に利用する。 AWS::Serverless::Api で紹介するプロパティ StageName プロパティ CanarySetting プロパティ DefinitionUri, DefinitionBody プロパティ Auth プロパティ StageName プロパティ API Gateway の API のデプロイ先となるステージ名は必須、かつ 1 つのみ指定ができる。 そのため、 dev, test, prod といった複数ステージをデプロイすることはできない。 CanarySetting プロパティ CanarySetting プロパティを利用すると、 API 定義をアップデートした際に、一部のトラフィックのみを最新版 (Canary) に流すことができる。 DefinitionUri, DefinitionBody プロパティ API Gateway の API 定義を独自に設定する場合、 DefinitionUri もしくは DefinitionBody プロパティに指定する。 DefinitionUri か DefinitionBody いずれかのみ指定可能。 DefinitionUri の場合 S3 に事前にアップロードした API 定義を指定する Definition Body の場合 テンプレートの中に直接 API 定義を書く Auth プロパティ API Gateway のオーソライザーを作成し認可方式が設定できる。 Auth プロパティを使う場合、 DefinitionUri による API 定義は使えないことに注意。 リソースタイプ - AWS::Serverless::SimpleTable DynamoDB のテーブルをデプロイ するリソースタイプ。 CloudFormation の AWS::DynamoDB::Table タイプと同等だが、より簡潔に書くことができる。 リソースタイプ - AWS::Serverless::LayerVersion Lambda レイヤーをデプロイするリソースタイプ。 リソースタイプ - AWS::Serverless::Application Serverless Application Repository や特定の SAM テンプレートから、アプリケーションをデプロイする。 実際のアプリケーションのデプロイは Nested Stack の中で行われる。 SAM テンプレート - グローバルセクション 各リソースタイプに適用するプロパティのデフォルト値を定義することができる。 AWS::Severless::Function AWS::Severless::Api AWS::Severless::SimpleTable の 3 種類のリソースが対応。 明示的にプロパティを指定しない場合のデフォルト値を決めることができる。 AWS SAM Command Line Interface AWS SAM Command Line Interface (CLI) 開発者のローカル環境で Lambda や API のエンドポイントを起動し、実行をテストすることができる Lambda をローカル実行するにあたり Docker コンテナを利用するため、 Docker のインストールが事前に必要 SAM を利用したサーバーレス アプリケーションの雛形を作ることができる SAM テンプレートの文法が正しいか検証することが可能 アプリケーションのビルド、パッケージング、デプロイを行うことができる 現在はベータ版としての提供 雛形の生成 (sam init) sam init コマンドで雛形を作成。 --runtime オプションに実装する言語を指定できる。 実行すると、Lambda へデプロイするコードや、単体テストのコード、さらに関数をデプロイするための SAM テンプレートなどが生成される。 bash $ sam init Which template source would you like to use? 1 - AWS Quick Start Templates 2 - Custom Template Location Choice: 1 Cloning from https://github.com/aws/aws-sam-cli-app-templates Choose an AWS Quick Start application template 1 - Hello World Example 2 - Multi-step workflow 3 - Serverless API 4 - Scheduled task 5 - Standalone function 6 - Data processing 7 - Infrastructure event management 8 - Machine Learning Template: 1 Use the most popular runtime and package type? (Nodejs and zip) [y/N]: N Which runtime would you like to use? 1 - dotnet5.0 2 - dotnetcore3.1 3 - dotnetcore2.1 4 - go1.x 5 - java11 6 - java8.al2 7 - java8 8 - nodejs14.x 9 - nodejs12.x 10 - nodejs10.x 11 - python3.9 12 - python3.8 13 - python3.7 14 - python3.6 15 - python2.7 16 - ruby2.7 17 - ruby2.5 Runtime: 12 What package type would you like to use? 1 - Zip 2 - Image Package type: 1 Based on your selections, the only dependency manager available is pip. We will proceed copying the template using pip. Project name [sam-app]: ----------------------- Generating application: ----------------------- Name: sam-app Runtime: python3.8 Architectures: x86_64 Dependency Manager: pip Application Template: hello-world Output Directory: . Next steps can be found in the README file at ./sam-app/README.md Commands you can use next ========================= [*] Create pipeline: cd sam-app && sam pipeline init --bootstrap [*] Test Function in the Cloud: sam sync --stack-name {stack-name} --watch SAM テンプレートの検証 (sam validate) sam validate コマンドで、 SAM テンプレートが正しく CloudFormation の文法に変換できるか検証できる。 SAM テンプレートの変換に失敗した場合、エラーが出力される。 bash // 正しい場合 $ sam validate --template template.yaml 2022-01-08 23:37:06 Loading policies from IAM... 2022-01-08 23:37:17 Finished loading policies from IAM. /Users/glaciermelt/workspace/sam-black-belt/sam-app/template.yaml is a valid SAM Template 2022-01-08 23:37:18 There are unpublished metrics. Please make sure you call publish after you record all metrics. 2022-01-08 23:37:18 There are unpublished metrics. Please make sure you call publish after you record all metrics. // エラーがある場合 $ sam validate --template template.yaml 2022-01-08 23:38:26 Loading policies from IAM... 2022-01-08 23:38:36 Finished loading policies from IAM. Template provided at '.../sam-app/template.yaml' was invalid SAM Template. Error: [InvalidResourceException('HelloWorldFunction', 'property Hoge not defined for resource of type AWS::Serverless::Function')] ('HelloWorldFunction', 'property Hoge not defined for resource of type AWS::Serverless::Function') 2022-01-08 23:38:37 There are unpublished metrics. Please make sure you call publish after you record all metrics. 2022-01-08 23:38:37 There are unpublished metrics. Please make sure you call publish after you record all metrics. Lambda 関数のビルド (sam build) sam build コマンドでアプリケーションをビルドできる。 ビルドされたアプリケーションは .aws-sam/build ディレクトリ内に作成される。 --use-container オプションをつけた場合、 Lambda の動作環境と同等のコンテナ内でビルドすることができるため、ネイティブ モジュールのビルドに役立つ。 bash $ sam build --template template.yaml Building codeuri: /.../sam-app/hello_world runtime: python3.9 metadata: {} architecture: x86_64 functions: ['HelloWorldFunction'] Running PythonPipBuilder:ResolveDependencies Running PythonPipBuilder:CopySource Build Succeeded Built Artifacts : .aws-sam/build Built Template : .aws-sam/build/template.yaml Commands you can use next ========================= [*] Invoke Function: sam local invoke [*] Test Function in the Cloud: sam sync --stack-name {stack-name} --watch [*] Deploy: sam deploy --guided Lambda 関数のローカル実行 (sam local invoke) sam local invoke コマンドで、 Lambda ランタイムが動作する Docker コンテナの内部で、ビルドした Lambda 関数を動かすことができる。 --event オプションに、 Lambda 関数に入力として渡す JSON ファイル名を指定する。 bash $ sam local invoke --event events/event.json Invoking app.lambda_handler (python3.9) Image was not found. Removing rapid images for repo public.ecr.aws/sam/emulation-python3.9 Building image........................................................................................................................ ...................................................................................................................................... ...................................................................................................................................... ........................................................................ Skip pulling image and use local one: public.ecr.aws/sam/emulation-python3.9:rapid-1.37.0-x86_64. Mounting /.../sam-app/.aws-sam/build/HelloWorldFunction as /var/task:ro,delegated inside runtime container {"statusCode": 200, "body": "{\"message\": \"hello world\"}"}END RequestId: 4972c8dd-8af5-4e18-a823-3a19db486f39 REPORT RequestId: 4972c8dd-8af5-4e18-a823-3a19db486f39 Init Duration: 0.90 ms Duration: 156.00 ms Billed Duration: 156 ms Memory Size: 128 MB Max Memory Used: 128 MB テスト用イベントの生成 (sam local generate-event) sam local generate-event コマンドで、Lambda 関数の入力に使うテスト用 JSON データを、サービスごとに出力できる。 ローカルエンドポイントの作成 (sam local start-lambda) sam local start-lambda コマンドで、 AWS CLI や SDK など外部から、ローカルの Lambda 関数を実行するエンドポイントを立ち上げることができる。 ユースケースとしては、外部ツールと連携してテストを行いたい場合などに利用する。 API エンドポイントの作成 (sam local start-api) sam local start-api コマンドで、 API Gateway をイベントソースにして起動する Lambda 関数を試すことができる。 SAM テンプレートで定義している内容をもとに、関数へアクセスするパスが生成される。 パッケージングとデプロイ (sam package / sam deploy) sam package コマンドで、アプリケーションを ZIP 形式にパッケージング。 S3 にアプリケーションをアップロードする。 (aws cloudformation package コマンドと同様の動作) sam deploy コマンドで CloudFormation へデプロイ (aws cloudformation deploy コマンドと同様の動作)。 デプロイした関数のログ確認 (sam logs) sam logs コマンドを使うと、 AWS にデプロイした Lambda 関数のログを出力することができる。 --stack-name オプションに、デプロイした CloudFormation のスタック名を指定。 --name オプションの指定には SAM テンプレートの中で定義した Lambda 関数の論理 ID を指定する。 完成したアプリケーションの保管 (sam publish) SAM テンプレートに Metadata というセクションを入れる。 Author に作者、Description にアプリケーションの説明、 Name にアプリケーション名を指定しておく。 sam publish コマンドで Serverless Application Repository へアプリケーションを発行する。 --region に発行先のリージョンを、 -template にパッケージング後の SAM テンプレートを、 --semantic-version に発行するアプリケーションのバージョンを指定する。 Serverless Application Repository にアプリケーションが保管され、 Lambda のコンソールや CLI から再びデプロイできるようになる。 SAM CLI のインストール SAM CLI は Linux, Mac, Windows に対応。 事前に AWS Command Line Interface (AWS CLI) のインストールが必要 テストのために Lambda 関数をローカルで実行する場合、事前に Docker のインストールが必要 SAM CLI は最新版のインストールを推奨 SAM の最新の文法への対応などが入るため その他考慮事項 SAM と CI/CD パイプライン Source: CodeCommit Build: CodeBuild Deploy CloudFormation AWS CodeStar を使うことで、 CI/CD パイプラインを自動作成可能。 SAM のベストプラクティス 一つのサーバーレス アプリケーションを構築するリソースの中で、ライフサイクルが同じものは、同じテンプレートにまとめる ライフサイクルが同じ = リソースが更新・削除されるタイミングが同じであること Lambda と、その呼び出し元となるリソース (S3 や API Gateway 等) は、同じテンプレートにまとめる AWS SAM では、既存の API Gateway や S3 をトリガーとして Lambda 関数を呼び出すことをサポートしていない Dev / Test / Prod といった環境は、 CloudFormation スタックで分離する AWS SAM では複数の API Gateway のステージを利用することができない ただし、テンプレートとしては共通化し、パラメータで環境を切り替えられるように Lambda の実装内容や API Gateway の API 定義を更新する際はカナリア リリース (段階的デプロイ) を活用する テストや CI/CD の仕組みが完全でも見落としは有り得る。万が一に備え、商用環境への適用は段階的に行い、エラーが発生しないか監視する 汎用的に利用するサーバーレス アプリケーションは、 Serverless Application Repository を使い、他の AWS アカウントへ共有する アプリケーションとしてパッケージングされた資材を、あらかじめ対象者に対してそのまま配布できるので、責任分界点が明確化できる AWS SAM CLI を使い、ローカル環境でビルド、デバッグ、 SAM テンプレート検証を行う Lambda を再現した Docker コンテナが立ち上がるので、本番同等の環境で検証ができる
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

AWS サービスを操作する方法&IAMロールの利用について

AWSを操作する方法は下記三つあります 各IAMユーザは「アクセスキー/シークレットアクセスキー」のペアを作成.保持することができます。 ただし、「アクセスキー/シークレットアクセスキー」はAWS CLI,AWS SDKの認証情報として 利用することができますが。 認証情報の更新問題や流出の危険性などから推奨されていません。 その代わりに、IAMロールの利用が推奨されています。 IAMロールには、IAMユーザと同様に、 AWSの各種リソースに対するアクセス可否を設定できます。 IAMロールは、EC2インスタンスなどに割り当てることができ、 IAMロールを割り当てられたEC2インスタンス上のプログラムは 「アクセスキー/シークレットアクセスキー」がなくても IAMロールに許可されているAWSのリソースにアクセスできます。 ただし IAMロールの利用はAWSリソース間しか利用できません。 例: ①:EC2からS3 ②:LambdaからDynamoDB ローカル端末からS3へアクセスしたい場合は利用できません。 IAMロールの利用例は下記も参照できます。 https://youtu.be/wTd4RBO98aI 今回のシェアは以上になります。   
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

超簡単!Dockerを使ってサクッとAWS ECR + AppRunnerにPython + Flask環境

タイトルは昔の記事をパクりました。以下の記事でプロニチをGCP(Cloud Run)からAWS(App Runner)に移行するにあたりApp Runner周りをまとめてみました。所々、固有名詞でpronichiとなっていますが私のプロジェクト名になるので参考にする方は任意で変更してください。 事前準備 AWS Command Line 導入 DockerイメージとFlask作成 AWS Command Line 導入 既に導入済だと思いますが念の為記載 AWS Command Line をインストール・更新 $ curl "https://awscli.amazonaws.com/AWSCLIV2.pkg" -o "AWSCLIV2.pkg" $ sudo installer -pkg AWSCLIV2.pkg -target / AWS Command Line 初期設定 予めIAMでユーザー作成しキーを取得してください。 $ aws configure --profile pronichi AWS Access Key ID [None]: AWS Secret Access Key [None]: Default region name [None]: ap-northeast-1 Default output format [None]: json Dockerfileイメージ作成、起動 DockerfileとFlask関連は以下を参照くださいませ。 $ docker build -t pronichi . $ docker run --name pronichi -p 8080:8080 -v ~/Sites/pronichi/:/app -it --rm pronichi Amazon ECR リポジトリ作成、プッシュ ECRリポジトリ作成 $ aws ecr create-repository \ --repository-name pronichi \ --image-scanning-configuration scanOnPush=true \ --region ap-northeast-1 \ --profile pronichi 認証 $ aws ecr get-login-password --region ap-northeast-1 --profile pronichi | docker login --username AWS --password-stdin 758610380088.dkr.ecr.ap-northeast-1.amazonaws.com Login Succeeded リポジトリにイメージをプッシュ $ docker tag pronichi:latest 758610380088.dkr.ecr.ap-northeast-1.amazonaws.com/pronichi:latest $ docker push 758610380088.dkr.ecr.ap-northeast-1.amazonaws.com/pronichi:latest AppRunner作成・デプロイ 本当はCUIでやりたかったが、GUIで一旦 アップロードしたコンテナイメージ選択、他はデフォルト 確認画面にて「作成とデプロイ」ボタンを押すと初回のデプロイが開始 デプロイ完了はログで確認 デプロイは初回は6分程度、2回目は5分程度かかっていた GCPのCloud Runだともっと早い気がしたが正確に測っていないのでまた計測したいと思う。 デフォルトドメインにアクセスするとページが表示されることを確認 $ curl https://p6drxqx7ku.ap-northeast-1.awsapprunner.com/ TEST 以上
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【備忘録】サーバーレスなお問い合わせフォームを実装してみた

背景 友達が申し込みフォームを利用してイベントの参加を募っていたが、申し込みの後、アドレスに返事がなくて文句言われてるのを聞いて、自動返信も大切なんだなぁと思い、作ろうと思いました。 サーバーレスなお問い合わせフォームって何? AWS上のサービスを利用し、サーバーレス(サーバーを構築しないで)実装してみました。 AWSで言うとEC2を利用せずに、アプリを構築したイメージです。 Webサーバーを「S3」と「Lambda」、「API Gateway」、メールサーバーを「SES」で設定をしました。 やり方 下記サイトを見たらできました。 ネットの海は宝物庫 S3 静的ウェブサイトにサーバーレスなお問い合わせフォームを実装してみた(Amazon SES + AWS Lambda + API Gateway) https://dev.classmethod.jp/articles/serverless-mailform-s3-website-hosting/ 筆者が作ってみたサイト http://portfolio-regards.s3-website-ap-northeast-1.amazonaws.com 終わりに サーバーを借りることなく、サービスが公開できる時代になったんですね〜
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

SQLServerのバックアップをAmazon S3に保存する

はじめに こんにちは、山田です。今年の目標として、学んだこと実装したことを記事に書いていきたいと思います。 今回は、現在関わらせていただいている案件でSQLServerのバックアップをS3に保存を実装したので、その手順について記載していこうと思います。 よろしくお願いいたします。 構成図 今回使用するAWSリソースは下記の通りです。 AWSリソース 個数 VPC 1 Subnet 2 Internet Gateway(IGW) 1 EC2 1 RDS(SQLServer) 1 S3 1 全体構成図は下記の通りです。 ① Internet Gateway(IGW)を介して、PublicSubnetに配置しているEC2にログインする。 ②「SQL Server Management Studio」を使用して、EC2からRDSにログインする。 ③ S3にバックアップを作成するクエリを実行する。 手順 下記よりSQLServerからS3にバックアップを取得する手順を記載していきます。 前提条件 VPC、Subnet、InternetGateway、EC2、RDS、S3に関しては作成済みとする。 オプショングループの作成 ① AWS管理コンソール->RDS->オプショングループの作成->グループを作成をクリックする。 ② 以下の設定項目を設定する。 自分の場合は、「SQL Server Express Edition」を使用したので、エンジンは「sqlserver-ex」を選択しました。 オプションの追加 ① オプション名は「SQLSERVER_BACKUP_RESTORE」を選択する。 ② IAMロールは、既存のロールを選択せずに「新しいロールの作成」を選択する。 ③ S3送信先は、SQLServerのデータバックアップ保存用に作成したS3を指定する。 ④ スケジューリングは「今すぐ」を選択する。 RDSの設定変更 ① AWS管理コンソール->RDS>データベース->バックアップを保存したいSQLServerを選択->「変更」をクリック ② 追加設定の項目で、オプショングループを新しく作成したオプショングループに変更する。 SQLManagementStudioのダウンロード ① EC2にログインする。 ② 下記URLより、「SQLManagementStudio」をダウンロードする。 RDSにログイン ① 「SQLManagementStudio」を起動する。 ② 以下の画面が表示されるので、それぞれの項目を入力してログインする。 項目名 入力値 Server type Database Engine Server name RDSエンドポイント名 Authentication SQL Server Authentication Login RDS作成時に設定したマスターユーザー名 Password RDS作成時に設定したマスターパスワード クエリの実行 ① ログイン後以下の画面が表示されるので、「New Query」をクリックする。 ② クエリ文を入力して、「Execute」をクリックしてクエリを実行する。  基本的な構文は、以下の通りです。 exec msdb.dbo.rds_backup_database    @source_db_name='<db 名>',    @s3_arn_to_backup_to='arn:aws:s3:::<バケット名>/<バックアップファイル名>', @overwrite_S3_backup_file=1; ③ 指定したS3にバックアップファイルが保存されていれば完了です。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

EC2インスタンスの複製と再デプロイ

EC2インスタンスの複製方法と、その際に発生した問題と解決方法についてご紹介していきます! 初めに 何故EC2インスタンスを複製する必要があったのか? ・最初は問題なくEC2インスタンスにアプリをデプロイできたが、VPCのIPv4アドレスを/16で切ってしまっていたことで、その後サブネット作成時にIPv4アドレス選定の計算がめんどくさくなった。 →VPCのIPv4アドレスを/20で切って、サブネットを/24で切っておくと、後にサブネットを追加で作成する際にネットワークの切り分けが楽。 何故サブネットのIPv4アドレスを/24で切っておくといいのか? 簡単にいうと、サブネットマスクを/20と/24で切った場合では、別サブネットを作成する際に選べるアドレスが以下のようになります。 ・例 172.31.32.0/24 →末尾の0のみが可変できる数字になる。  つまり、別のサブネットを作成する際、172.31.32.0の32を33や34のように一つずらすだけでネットワークを切り分けることができるので計算が楽なんです! ・例 172.31.32.0/20 この場合は、選択範囲が172.31.32.0 - 172.31.47.255になります。 ※計算はこちらのサイトで簡単にできます! https://www.softel.co.jp/labs/tools/network/ と、このようにサブネットマスクを/24で切っておいた方が断然楽なので、IPv4aアドレスを割り当てし直そうということでEC2インスタンスを複製することにしました。 EC2インスタンスの複製 では早速、既存のEC2インスタンスから新規インスタンスを作成していきます。 下記の参考記事の通りに進めればOKです。 ※注意点として、新規でVPCとサブネットを作成する際、IPv4 CIDRをVPCは/20、サブネットは/24で切るようにしてください。 ELPの関連付け 次に、下記の手順で既存EC2に関連付けしていたELPを解除して新規EC2に関連付けさせます。 ※ELPを解除しないまま既存EC2インスタンスを停止してしまうと課金が適用されてしまうので注意。 1.既存EC2インスタンスとELPを解除し、インスタンス停止 下記記事に手順が記載されていますので参考にしてください。 解除ができたら、既存EC2を停止してください。 2.インターネットゲートウェイをアタッチ このままELPを新規EC2に関連つけさせてもエラーになります。 理由は、現在のままだとインタネットゲートウェイがアタッチされているのは既存EC2で使用していたVPCだからです。 なので、現在のVPCをデタッチして新規で作成したVPCにアタッチしましょう! アタッチできたらELPを新規EC2に関連付けさせてください。 ssh接続の設定 このままだとターミナルからssh接続した時にエラーが出てしまいます。 なので、下記の設定をしていきます。 1.サブネットにルーティング追加 新規インスタンスのサブネット画面、「ルートテーブルの関連付けを編集」からインターネットゲートウェイへのルートを追加します。 2.一旦ssh接続確認 試しにssh接続してみると下記のようにエラーが発生し、もう一つのコマンドだと接続できます。 このエラーは、同じFQDNで別のマシンに差し替わったので、なりすましかもしれないよ!という意味です。 known_hostsというファイルに残っている履歴を削除してあげることで、エラーが出たコマンドでも接続できるようになります。 .ssh $ ssh -i "???????-????.pem" ec2-user@ec2-35-76-86-77.ap-northeast-1.compute.amazonaws.com @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @ WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED! @ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY! Someone could be eavesdropping on you right now (man-in-the-middle attack)! It is also possible that a host key has just been changed. The fingerprint for the ED25519 key sent by the remote host is SHA256:quupw3VFbI0PMBQiwz+w5qKL54RUDiBLO2ww+I5OYjA. Please contact your system administrator. Add correct host key in /Users/.ssh/known_hosts to get rid of this message. Offending ED25519 key in /Users/.ssh/known_hosts:9 Host key for ec2-35-76-86-77.ap-northeast-1.compute.amazonaws.com has changed and you have requested strict checking. Host key verification failed. .ssh $ ssh -i "??????-????.pem" ec2-user@35.76.86.77 Last login: Mon Dec 20 07:10:40 2021 from p3014131-ipoe.ipoe.ocn.ne.jp __| __|_ ) _| ( / Amazon Linux 2 AMI ___|\___|___| https://aws.amazon.com/amazon-linux-2/ [ec2-user@ip-172-31-32-183 ~]$ 3.known_hostsファイルの履歴削除 エラーを見ると、hostsの9行目が指摘されているので、known_hostsの中身を確認して下記コマンドで履歴を削除します。 ※ここに関しては人によって違うかと思うので、ご自身の情報に当てはめて対処してください。 ssh-keygen -R ec2-35-76-86-77.ap-northeast-1.compute.amazonaws.com これで再度ssh接続すると先ほどのコマンドで接続できることがわかります! アプリ起動 では早速、独自ドメイン、又はELPからアプリの起動確認をしてみましょう! そうすると、あれ?404エラーが出ましたね。。。 404ということは、サーバーは問題なく動作しているので、OS側の設定が何処かおかしいのか? ということで下記のように調査します。 1.curlコマンドでアクセス確認。 先ずは、ターミナルからssh接続し、curlで自分自身にアクセスしてみます。 ec2-user@ip-172-31-32-183 ~]$ curl 127.0.0.1 <html> <head><title>404 Not Found</title></head> <body> <center><h1>404 Not Found</h1></center> <hr><center>nginx/1.20.0</center> </body> </html> [ec2-user@ip-172-31-32-183 ~]$ 404が返ってきましたね。 2.ログ確認 /log/php-fpm/error.logからログの確認をします。 エラーが吐かれてますね! [root@ip-172-31-32-183 php-fpm]# tail error.log [04-Jan-2022 15:12:41] WARNING: [pool www] ACL set, listen.owner = 'nginx' is ignored [04-Jan-2022 15:12:41] WARNING: [pool www] ACL set, listen.group = 'nginx' is ignored [04-Jan-2022 15:12:41] NOTICE: fpm is running, pid 26788 [04-Jan-2022 15:12:41] NOTICE: ready to handle connections [04-Jan-2022 15:12:41] NOTICE: systemd monitor interval set to 10000ms 3.対処 WARNING: [pool www] ACL set, listen.owner = 'nginx' is ignoredで検索してみて、記事を見つけたので参考に対処しましょう。 /etc/php-fpm.d/www.confの下記の箇所をコメントアウトします。 [root@ip-172-31-32-183 php-fpm.d]# vi /etc/php-fpm.d/www.conf ;listen.acl_users = apache,nginx #コメントアウト 編集を終えたら、php-fpmを再起動してphp-fpmを開き、先ほどのエラーが消えていれば成功です! [root@ip-172-31-32-183 php-fpm.d]# systemctl restart php-fpm #再起動 [root@ip-172-31-32-183 php-fpm.d]# systemctl status php-fpm #起動状態確認 ● php-fpm.service - The PHP FastCGI Process Manager Loaded: loaded (/usr/lib/systemd/system/php-fpm.service; enabled; vendor preset: disabled) Active: active (running) since Thu 2022-01-06 14:00:02 UTC; 7s ago Main PID: 8215 (php-fpm) Status: "Ready to handle connections" CGroup: /system.slice/php-fpm.service ├─8215 php-fpm: master process (/etc/php-fpm.conf) ├─8216 php-fpm: pool www ├─8217 php-fpm: pool www ├─8218 php-fpm: pool www ├─8219 php-fpm: pool www └─8220 php-fpm: pool www Jan 06 14:00:02 ip-172-31-32-183.ap-northeast-1.compute.internal systemd[1]: Starting The... Jan 06 14:00:02 ip-172-31-32-183.ap-northeast-1.compute.internal systemd[1]: Started The ... Hint: Some lines were ellipsized, use -l to show in full. [root@ip-172-31-32-183 php-fpm.d]# tail /var/log/php-fpm/error.log #ログ確認 [04-Jan-2022 15:12:41] WARNING: [pool www] ACL set, listen.owner = 'nginx' is ignored [04-Jan-2022 15:12:41] WARNING: [pool www] ACL set, listen.group = 'nginx' is ignored [04-Jan-2022 15:12:41] NOTICE: fpm is running, pid 26788 [04-Jan-2022 15:12:41] NOTICE: ready to handle connections [04-Jan-2022 15:12:41] NOTICE: systemd monitor interval set to 10000ms [06-Jan-2022 14:00:01] NOTICE: Terminating ... [06-Jan-2022 14:00:02] NOTICE: exiting, bye-bye! [06-Jan-2022 14:00:02] NOTICE: fpm is running, pid 8215 [06-Jan-2022 14:00:02] NOTICE: ready to handle connections [06-Jan-2022 14:00:02] NOTICE: systemd monitor interval set to 10000ms おっと、まだエラーが出てますね。。。。 4.laravelのログ確認 一旦laravelの方のログを見てみます。 [root@ip-172-31-32-183 ~]# cd /var/www/laravel-zaikokanri/backend/storage/logs [root@ip-172-31-32-183 logs]# ls root@ip-172-31-32-183 logs]# あれ?あるはずのlaravel.logが無い?! となると、恐らくLaravelのアプリ自体が正常に起動できていなく、ログが出力されてない状態のようです! EC2の複製をオンラインのまま行ったとすると、もしかしたら変なセッションが残っていてそれが邪魔してる可能性があるので、一度OSを再起動してみます。 [root@ip-172-31-32-183 ~]# shutdown -r now #再起動 Connection to ec2-35-76-86-77.ap-northeast-1.compute.amazonaws.com closed by remote host. Connection to ec2-35-76-86-77.ap-northeast-1.compute.amazonaws.com closed. .ssh $ ssh -i "sample-key.pem" ec2-user@ec2-35-76-86-77.ap-northeast-1.compute.amazonaws.com #接続タイムアウトで失敗 ssh: connect to host ec2-35-76-86-77.ap-northeast-1.compute.amazonaws.com port 22: Operation timed out .ssh $ ssh -i "sample-key.pem" ec2-user@35.76.86.77 #接続 Last login: Fri Jan 7 10:11:02 2022 from p3014131-ipoe.ipoe.ocn.ne.jp __| __|_ ) _| ( / Amazon Linux 2 AMI ___|\___|___| https://aws.amazon.com/amazon-linux-2/ 6 package(s) needed for security, out of 16 available Run "sudo yum update" to apply all updates. [ec2-user@ip-172-31-32-183 ~]$ curl 127.0.0.1 #アクセス確認 <html> <head><title>404 Not Found</title></head> <body> <center><h1>404 Not Found</h1></center> <hr><center>nginx/1.20.0</center> </body> </html> [ec2-user@ip-172-31-32-183 ~]$ sudo su - #ルートユーザーに変更 最終ログイン: 2022/01/07 (金) 10:11:07 UTC日時 pts/0 [root@ip-172-31-32-183 ~]# cd /var/www/laravel-zaikokanri/backend/storage/logs #logの場所まで移動 [root@ip-172-31-32-183 logs]# ls #laravel.logの確認 [root@ip-172-31-32-183 logs]# #存在してない 再起動でもダメそうですね。。。 ここでメンターに相談。 キャッシュクリアやパーミッション、リンク等を一つずつ調査してもいいけど、laravelのプロジェクトを再デプロイしてしまった方が早いかもしれないとアドバイス頂きました! ということで、laravelプロジェクトの再デプロイを進めていきます。 初めは、え?またインスタンスとか作り直すの?と思ったのですが、そんなことはする必要はなく、プロジェクトディレクトリを際クローンするだけなのでもう一踏ん張り頑張りましょう! 再デプロイ 1.laravelプロジェクトをクローン 先ずは既存プロジェクトをコピー用で用意したディレクトリに移動させ、その後にgithubからプロジェクトをクローンしてきます。 ※ここで既存プロジェクトは必要ないから削除しようとしてしまうところですが、新規でクローンしてきたプロジェクトのDB周りの設定を行う際に、既存プロジェクトのコードがみれた方が便利なので、既存プロジェクトは削除せず移動させるようにしましょう。 [root@ip-172-31-32-183 www]# mkdir copy-laravel-zaikokanri #既存プロジェクトの移動先を作成 [root@ip-172-31-32-183 www]# ls #作成されたか確認 cgi-bin copy-laravel-zaikokanri html laravel-zaikokanri [root@ip-172-31-32-183 www]# mv -v laravel-zaikokanri/ copy-laravel-zaikokanri/ #既存プロジェクトを移動 -vオプションで移動過程が表示されます。 ‘laravel-zaikokanri/’ -> ‘copy-laravel-zaikokanri/laravel-zaikokanri’ [root@ip-172-31-32-183 www]# ls #ちゃんと移動できたか確認 cgi-bin copy-laravel-zaikokanri html [root@ip-172-31-32-183 www]# cd copy-laravel-zaikokanri [root@ip-172-31-32-183 copy-laravel-zaikokanri]# ls laravel-zaikokanri [root@ip-172-31-32-183 copy-laravel-zaikokanri]# cd ../ #プロジェクトクローン先に移動 [root@ip-172-31-32-183 www]# git clone https://github.com/?????/?????.git #githubからプロジェクトをクローン Cloning into 'laravel-zaikokanri'... remote: Enumerating objects: 2073, done. remote: Counting objects: 100% (2073/2073), done. remote: Compressing objects: 100% (773/773), done. remote: Total 2073 (delta 1471), reused 1823 (delta 1259), pack-reused 0 Receiving objects: 100% (2073/2073), 963.78 KiB | 6.06 MiB/s, done. Resolving deltas: 100% (1471/1471), done. これでクローンが完了しました。 これだけではDB関係の設定ができてないのでアプリは起動できません。 2.DB設定 ①.env作成 .env.exampleをコピーして.envを作成します。 [root@ip-172-31-32-183 backend]# cp .env.example .env ②アプリケーションキーの作成 アプリケーションキーを作成しますが、このまま実行してもエラーになりますが、 composerをインストールすれば解決できます! [root@ip-172-31-32-183 backend]# php artisan key:generate PHP Warning: require(/var/www/laravel-zaikokanri/backend/vendor/autoload.php): failed to open stream: No such file or directory in /var/www/laravel-zaikokanri/backend/artisan on line 18 PHP Fatal error: require(): Failed opening required '/var/www/laravel-zaikokanri/backend/vendor/autoload.php' (include_path='.:/usr/share/pear:/usr/share/php') in /var/www/laravel-zaikokanri/backend/artisan on line 18 [root@ip-172-31-32-183 backend]# composer install Package manifest generated successfully. 80 packages you are using are looking for funding. Use the `composer fund` command to find out more! [root@ip-172-31-32-183 backend]# php artisan key:generate #キー作成 Application key set successfully. [root@ip-172-31-45-44 backend]# cat .env #キーの確認 APP_NAME=Laravel APP_ENV=local APP_KEY=??????????????????????????= #ここで問題なく設定されてますね! APP_DEBUG=true APP_URL=http://localhost ③.env、database.phpの設定 ・.envの設定 #各RDSの設定内容を入力 DB_CONNECTION=mysql DB_HOST=database-1.??????????.ap-northeast-1.rds.amazonaws.com DB_PORT=3306 DB_DATABASE=laravel_zaiko DB_USERNAME=admin DB_PASSWORD=????? #マスターパスワード ・/config/database.phpの設定 env()で囲んである箇所は.envの内容を読み込むようになっていますが、第二引数に直接書き込んでも大丈夫です。 また、RDSに登録したDBの内容はコンソールのRDS画面でDBを選択すれば確認ができます。 'default' => env('DB_CONNECTION', 'mysql'), 'mysql' => [ 'driver' => 'mysql', 'url' => env('DATABASE_URL'), 'host' => env('DB_HOST', 'database-1.???????????.ap-northeast-1.rds.amazonaws.com'), 'port' => env('DB_PORT', '3306'), 'database' => env('DB_DATABASE', 'laravel_zaiko'), 'username' => env('DB_USERNAME', 'admin'), 'password' => env('DB_PASSWORD', '??????'), 'unix_socket' => env('DB_SOCKET', ''), 'charset' => 'utf8mb4', 'collation' => 'utf8mb4_unicode_ci', 'prefix' => '', 'prefix_indexes' => true, 'strict' => true, 'engine' => null, 'options' => extension_loaded('pdo_mysql') ? array_filter([ PDO::MYSQL_ATTR_SSL_CA => env('MYSQL_ATTR_SSL_CA'), ]) : [], ], 設定が完了したらmigrateしてDBが作成されているか確認しましょう。 前回一度migrateしてるので、今回はリフレッシュします。 [root@ip-172-31-45-44 backend]# php artisan migrate:refresh Migration table created successfully. ・DBが作成されているか確認 #mysqlログインコマンド $ mysql -h database-1.????????.ap-northeast-1.rds.amazonaws.com -P 3306 -u admin -p また、ログインコマンド実行後にパスワードの入力を求められますが、そちらは自身で設定したマスターパスワードになります。 ※もしマスターパスワードを忘れた場合はこちらの手順で簡単にパスワードを変更できます。 [ec2-user@ip-172-31-45-44 ~]$ mysql -h database-1.????????.ap-northeast-1.rds.amazonaws.com -P 3306 -u admin -p Enter password: Welcome to the MariaDB monitor. Commands end with ; or \g. Your MySQL connection id is 24 Server version: 8.0.23 Source distribution Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others. Type 'help;' or '\h' for help. Type '\c' to clear the current input statement. MySQL [(none)]> show databases; #DB確認 +--------------------+ | Database | +--------------------+ | information_schema | | laravel_zaiko | | mysql | | performance_schema | | sys | +--------------------+ 5 rows in set (0.00 sec) 無事作成できてますね! 3.アプリ起動確認 ここで、アプリへアクセスしてみると下記のようにエラーが発生します。 laravel failed to open stream: Permission denied これは、権限の問題でログが書き込みできないというエラーになります。 storageディレクトリの権限を変更してあげましょう。 これで問題なくアプリが起動するようになるかと思います。 [root@ip-172-31-32-183 backend]# chmod -R 777 storage [root@ip-172-31-32-183 backend]# client_loop: send disconnect: Broken pipe 再度アプリへアクセスしてみると、今度は無事に起動できました! 4.シンボリックリンク作成 では、最後にシンボリックリンクの作成やS3バケットの設定など、アプリ動作に必要な準備をしていきます! [root@ip-172-31-45-44 backend]# php artisan storage:link The [/var/www/laravel-zaikokanri/backend/public/storage] link has been connected to [/var/www/laravel-zaikokanri/backend/storage/app/public]. The links have been created. 5.S3バケットの設定 画像アップロード機能を使えるようにする為に.envへS3の設定を追加していきます。 [root@ip-172-31-45-44 backend]# vi .env AWS_ACCESS_KEY_ID=??????????????? AWS_SECRET_ACCESS_KEY=???????????????? AWS_DEFAULT_REGION=ap-northeast-1 AWS_BUCKET=zaikokanri 設定内容が入力できたら、.envの修正内容を反映させる為にキャッシュをクリアします。 [root@ip-172-31-32-183 backend]# php artisan cache:clear Application cache cleared! 6.ログインアカウント作成 もし、管理者やダミーユーザーなどのユーザーアカウントをシードに用意してる場合は、シードを実行しておきましょう! [root@ip-172-31-45-44 backend]# php artisan db:seed --class=UserSeeder Database seeding completed successfully. 最後に これでEC2インスタンスの複製と再デプロイは終了になります! 結構長くなってしまいましたが、是非少しでも参考になればと思います!
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

MacからのSSH接続でWARNING: UNPROTECTED PRIVATE KEY FILE!と表記されてEC2にログインできない!

エラー内容 AWSで新しくEC2、キーペアを作成。 仮想サーバにSSHでアクセス、ログインしようとするが、 ssh -i ~.pem ec2-user@~(EC2のIPアドレス) 以下のエラーが表示された。 @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @ WARNING: UNPROTECTED PRIVATE KEY FILE! @ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ Permissions 0644 for '~.pem' are too open. It is required that your private key files are NOT accessible by others. This private key will be ignored. Load key "~.pem": bad permissions ec2-user@~(EC2のIPアドレス): Permission denied (publickey,gssapi-keyex,gssapi-with-mic). 作成したキーファイルは使用できない? Macからだと権限の問題でエラーになると聞いたような... 原因 Macでダウンロードしたキーファイルを使い、SSHしようとするとはじかれます。 ファイルの権限が緩すぎるのが原因。 秘密鍵は、他のユーザからアクセスできる権限では使用できないらしい。 つまり、秘密鍵が安全でない場合に発生するエラー。 所有者のみ読み書きできる権限にする必要がある。 対処方法 ①lsコマンドでキーファイルの権限(パーミッション)を確認してみる。 ls -l -rw-r--r--@ 1 ~ ~ 1700 1 9 14:08 ~.pem キーファイルの権限が644になっていることが確認できた。 所有者以外も読み込み可になっている... そうなると、設定すべき権限は所有者のみ読み書き可能。 ②権限変更なのでchmodコマンドを使用。 chmod 600 ~.pem ③権限を変更することで、キーファイルを使用し、SSH接続が可能になります。 ssh -i ~.pem ec2-user@~(EC2のIPアドレス) ④これにて接続可能になりました! __| __|_ ) _| ( / Amazon Linux 2 AMI ___|\___|___| 参考
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【AWS】EFSの構築 + EC2からのアクセス確認まで

きっかけ Lambdaで/tmp上限の500MBを超えるファイルを扱う必要があり、その動作確認のため。 構築Step SSH可能なVPC,EC2の構築 EFS構築 EC2からEFSへのアクセス準備、動作確認 1. SSH可能なVPC,EC2の構築 適当なVPCを作成 VPCでDNSホスト名設定を有効化 適当なサブネットを作成 インターネットゲートウェイを作成 VPCにIGWをアタッチ VPCのメインルートテーブルにigwへのルートを追加 EC2を作成したサブネット内に作成、SGはSSHを許可 EC2にIAMロールを紐付け AmazonElasticFileSystemClientReadWriteAccessポリシーが含まれているロール EC2へSSH接続ができることを確認 同じ設定で別インスタンスを構築 2. EFS構築 EFSに紐づけるSGを作成 インバウンドルールに タイプ:NFSでソースにEC2のSGを設定 EFSの作成ウィザードでVPC設定をし、カスタマイズで他設定を行う NW設定でマウントターゲットのセキュリティグループを先ほど作成したSGに設定、EFSを作成する 3. EC2からEFSへのアクセス準備、動作確認(以下EC2へSSHで接続した状態) yum updateの実施 botocoreのインストール amazon-efs-utilsの内部で使っている様子 amazon-efs-utilsのインストール amazon-efs-utilsのインストール正常完了画面 efsフォルダを作成、マウントを実施 同じ設定で別インスタンスを設定 動作確認: ファイルをマウントしたefsディレクトリ内に作成、別インスタンスで作成されていることを確認 参考URL
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

AthenaとQuicksightでログ分析する時のつまづきと解消

Apache HTTPサーバーのアクセスログをS3に配置してAthenaでテーブル作成、QuickSightで可視化をしようと試み、つまづいたポイントと解消方法を恥ずかしげもなくメモとして残します。 サンプルのログ 下記のようなログをサンプルに試みました。 xx.xx.xx.xx - - [dd/Sep/202x:08:00:31] "POST /category.screen?categoryId=STRATEGY&JSESSIONID=xxxxx HTTP 1.1" 200 2571 "http://www.samplesample.com" "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.2.28) Gecko/20120306 YFF3 Firefox/3.6.28 ( .NET CLR 3.5.30729; .NET4.0C)" 830 データの構造が知りたい まずApacheのログには何が書かれているのだろうか、データを分析しようとすると対象となるデータの構造を抑えなければなりません。何が書かれているかは最終的にはmod_log_configを確認するのが確実です。 https://httpd.apache.org/docs/2.2/ja/mod/mod_log_config.html 下記のサイトでもやさしく勉強になります。 https://beyondjapan.com/blog/2020/02/access-log/ 最終的にはLogstashのGrokのパターンも理解に役立ちます。 https://github.com/elastic/logstash/blob/v1.4.2/patterns/grok-patterns 今回のケースでは一番最後のこちらです。 COMMONAPACHELOG %{IPORHOST:clientip} %{USER:ident} %{USER:auth} \[%{HTTPDATE:timestamp}\] "(?:%{WORD:verb} %{NOTSPACE:request}(?: HTTP/%{NUMBER:httpversion})?|%{DATA:rawrequest})" %{NUMBER:response} (?:%{NUMBER:bytes}|-) SerDeとは何だ シリアライザー、デジタライザーをSerDeと訳しています。ログがどういうフォーマット、区切りで作られているのかを識別させるために使います。 https://docs.aws.amazon.com/ja_jp/athena/latest/ug/serde-about.html 今回は構造化されていないログの分析なので、Grok SerDeというものを使いました。 https://docs.aws.amazon.com/ja_jp/athena/latest/ug/grok-serde.html 上記リンク先にもありますが、Grokで定義されているパターンは下記です。パターンが定義されているので便利という代物です。区切り文字だけでしたら、その他の認識すべき文字列をカスタムで定義しなければなりません。 https://github.com/elastic/logstash/blob/v1.4.2/patterns/grok-patterns Athenaで認識したログの区切り位置が違う Grokでの定義を見ながら、SERDEPROPERTIESをDATAのパターンを多用しながら、定義してみると悲しいかな区切り位置が違って、思っていたログの見え方がされません。""のような区切り部分は、QUOTEDSTRINGを使います。 Athenaで日時を抽出したい AWSのApacheログをクエリするというページで、アクセス日時をStringでガツッと宣言しています。 https://docs.aws.amazon.com/ja_jp/athena/latest/ug/querying-apache-logs.html (略) CREATE EXTERNAL TABLE apache_logs( request_received_time string, (略) ROW FORMAT SERDE 'com.amazonaws.glue.serde.GrokSerDe' WITH SERDEPROPERTIES ( 'input.format'=' (略) {GREEDYDATA:request_received_time} これではQuickSightで日毎にデータを見たいというときに不便です。本当はログ出力をtimestamp型で認識できるフォーマットにして欲しいところではありますが、そんなときには下記でデータを分割してしまおうというアプローチもあります。無理矢理です。 CREATE EXTERNAL TABLE apache_logs_sample( client_ip string, client_id string, user_id string, request_date string, request_month string, request_year string, request_time string, client_request string, server_status string, returned_obj_size string, referer string, user_agent string, process_id string ) ROW FORMAT SERDE 'com.amazonaws.glue.serde.GrokSerDe' WITH SERDEPROPERTIES ( 'input.format' = '^%{IPV4:client_ip} %{DATA:client_id} %{USERNAME:user_id} \\[%{MONTHDAY:request_day}/%{MONTH:request_month}/%{YEAR:request_year}:%{TIME:request_time}\\] %{QUOTEDSTRING:client_request} %{DATA:server_status} %{DATA: returned_obj_size} %{DATA: referer} %{QUOTEDSTRING: user_agent} %{DATA: process_id}$' ) STORED AS INPUTFORMAT 'org.apache.hadoop.mapred.TextInputFormat' OUTPUTFORMAT 'org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat' LOCATION 's3://location/'; QuickSightで「テーブルが見つかりません」 QuickSightでデータソースとしてAthenaを選択します。しかしながらお望みのテーブルが表示されず「テーブルが見つかりません(Table not found)」なんて悲しい表示に出会ってしまうと、「なんでや」と心の呟きが止まりません。しかし忘れないで。QuickSightでも自分がどこのRegionにいるかを。S3にデータを配置したRegionにいることを確認しましょう。 参考:https://stackoverflow.com/questions/53272205/aws-quicksight-cant-see-athena-db 私の場合には初期にQuickSightを米国バージニア北部で作っていたため下記となっていました。 ここを適切なRegionを選択するとテーブルが見つかります。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

EC2起動時に、自身も監視するCloud Watch Alarmを自動で作成する

What's This userdata使用で、起動時にcloudwatch alarmを作りました。 要件的には、以下 ・OSはUbuntu(AWS公式イメージ) ・自分のCPUメトリクスを監視するalarm ・アラーム名に自身のインスタンスIDを付与 ・例 ec2-i-aaaaaaa-cpu-alarm Userdata Credentials情報はベタ張りなので、もっとセキュアな方法があるかも アラーム名に自身のインスタンスIDを付与するのは、環境変数使って通しました #!/bin/bash curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip" sudo apt install unzip unzip awscliv2.zip sudo ./aws/install export InstanceId=`curl http://169.254.169.254/latest/meta-data/instance-id -w "\n"` export AWS_ACCESS_KEY_ID="XXX" export AWS_SECRET_ACCESS_KEY="XXX" export AWS_DEFAULT_REGION="XXX" aws cloudwatch put-metric-alarm --alarm-name ec2-$InstanceId-cpu-alarm --namespace AWS/EC2 --metric-name CPUUtilization --dimensions "Name=InstanceId,Value=$InstanceId" --evaluation-periods 1 --comparison-operator GreaterThanOrEqualToThreshold --period 60 --statistic Average --threshold 80 参考 https://docs.aws.amazon.com/ja_jp/cli/latest/userguide/install-cliv2-linux.html https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/using-cloudwatch-createalarm.html https://hacknote.jp/archives/43635/ 参考にさせていただきました。ありがとうございます。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

AmplifyでGraphQLを使いつつ、Lambdaを非認証ユーザーで叩く(Typescript)

概要 AWS Amplifyにて非認証ユーザーで外部のAPIを叩いて、JSONを引っ張ってくるところを作りたかったが、色々詰まったのでシェア 環境 "aws-amplify": "^4.3.12", "typescript": "~4.1.5" "vue": "^3.0.0" Amplifyの各環境を作る cmd amplify configure amplify init amplify add api amplify add function このあたりはこの辺を見れば詰まらないと思う。 ファンクション名はreadListとした。 Authを設定する ここからがポイント。 まず、認証の方法だが、非認証ユーザーでのアクセスを許可する場合は、API KeyとIAMがあるが、 API Keyは日付制限(最長365日)があるので、IAMとする。 cmd amplify add auth すると、問が出てるくので以下を選択する。 cmd Do you want to use the default authentication and security configuration? (Use arrow keys): → Manual configuration 進めると、更に問が出てくるので以下と答える。 cmd Select the authentication/authorization services that you want to use: (Use arrow keys) → User Sign-Up, Sign-In, connected with AWS IAM controls (Enables per-user Storage features for images or other content, Analytics, and more) さらに進めると、更に問が出てくるので以下と答える。 cmd ? Allow unauthenticated logins? (Provides scoped down permissions that you can control via AWS IAM) → Yes これで、認証の設定は完了。 GraphQLのスキーマを編集 次にGraphQLのスキーマを変更していく。 以下の設定とした。 schema.graphql input AMPLIFY { globalAuthRule: AuthRule = { allow: public } } # FOR TESTING ONLY! type Query { readList: String @function(name: "readList-${env}") @auth(rules: [ {allow: public, provider: iam}, ]) } ファンクションの編集 ファンクションの編集をする。 今回はファンクション名はreadListとして、コードは以下とした。 index.js exports.handler = async () => { return JSON.stringify('Hello from Lambda!'); }; ここで一旦、プッシュしておく。 cmd amplify push フロントの編集 今回はVueのサンプルページをそのまま使用した。 Home.vue <template> <div class="home"> <img alt="Vue logo" src="../assets/logo.png" /> <HelloWorld msg="Welcome to Your Vue.js + TypeScript App" /> </div> </template> <script lang="ts"> import { Options, Vue } from 'vue-class-component'; import HelloWorld from '@/components/HelloWorld.vue'; import Amplify, { API, graphqlOperation } from 'aws-amplify'; import config from '@/aws-exports'; import { readList } from '@/graphql/queries'; @Options({ components: { HelloWorld, }, }) export default class Home extends Vue { public async mounted(): Promise<void> { Amplify.configure(config); const res = await API.graphql(graphqlOperation(readList)); console.log(res); } } </script> しかし、このままだとエラーが出るため以下の対応をする。 ファイル名 aws-exports.js → aws-exports.ts に変更する。 (こちらの記事を参考にさせてもらった。ありがとうございます。) また、aws-exports.tsに以下の記載があるか確認して、ない場合は追加する。 "aws_appsync_authenticationType": "AWS_IAM" 確認 結果を確認する。 Homeページにアクセスして、コンソールを開いて確認すると readList: "\"Hello from Lambda!\" と表示されていると思う。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Minioを用いてAWSアカウントなしでS3接続(javaSDK)を確認する方法

概要 この記事では、AWSのアカウントなしでもAWS S3 接続を確認できる方法を記事にしてみました。 Minio自体は、AWS S3 と互換性があるマルチクラウドオブジェクトストレージのOSSとして知られています。 現場の業務上 S3 に対してJavaを用いて接続する必要があり自宅で無料で接続確認がしたくてminioを採用しました。 使用方法をwebで調べたのですが、出てくるのはdockerを用いて簡単に構築することができることやMinioが提供しているライブラリを用いて接続する方法しかなく、AWS SDKで接続する方法が見つからなかったので今回挑戦し成功したので記事にしてみました。 minioって何?っていう方は以下の記事や公式のサイトを見ると理解できると思います。 https://min.io/ https://dev.classmethod.jp/articles/s3-compatible-storage-minio/ aws s3って何?という方は以下の記事や公式のサイトを見ると理解できると思います。 https://aws.amazon.com/jp/s3/ https://business.ntt-east.co.jp/content/cloudsolution/column-try-43.html 必要なもの dockerDesktop eclipse aws SDK jarファイル 方法 以下の記事より、dockerDesktopよりminioの環境を構築する https://dev.classmethod.jp/articles/s3-compatible-storage-minio/ 以下のサイトを参考にソースコードを作成しました。 https://docs.min.io/docs/how-to-use-aws-sdk-for-java-with-minio-server.html package minioS3; import java.io.BufferedReader; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import com.amazonaws.AmazonClientException; import com.amazonaws.AmazonServiceException; import com.amazonaws.ClientConfiguration; import com.amazonaws.auth.AWSCredentials; import com.amazonaws.auth.AWSStaticCredentialsProvider; import com.amazonaws.auth.BasicAWSCredentials; import com.amazonaws.client.builder.AwsClientBuilder; import com.amazonaws.regions.Regions; import com.amazonaws.services.s3.AmazonS3; import com.amazonaws.services.s3.AmazonS3ClientBuilder; import com.amazonaws.services.s3.model.GetObjectRequest; import com.amazonaws.services.s3.model.PutObjectRequest; import com.amazonaws.services.s3.model.S3Object; public class Main { private static String bucketName = "testbucket"; private static String keyName = "hosts"; //指定したい自身のパソコン内のパスを記入する 今回はホストファイルを指定して簡易動作確認します。 private static String uploadFileName = "/etc/hosts"; public static void main(String[] args) throws IOException { //YOUR-ACCESSKEYID YOUR-SECRETACCESSKEYにminioに指定した値を入れる AWSCredentials credentials = new BasicAWSCredentials("YOUR-ACCESSKEYID", "YOUR-SECRETACCESSKEY"); ClientConfiguration clientConfiguration = new ClientConfiguration(); clientConfiguration.setSignerOverride("AWSS3V4SignerType"); //EndpointにMinioで指定した値を入れる リージョンの値はそのままで問題ないです。 AmazonS3 s3Client = AmazonS3ClientBuilder .standard() .withEndpointConfiguration( new AwsClientBuilder.EndpointConfiguration("http://localhost:9000", Regions.US_EAST_1.name())) .withPathStyleAccessEnabled(true) .withClientConfiguration(clientConfiguration) .withCredentials(new AWSStaticCredentialsProvider(credentials)) .build(); try { System.out.println("Uploading a new object to S3 from a file\n"); File file = new File(uploadFileName); // Upload file s3Client.putObject(new PutObjectRequest(bucketName, keyName, file)); // Download file GetObjectRequest rangeObjectRequest = new GetObjectRequest(bucketName, keyName); S3Object objectPortion = s3Client.getObject(rangeObjectRequest); System.out.println("Printing bytes retrieved:"); displayTextInputStream(objectPortion.getObjectContent()); } catch (AmazonServiceException ase) { System.out.println("Caught an AmazonServiceException, which " + "means your request made it " + "to Amazon S3, but was rejected with an error response" + " for some reason."); System.out.println("Error Message: " + ase.getMessage()); System.out.println("HTTP Status Code: " + ase.getStatusCode()); System.out.println("AWS Error Code: " + ase.getErrorCode()); System.out.println("Error Type: " + ase.getErrorType()); System.out.println("Request ID: " + ase.getRequestId()); } catch (AmazonClientException ace) { System.out.println("Caught an AmazonClientException, which " + "means the client encountered " + "an internal error while trying to " + "communicate with S3, " + "such as not being able to access the network."); System.out.println("Error Message: " + ace.getMessage()); } } private static void displayTextInputStream(InputStream input) throws IOException { // Read one text line at a time and display. BufferedReader reader = new BufferedReader(new InputStreamReader(input)); while (true) { String line = reader.readLine(); if (line == null) break; System.out.println(" " + line); } System.out.println(); } } まとめ awsは素晴らしいサービスですが、一歩間違うと大金を支払う可能性が出てくるので使うのが怖いですよね。 minioは他にも工夫すれば、スクレイピングの情報を溜めておくのに使えたりサイトのページとして使えるので応用を効かせると 夢が広がります。 今回、人生で初めてQiita投稿しました。 今後も、現場での知識や気になった技術などの投稿をしていきたいと思います。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

awsをterraformで構築するには(基本編)

プロバイダーを決める terraform { required_version = ">= 1.0.1" required_providers { aws = ">= 3.0" } } provider "aws" { access_key = var.aws_access_key secret_key = var.aws_secret_key region = var.aws_region } 変数定義 terraform.tfvarsにて aws_access_key="xxxxxxxx" aws_secret_key="xxxxxxxx" aws_region="xxxxxxxx" variables.tfの中で variable "aws_access_key" { type = string } variable "aws_secret_key" { type = string } variable "aws_region" { type = string } resourceの定義 あとは例えばaws_alb.tfみたいなファイルを作って(ファイルは分割しなくても動くが、基本分割した方が綺麗だし、わかりやすい)、リソースの定義をする。詳しくはドキュメントを確認。 resource "aws_lb" "api_lb" { name = "test-alb" internal = false load_balancer_type = "application" security_groups = [aws_security_group.test-group.id] subnets = ["${aws_subnet.test_subnet.id}", "${aws_subnet.test_subnet2.id}"] enable_deletion_protection = true tags = { "Environment" = terraform.workspace "Application" = "api" } } 一通り記載したら下記を実行 terraform plan terraform apply 変更あるたびに terraform plan terraform applyを行う リソースを一旦消したいのであれば terraform destroy 以上メモように記録
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

VPC-S3の環境で、不正なデータ送信をAlarmする環境を、CloudFormationで構築する

はじめに 以前作成した、VPCの内部から不正なデータ送信のアラームを送信する環境と、S3の不正アクセスを検出する環境を、一つにしたCloudFormationを作成しました。 構成 今回も、複数の環境を想定して、「共通で使うリソース」と「個別の環境で使うリソース」で分けて作成しました。 以前と少し異なる点は、VPCとCloudTrailにアタッチさせるIAMロール(CloudWatch Logs出力権限)を共通にしました。 それ以外のリソース等は、以前(VPCとS3)のものと同じです。 CloudFormation コードは以下になります、説明等に使われている英語の拙さはご容赦ください。 共通で使うリソース 01_createBaseEnvForTrail.yml AWSTemplateFormatVersion: 2010-09-09 Description: Create Base Env for Trail on VPC and S3. And Add target Bucket for trail. Parameters: TrailBuckets: Description: Set S3Bucket Arn(arn:aws:s3:::xxxxxxxxxxx/) for trail. delimiter is connma(,). If bukcet don't exists, set empty (Don't Create CloudTrail) . Type: CommaDelimitedList Metadata: AWS::CloudFormation::Interface: ParameterGroups: - Label: default: User Setting. Parameters: - TrailBuckets # パラメータのリストを連結させて空文字なら、CloudTrailを作らない Conditions: CreateTrail: !Not [!Equals [ !Join [ '', !Ref TrailBuckets ] , '']] Resources: ################################################## # Common Resource ################################################## # SNS IllegalTraficSnsTopic: Type: AWS::SNS::Topic Properties: TopicName: illegal-trafic-sns-topic Tags: - Key: "usefor" Value: "send e-mail detection of illegal trafic" # Role for Output to Log Group ## ロググループに出力可能なロール作成 OutputRoleToLogGroup: Type: AWS::IAM::Role Properties: RoleName: for-outputto-loggroup Path: / AssumeRolePolicyDocument: Version: 2012-10-17 Statement: - Effect: Allow Principal: Service: - "vpc-flow-logs.amazonaws.com" - "cloudtrail.amazonaws.com" Action: 'sts:AssumeRole' Policies: # IAMの参照などを追加 - PolicyName: outputto-loggroup PolicyDocument: Version: 2012-10-17 Statement: - Effect: Allow Action: - "logs:CreateLogGroup" - "logs:CreateLogStream" - "logs:PutLogEvents" - "logs:DescribeLogGroups" - "logs:DescribeLogStreams" Resource: '*' Tags: - Key: "usefor" Value: "output to LogGroup" ################################################## # VPC Resource ################################################## # Cloudwatch log Group VpcFlowlogsLogGroup: Type: AWS::Logs::LogGroup Properties: LogGroupName: /custom/vpcflowlogs RetentionInDays: 3653 # 未指定時は「失効しない」 ################################################## # S3 Resource ################################################## # Cloudwatch log Group S3AccesslogLogGroup: Type: AWS::Logs::LogGroup Properties: LogGroupName: /custom/s3accesslog RetentionInDays: 3653 # 未指定時は「失効しない」 # Bucket for CloudTrail OutCloudTrailBucket: Type: AWS::S3::Bucket Properties: BucketName: !Sub "out-cloudtrail-s3accesslogs-${AWS::AccountId}" BucketEncryption: ServerSideEncryptionConfiguration: - ServerSideEncryptionByDefault: SSEAlgorithm: "AES256" BucketKeyEnabled: false PublicAccessBlockConfiguration: BlockPublicAcls: true BlockPublicPolicy: true IgnorePublicAcls: true RestrictPublicBuckets: true ## SSLがないのはNG OutCloudTrailBucketPolicy: Type: AWS::S3::BucketPolicy Properties: Bucket: !Ref OutCloudTrailBucket PolicyDocument: Version: 2012-10-17 Statement: - Sid: DenyNotSecureTransport Effect: Deny Principal: "*" Resource: - !Sub "arn:aws:s3:::${OutCloudTrailBucket}" - !Sub "arn:aws:s3:::${OutCloudTrailBucket}/*" Action: "*" Condition: Bool: aws:SecureTransport: false - Sid: AWSCloudTrailAclCheck Effect: Allow Principal: Service: cloudtrail.amazonaws.com Action: s3:GetBucketAcl Resource: !Sub "arn:aws:s3:::${OutCloudTrailBucket}" - Sid: AWSCloudTrailWrite Effect: Allow Principal: Service: cloudtrail.amazonaws.com Action: s3:PutObject Resource: !Sub "arn:aws:s3:::${OutCloudTrailBucket}/s3AccessLogTrail/AWSLogs/${AWS::AccountId}/*" Condition: StringEquals: s3:x-amz-acl: bucket-owner-full-control # CloudTrail Trail: Type: AWS::CloudTrail::Trail Condition: CreateTrail Properties: S3BucketName: !Ref OutCloudTrailBucket S3KeyPrefix: "s3AccessLogTrail" CloudWatchLogsLogGroupArn: !GetAtt S3AccesslogLogGroup.Arn CloudWatchLogsRoleArn: !GetAtt OutputRoleToLogGroup.Arn EnableLogFileValidation: true IsLogging: true TrailName: S3AccessLogTrail IncludeGlobalServiceEvents: true EventSelectors: - DataResources: - Type: AWS::S3::Object Values: !Ref TrailBuckets ReadWriteType: All IncludeManagementEvents: false Outputs: ################################################## # Common Resource ################################################## IllegalTraficSnsTopic: Value: !Ref IllegalTraficSnsTopic Export: Name: IllegalTraficSnsTopic OutputRoleArnToLogGroup: Value: !GetAtt OutputRoleToLogGroup.Arn Export: Name: OutputRoleArnToLogGroup ################################################## # VPC Resource ################################################## VpcFlowlogsLogGroup: Value: !Ref VpcFlowlogsLogGroup Export: Name: VpcFlowlogsLogGroup ################################################## # S3 Resource ################################################## S3AccesslogLogGroup: Value: !Ref S3AccesslogLogGroup Export: Name: S3AccesslogLogGroup 個別の環境で使うリソース 02_createEachEnvForTrail.yml AWSTemplateFormatVersion: 2010-09-09 Description: Create Each Env for Trail on VPC and S3. Parameters: EnvId: Type: String VpcCidr: Type: String Default: 192.168.209.0/24 SubnetACidr: Type: String Default: 192.168.209.0/26 SubnetCCidr: Type: String Default: 192.168.209.64/26 SubnetDCidr: Type: String Default: 192.168.209.128/26 Metadata: AWS::CloudFormation::Interface: ParameterGroups: - Label: default: User Setting. Parameters: - EnvId - VpcCidr - SubnetACidr - SubnetCCidr - SubnetDCidr Resources: ################################################## # VPC ################################################## Vpc: Type: AWS::EC2::VPC Properties: CidrBlock: !Ref VpcCidr # EnableDnsHostnames: true # EnableDnsSupport: true Tags: - Key: Name Value: !Sub "${EnvId}-vpc" ################################################## # Security Group ################################################## SecGrpOnlyInternal: Type: AWS::EC2::SecurityGroup Properties: GroupDescription: Enable access from EC2 Instance Connect IP GroupName: !Sub "${EnvId}-sg" VpcId: !Ref Vpc # For EC2 Instance Connect SecurityGroupIngress: - IpProtocol: tcp FromPort: 22 ToPort: 22 CidrIp: 3.112.23.0/29 SGBaseIngress: Type: AWS::EC2::SecurityGroupIngress Properties: GroupId: !Ref SecGrpOnlyInternal IpProtocol: -1 SourceSecurityGroupId: !GetAtt SecGrpOnlyInternal.GroupId ################################################## # IGW ################################################## Igw: Type: AWS::EC2::InternetGateway Properties: Tags: - Key: Name Value: !Sub ${EnvId}-igw IgwAttachment: Type: AWS::EC2::VPCGatewayAttachment Properties: InternetGatewayId: !Ref Igw VpcId: !Ref Vpc ################################################## # Subnets ################################################## SubnetA: Type: AWS::EC2::Subnet Properties: VpcId: !Ref Vpc AvailabilityZone: ap-northeast-1a CidrBlock: !Ref SubnetACidr MapPublicIpOnLaunch: false Tags: - Key: Name Value: !Sub ${EnvId}-subnet-a SubnetC: Type: AWS::EC2::Subnet Properties: VpcId: !Ref Vpc AvailabilityZone: ap-northeast-1c CidrBlock: !Ref SubnetCCidr MapPublicIpOnLaunch: false Tags: - Key: Name Value: !Sub ${EnvId}-subnet-c SubnetD: Type: AWS::EC2::Subnet Properties: VpcId: !Ref Vpc AvailabilityZone: ap-northeast-1d CidrBlock: !Ref SubnetDCidr MapPublicIpOnLaunch: false Tags: - Key: Name Value: !Sub ${EnvId}-subnet-d ################################################## # Routing ################################################## RouteTable: Type: AWS::EC2::RouteTable Properties: VpcId: !Ref Vpc Tags: - Key: Name Value: !Sub ${EnvId}-public-rtb RouteTableAssocA: Type: AWS::EC2::SubnetRouteTableAssociation Properties: RouteTableId: !Ref RouteTable SubnetId: !Ref SubnetA RouteTableAssocC: Type: AWS::EC2::SubnetRouteTableAssociation Properties: RouteTableId: !Ref RouteTable SubnetId: !Ref SubnetC RouteTableAssocD: Type: AWS::EC2::SubnetRouteTableAssociation Properties: RouteTableId: !Ref RouteTable SubnetId: !Ref SubnetD Route: Type: AWS::EC2::Route Properties: RouteTableId: !Ref RouteTable DestinationCidrBlock: 0.0.0.0/0 GatewayId: !Ref Igw ################################################## # S3 ################################################## PrivateBucket: Type: AWS::S3::Bucket Properties: BucketName: !Sub "for-${EnvId}-${AWS::AccountId}" BucketEncryption: ServerSideEncryptionConfiguration: - ServerSideEncryptionByDefault: SSEAlgorithm: "AES256" BucketKeyEnabled: false PublicAccessBlockConfiguration: BlockPublicAcls: true BlockPublicPolicy: true IgnorePublicAcls: true RestrictPublicBuckets: true # SSLがないのはNG PrivateBucketPolicy: Type: AWS::S3::BucketPolicy Properties: Bucket: !Ref PrivateBucket PolicyDocument: Version: 2012-10-17 Statement: - Sid: DenyNotSecureTransport Effect: Deny Principal: "*" Resource: - !Sub "arn:aws:s3:::${PrivateBucket}" - !Sub "arn:aws:s3:::${PrivateBucket}/*" Action: "*" Condition: Bool: aws:SecureTransport: false ################################################## # VPC Endpoint to S3 ################################################## VPCS3Endpoint: Type: AWS::EC2::VPCEndpoint Properties: VpcEndpointType: Gateway RouteTableIds: - !Ref RouteTable ServiceName: !Sub "com.amazonaws.${AWS::Region}.s3" VpcId: !Ref Vpc PolicyDocument: Version: 2012-10-17 Statement: - Effect: Allow Principal: '*' Action: - "s3:*" Resource: - !Sub "arn:aws:s3:::${PrivateBucket}" - !Sub "arn:aws:s3:::${PrivateBucket}/*" ################################################## # VPC FlowLogs ################################################## VpcFlowLogs: Type: AWS::EC2::FlowLog Properties: ResourceType: VPC ResourceId: !Ref Vpc TrafficType: ALL DeliverLogsPermissionArn: !ImportValue OutputRoleArnToLogGroup LogGroupName: !ImportValue VpcFlowlogsLogGroup LogFormat: '${account-id} ${action} ${az-id} ${bytes} ${dstaddr} ${dstport} ${end} ${flow-direction} ${instance-id} ${interface-id} ${log-status} ${packets} ${pkt-dst-aws-service} ${pkt-dstaddr} ${pkt-src-aws-service} ${pkt-srcaddr} ${protocol} ${region} ${srcaddr} ${srcport} ${start} ${sublocation-id} ${sublocation-type} ${subnet-id} ${tcp-flags} ${traffic-path} ${type} ${version} ${vpc-id}' Tags: - Key: Name Value: !Sub ${EnvId}-flowlog ################################################## # Role ################################################## # EC2アタッチ用ロール作成 Ec2Role: Type: AWS::IAM::Role Properties: RoleName: !Sub for-ec2-on-${EnvId} Path: / AssumeRolePolicyDocument: Version: 2012-10-17 Statement: - Effect: Allow Principal: Service: - "ec2.amazonaws.com" Action: 'sts:AssumeRole' Policies: - PolicyName: s3fullaccess PolicyDocument: Version: 2012-10-17 Statement: - Effect: Allow Action: - "s3:*" Resource: - !Sub "arn:aws:s3:::${PrivateBucket}" - !Sub "arn:aws:s3:::${PrivateBucket}/*" ## インスタンスプロファイル作成 MyInstanceProfile: Type: AWS::IAM::InstanceProfile Properties: Path: / Roles: - !Ref Ec2Role ################################################## # MetricFilter # フィルタ名は [CFnのスタック名]-[リソース名]-[ランダム文字列]が付く ################################################## # VPC FlowLogs MetricFilterOfVpcFlowLogs: Type: AWS::Logs::MetricFilter Properties: LogGroupName: !ImportValue VpcFlowlogsLogGroup FilterPattern: !Sub "[account_id, action, az_id, bytes > 1000000, dstaddr!=52.219.* && dstaddr!=3.5.* && dstaddr!=35.72.164.* && dstaddr!=35.73.115.* , dstport, end, flow_direction = egress, instance_id, interface_id, log_status, packets, pkt_dst_aws_service!=EC2_INSTANCE_CONNECT, ..., vpc_id=${Vpc}]" MetricTransformations: - MetricValue: 1 MetricNamespace: Custom/VPC MetricName: !Sub ${EnvId}-vpc-IllegalTrafic DefaultValue: 0 # S3 AccessLog MetricFilterOfS3AccessLog: Type: AWS::Logs::MetricFilter Properties: LogGroupName: !ImportValue S3AccesslogLogGroup FilterPattern: !Sub '{($.eventName="GetObject") && (($.sourceIPAddress!="123.123.123.123") && ($.sourceIPAddress!="234.234.*") && ($.vpcEndpointId!="${VPCS3Endpoint}" || $.vpcEndpointId NOT EXISTS)) && ($.requestParameters.bucketName="${PrivateBucket}")}' MetricTransformations: - MetricValue: 1 MetricNamespace: Custom/S3 MetricName: !Sub ${EnvId}-s3-IllegalTrafic DefaultValue: 0 ################################################## # Alarm ################################################## # VPC FlowLogs LogFilterAlarmOfVpcFlowLogs: Type: AWS::CloudWatch::Alarm Properties: Namespace: Custom/VPC MetricName: !Sub ${EnvId}-vpc-IllegalTrafic Statistic: Sum Period: 300 # の間に ComparisonOperator: GreaterThanOrEqualToThreshold # の状態を Threshold: 1 # 回超えることが EvaluationPeriods: 1 # 周期中 DatapointsToAlarm: 1 # 回なら TreatMissingData: notBreaching AlarmActions: - !ImportValue IllegalTraficSnsTopic AlarmName: !Sub ${EnvId}-vpc-IllegalTraficAlarm AlarmDescription: !Sub "${EnvId} vpc にて、不正トラフィック検出" # S3 AccessLog LogFilterAlarmOfS3AccessLog: Type: AWS::CloudWatch::Alarm Properties: Namespace: Custom/S3 MetricName: !Sub ${EnvId}-s3-IllegalTrafic Statistic: Sum Period: 300 # の間に ComparisonOperator: GreaterThanOrEqualToThreshold # の状態を Threshold: 1 # 回超えることが EvaluationPeriods: 1 # 周期中 DatapointsToAlarm: 1 # 回なら TreatMissingData: notBreaching AlarmActions: - !ImportValue IllegalTraficSnsTopic AlarmName: !Sub ${EnvId}-s3-IllegalTraficAlarm AlarmDescription: !Sub "arn:aws:s3:::${PrivateBucket} にて、不正トラフィック検出" ################################################## # Output ################################################## # CloudTrailを作成するCFnのパラメータに渡す文字列を出力 # (指定時に末尾スラッシュ必要) Outputs: PrivateBucket: Value: !Sub "arn:aws:s3:::${PrivateBucket}" Export: Name: !Sub "PrivateBucket-${EnvId}" 以前と異なる点は以下になります。 VPCフローログのフィルタ サイズを"1MBを超える"にしました。 "EC2_INSTANCE_CONNECT経由のトラフィック"を除外 pkt_dst_aws_service!=EC2_INSTANCE_CONNECT, 使ってみると、ここのトラフィックに流れるデータのサイズが大きかったため除外。 S3アクセスログのフィルタ 同じスタックで作成したVPCのエンドポイント経由を除外 ($.vpcEndpointId!="${VPCS3Endpoint}" || $.vpcEndpointId NOT EXISTS) $.vpcEndpointId!=xxxxだけだと、VPCエンドポイントを経由しないアクセスにもFalseとなるようだったので、$.vpcEndpointId NOT EXISTSをORで結合しました。 環境作成手順、片づけ手順 作成の仕方はS3の時と、片づけの仕方もS3の時と同様です。 まとめ PC&S3バケットの不正トラフィックの検出環境の構築をCloudFormation化しました。 課題として「パブリックのサービスからのアクセスに対してアラームになる」という点ありますので、折を見て探ってみたいと思います。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

AWS Step Functions で AWS Batch のステートマシンを作成する

ステートマシンの作成 まずステートマシンの Type フィールドですが、 Task を指定します。これはステートマシンが他の AWS リソースを呼び出すときに使用します。 "Type": "Task" 次に Resource フィールドですが、Batch 用には次の ARN が用意されています。 arn:aws:states:::batch:submitJob さらにサフィックスに .sync を付与すると、ステートマシンは実行完了まで待機します。 リクエストの完了まで待機してから、次の状態に進むことができます。Step Functions を待機させるには、"Resource"フィールドを使用して、タスク状態定義の.syncサフィックスをリソース URI の後に付加します。 詳しくはこちらを参照してください。 上記を踏まえ、以下のような Resource を指定します。 "Resource": "arn:aws:states:::batch:submitJob.sync" 次に Parameters フィールドですが、以下のように指定します。 "Parameters": { "JobDefinition": "call-job", "JobName": "call-job", "JobQueue": "call-queue" } 以下が完成版になります。 { "Comment": "Execute Variant Call", "StartAt": "call", "States": { "call": { "Type": "Task", "Resource": "arn:aws:states:::batch:submitJob.sync", "Parameters": { "JobDefinition": "call-job", "JobName": "call-job", "JobQueue": "call-queue" }, "End": true } } } 実行時はジョブキューで指定したコンピューティング環境を有効化することを忘れないように注意してください。 以下は実行結果になります。 参考記事
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Lambdaでec2自動起動停止

自動起動 iam role作成 AWSコンソールへログイン https://console.aws.amazon.com/iamv2 左ペインロール押下 ロールを作成押下 一般的なユースケース:lambda ポリシー:AmazonEC2FullAccess ロール名:control-ec2 作成 lambda関数作成 https://console.aws.amazon.com/lambda 関数の作成押下 関数名:start-ec2 ランタイム:python3.9 デフォルトの実行ロールの変更 既存のロールを使用する:control-ec2 関数の作成 以下コード入れる import boto3 region = 'ap-northeast-1' instances = [] instances.append('対象インスタンスID1') instances.append('対象インスタンスID2') ec2 = boto3.client('ec2', region_name=region) def lambda_handler(event, context): ec2.start_instances(InstanceIds=instances) print('started your instances: ' + str(instances)) test押下 新しいテストイベントの作成 イベントテンプレート:そのまま イベント名:適当に 作成 test押下 ちゃんと動くか確認 EventBridge +トリガーの追加 トリガーの選択 EventBridge 新規ルールの作成 ルール名:auto-start-ec2 ルールタイプ スケジュール式 cron(0 23 ? * SUN-THU *) #平日の朝8時起動 自動停止 lambda関数作成 https://console.aws.amazon.com/lambda 関数の作成押下 関数名:stop-ec2 ランタイム:python3.9 デフォルトの実行ロールの変更 既存のロールを使用する:control-ec2 関数の作成 以下コード入れる import boto3 region = 'ap-northeast-1' instances = [] instances.append('対象インスタンスID1') instances.append('対象インスタンスID2') ec2 = boto3.client('ec2', region_name=region) def lambda_handler(event, context): ec2.stop_instances(InstanceIds=instances) print('stopped your instances: ' + str(instances)) test押下 新しいテストイベントの作成 イベントテンプレート:そのまま イベント名:適当に 作成 test押下 ちゃんと動くか確認 EventBridge +トリガーの追加 トリガーの選択 EventBridge 新規ルールの作成 ルール名:auto-stop-ec2 ルールタイプ スケジュール式 cron(0 13 ? * MON-FRI *) #平日の22時停止
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

AWS Batch でゲノムマッピングをしてみる

初めに BWA を Centos イメージにインストールして簡単に AWS Batch で動かしてみます。リファレンスファイルや FASTQ ファイルは S3 バケットに保存しておき、Batch ジョブでダウンロードします。 Docker イメージの作成 Centos イメージに BWA、AWS CLI v2 をインストールするイメージを作成します。 Dockerfile FROM centos RUN yum install -y git make gcc zlib-devel unzip \ && git clone https://github.com/lh3/bwa.git \ && cd bwa \ && make \ && cp bwa *.pl /usr/bin \ && curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip" \ && unzip awscliv2.zip \ && ./aws/install -i /usr/local/aws-cli -b /usr/bin \ && rm -f awscliv2.zip COPY run_bwa.sh /bwa/run_bwa.sh CMD sh /bwa/run_bwa.sh こちらはコンテナで実行するシェルスクリプトです。BWA でマッピングを行うためのコマンドを記述します。 run_bwa.sh echo 'mapping START' mkdir /fa_files mkdir /fq_files mkdir /sam_files # リファレンスファイルのダウンロード aws s3 cp s3://my-gwf-bucket/fa_files/chr5.fa /fa_files/chr5.fa # インデックスの作成 bwa index /fa_files/chr5.fa # FASTQ ファイルをダウンロード aws s3 cp s3://my-gwf-bucket/fq_files/paired_1.fq /fq_files/paired_1.fq aws s3 cp s3://my-gwf-bucket/fq_files/paired_2.fq /fq_files/paired_2.fq # マッピング bwa mem -t 8 -o /sam_files/output.sam /fa_files/chr5.fa /fq_files/paired_1.fq /fq_files/paired_2.fq # 作成した SAM ファイルをアップロード aws s3 cp /sam_files/output.sam s3://my-gwf-bucket/sam_files/output.sam Docker イメージが完成したら ECR に Push します。 AWS Batch の手順 コンピューティング環境の作成 「マネージド型」を選択し、サービスロールは 「Batch service-linked role」 を選択します。 「オンデマンド」を選択し、最小 vCPU 、最大 vCPU、必要な vCPU はそれぞれデフォルトのままにします。 こちらもデフォルトのままにします。 EC2 設定のところで、矢印で示した「設定の追加」をクリックします。イメージタイプには「Amazon Linux2」を選択します。なぜか空白のままですが、問題ありません。 その後「コンピューティング環境の作成」をクリックします。 ジョブ定義の作成 「EC2」を選択し、ジョブの試行は「1」を入力します。 コンテナプロパティではイメージに ECR の URI を入力します。コマンドは Dockerfile の CMD で指定したコマンド sh /bwa/run_bwa.sh を入力します。 vCPU は「8」、メモリはデフォルトの「2048」を指定します。ジョブロールには S3 バケットに対するダウンロード・アップロード権限を付与したロールを指定します。実行ロールには ECR からイメージを Pull できる権限を付与したロールを指定します。 その後「作成」をクリックします。 ジョブキューの作成 ジョブキュー名を入力します。 コンピューティング環境の作成 で作成したコンピューティング環境を選択します。 その後「作成」をクリックします。 ジョブの送信 作成したジョブ定義から「新しいジョブを送信」をクリックします。 ジョブ定義、ジョブキューを指定します。 その後「送信」をクリックします。 注意点 ジョブの vCPU(コンテナに割り当てられる vCPU)が、コンピューティング環境で指定した EC2 インスタンスタイプの CPU を超えていると ジョブのステータスが RUNNABLE から動かなくなります。この記事ではインスタンスタイプを Optional にしていますので、任意の vCPU に対して AWS Batch により適切なインスタンスが起動し、ジョブは RUNNABLE で止まることはありません。 ジョブが成功したことを確認する ジョブ送信後、ECS でコンテナタスクが実行されます。 インスタンスが起動しています。 タスクが終了するとインスタンスは削除されます。 ログを確認して、タスクが正常に完了したことを確認します。 S3 バケットに SAM ファイルがアップロードされていることを確認します。 参考記事
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む