- 投稿日:2022-03-22T23:51:39+09:00
AWS CloudEndureを使ってMigrationを仕掛ける際の考慮事項
CloudEndure Migrationとは "CloudEndure Migration" はAWSが提供するサービスで、いわゆる「イメージ転送」にて移行ができるものです。 元々は有償サービスで、AWSを始めとした各種クラウドへの移行が行えるサービスでしたが、AWSが買収したことにより無償提供されAWSへの移行専用サービスとなりました。 AWSが提供するサーバーイメージ移行サービス(ツール)としては、VMImport や Server Migration Service がありますが、前述のサービスより手軽で幅広いシーンに対応できることから非常に使い勝手がよく、個人的には第一選択とすべきと考えています。 サービス名 特徴 データ同期 VMImport VMwareからエクスポートしたサーバイメージをインポートしEC2に変換 無し Server Migration Service 仮想化基盤(VMware、Hyper-V)からサーバイメージを抽出しEC2に変換 無し CloudEndure Migration 移行元サーバに導入したエージェントを介してディスクイメージを転送しEC2に変換 有り 特徴 制約 対応OSに縛りがある https://docs.cloudendure.com/Content/Getting_Started_with_CloudEndure/Supported_Operating_Systems/Supported_Operating_Systems.htm 移行対象サーバー全てにエージェント導入が必要 制御系とデータ転送の2つの通信経路がある 前者の制御系はクラウド上にあるCloudEndureのサービス本体と通信する必要があり、インターネット通信が必須となる。 - データ転送はインターネットと閉域網の双方が利用できる。閉域網の場合はDirectConnectやVPN接続を事前に張っておく必要がある。 無償利用できるがライセンス期間は90日である。 動作順序 CloudEndure は移行元サーバー導入したエージェントを介してディスクイメージを転送する データ転送制御のためクラウド上のCloudEndureサービスと通信を行う データ転送を開始するとディスクイメージを受け取るレプリケーションサーバーが立ち上がり、移行元サーバーと同数のEBSが作成されデータ転送される。 この際、移行元サーバーとレプリケーションサーバー間は 継続的なデータ同期 が行われている点に着目。 移行先サーバーの設定は BluePrint と呼ばれるパラメータにてインスタンスタイプや所属サブネットやセキュリティグループ等を指定して行う。 移行先環境にサーバーを立ち上げる(=カットオーバーという)際はBluePrintを元にAMIが作成されEC2が立ち上がる レプリケーションサーバにアタッチされ転送されたディスクイメージはスナップショットが取られ、それを元に移行先サーバーに新たなEBSとしてアタッチされる カットオーバーで同期は失われる レプリケーションサーバーは移行元サーバーのディスクイメージを継続的に受け止め同期が行われるが、移行先サーバーのディスクはカットオーバーした時点のスナップショットを元に構築される点です。 つまり、カットオーバーした段階で移行元サーバーと移行先サーバーのデータの乖離が始まると言うことになります。 テストモードとカットオーバー CloudEndureで移行先サーバーを構築するのはカットオーバーだけでなく「テストモード」というものがあります。 これは動作としてBluePrintどおりに移行先のEC2が立ち上がるかどうかを確認するもので、ほぼカットオーバーと同じです。 CloudEndureの設計思想としてはこのテストモードを利用して動作確認を行う位置づけとなります。 このテストモードで十分な動作確認が取れたのであれば本番用のカットオーバーとなりますが注意すべき点があります。 テストモードで立ち上げたサーバーは削除される という点です。 せっかく設定変更やチューニングを施しても、カットオーバーでレプリケーションサーバー上にある同期されたディスク情報で新たにサーバーが立ってしまうため、これらの作業は「無かったこと」となります。 手順を明確にし設定変更をスクリプト化する等の準備を行い、カットオーバーがスピーディに行われるよう準備する必要があります。 移行元環境への考慮 データ転送は複数サーバーを同時に実行することが可能です。 これは非常に有用な機能なのですが、移行元環境に過度の負荷をかける可能性があり、計画を建てる上で重要なファクターとなります。 データ転送初期はディスク全体をスキャンするためCPU負荷が高くなる可能性があります。特にシングルコアのサーバーの場合はサービス影響が大きく出る可能性があります。 複数サーバーを一括で同期をとった際に移行元環境のネットワーク出口のトラフィック逼迫し既存サービスに影響が出る可能性があります。この場合は転送時間帯や帯域制御を考慮する必要があります。 移行計画の考慮事項 計画時に考慮に含める必要があるのは以下 移行期間 ライセンスの期間は90日ですがアカウントは再発行は可能なためそれほどシビアではありません。とはいえデータ転送の期間を考慮したライセンス取得を行う必要があります。 またデータ転送の時間や移行後の動作確認等も必要となるため十分な期間の考慮が必要となります。 通信経路 CloudEndureはエージェントがインターネット通信が必要となるため、移行元サーバーの配置によっては通信経路の穴開けが必要となります。 既存環境の変更が必要な場合、様々な調整や費用が発生するケースも考えられますので、十分な考慮をしておく必要があります。 データ転送経路についても考慮が必要です。インターネット経由でのデータ転送でも十分なケースもありますが、データ転送期間をなるべく短くしたいのであれば高品質な専用線が必要となってきます。この場合はデータ量(全サーバーのディスク容量の和)と回線品質を考慮し、専用線が必要かどうかを判断する必要があります。 また、インターネット経由でのデータ転送の場合、既存サービスの通信を圧迫しないかの考慮も必要となってきますので、併せて確認をする必要があります。 システム切り替え CloudEndureはサーバー移行を行うサービスであり、エンドポイントを切り替えは別途考慮する必要があります。主にDNS切替えが主となる戦略となると思いますが、閉域網の場合はルーティング等も考慮する必要がでてきます。 移行先 CloudEndure は移行元サーバーのイメージをそのまま転送するため、アプリケーション設定やOSユーザーもそのまま引き継がれます。 そのためネットワーク設定をそのまま引き継いだ場合、そのまま動作すると考えられます。逆にネットワーク設定を変更したのであれば、各サーバーのアプリケーション設定を見直す必要があります。サーバー転送後の作業として設定変更と動作確認が必要となってきますので注意が必要です。 なお、移行先環境(VPC,サブネット等)はカットオーバーに先立ち構築しておく必要がありますので、計画の際には考慮が必要です。 人手がかかる作業の考慮 移行先サーバーのパラメターは CloudEndure コンソール の Blue Print にて入力を行います。 これはコンソールのGUIでの実施であるため一括入力・一括確認ができません。対象のサーバー台数が数~十数台程度であれば「気合でなんとかなる」レベルですが、数十台以上のオーダーとなるとそうもいきません。 幸いなことに CloudEndure には複数ユーザーを登録することが可能ですので複数人で分担して並列作業が可能となります。 移行対象台数を考慮し人員と十分な工期の確保が必要です。 カットオーバー後作業の考慮 「テストモードとカットオーバー」の項で述べたように、カットオーバー後の作業はなるべく自動化を行う必要があります。 テストモード時にしっかりと確認することが必要で、このフェーズに十分な工数を掛けておく必要があります。 テストモードは何度も実行することが可能ですので、事後作業のスクリプト化や省力化の確認を何度も行うことが出来るため、カットオーバーの前の最終確認はここで担保することとなります。 なおこの期間も移行元サーバーとレプリケーションサーバー間は継続的なディスク同期が行われています。 ライセンス期間も気をつけて十分な工期をとるよう考慮する必要があります。 マネージドサービスの考慮 せっかくクラウドに移行するのでロードバランサーやデータベースをマネージドサービスに変更したいといった要望があるかもしれません。 CloudEndureはサーバー移行のみ担当するため、マネージドサービスは別途構築が必要となります。 例えばロードバランサーだと、Application Loadbalancer の構築とサーバー証明書設置およびEC2へのアタッチ作業が必要となります。マネージドDBのRDSを採用した場合ですと、既存DBからのデータ移行も考慮が必要となります。 動作確認 動作確認はエンドポイント切替え前に実施するものとなるため、その方式や経路について十分な考慮が必要となります。 データ同期 AWS環境にサーバーを立ち上げるカットオーバー後には、設定内容変更や動作確認が必要になるケースが多々有りえます。「カットオーバーをすると移行元サーバーとデータの乖離が生じる」ため、その期間が長ければ何らかのデータ同期を考慮する必要があります。 データ同期については静止点が取れ十分なダウンタイムが取れるのであればあまり考慮は必要有りません。 一方で無停止やそれに準じる必要がある場合、既存サーバーとのデータ同期を考慮する必要があります。CloudEndure Migration 単体で解決出来ないので何らかの方策を考える必要があります。 逆に言えばデータ同期戦略がはっきりしていれば、システム切替えについて慌てる必要がなくなるとも言えます。 データ同期参考: データベース データベースのレプリケーション機能を使用する AWS Database Migration Serviceを使用する https://aws.amazon.com/jp/dms/ ファイルシステム AWS DataSync を使用する https://aws.amazon.com/jp/datasync/?whats-new-cards.sort-by=item.additionalFields.postDateTime&whats-new-cards.sort-order=desc rsync等、サーバにデータレプリケーションの設定をする
- 投稿日:2022-03-22T23:32:00+09:00
Laravelバッチ(コマンド) のログをバッチ毎にCloudWatch Logsへ出力する
はじめに EC2上でLaravel APIサーバーが稼働しています。 このAPIサーバーでは$schedule->commandを使用して定期的にバッチ(コマンド)の実行もしています。 (バッチサーバーも兼ねているわけです。) APIとバッチがあいのりしている件はあまり良くないですが、今回はその改善には触れません。 今回の問題はログです。 storage/logs配下へログを出力していますが、 1つのログファイルにAPIとバッチのログがまじってしまっており、さらにバッチが10個程度存在していたため、 どれがどのログなのかを理解する・探すのも難しい状態になっていました。 そこで各ログファイルを分け、ついでにCloudWatchLogsへ連携してみました。 バッチごとにログを分ける logging.phpへチャンネルの設定を追加する バッチごとに使用するログチャンネルの設定を記載します。 日毎にローテーションしていたり、debugログすべて出力していたりするのでそこは調整してください。 config/logging.php ~省略~ 'channels' => [ 'stack' => [ 'driver' => 'stack', 'channels' => ['daily'], 'ignore_exceptions' => false, ], 'single' => [ 'driver' => 'single', 'path' => storage_path('logs/laravel.log'), 'level' => env('LOG_LEVEL', 'debug'), 'permission' => 0777, ], 'daily' => [ 'driver' => 'daily', 'path' => storage_path('logs/laravel.log'), 'level' => env('LOG_LEVEL', 'debug'), 'days' => 30, 'permission' => 0777 ], // バッチごとにログファイルを分けるためチャンネルを作成 'batch-a' => [ 'driver' => 'daily', 'path' => storage_path('logs/batch-a.log'), 'level' => env('LOG_LEVEL', 'debug'), 'days' => 30, 'permission' => 0777, 'ignore_exceptions' => false ], 'batch-b' => [ 'driver' => 'daily', 'path' => storage_path('logs/batch-b.log'), 'level' => env('LOG_LEVEL', 'debug'), 'days' => 30, 'permission' => 0777, 'ignore_exceptions' => false ], 'batch-c' => [ 'driver' => 'daily', 'path' => storage_path('logs/batch-c.log'), 'level' => env('LOG_LEVEL', 'debug'), 'days' => 30, 'permission' => 0777, 'ignore_exceptions' => false ], ] ~省略~ BatchA.php <?php namespace App\Console\Commands; use Illuminate\Console\Command; use Illuminate\Support\Facades\Log; class BatchA extends Command { ~省略~ public function handle() { Log::setDefaultDriver('batch-a'); 処理 } } これでBatchAからのログ出力にはbatch-aチャンネルが利用されlogs/batch-a.logへログが出力されます。 ※BatchB、Cも同様です。 下記のようにログ出力するたびにチャンネルを指定する方法もあるようですが、 いちいちチャンネルを指定するのは面倒だったので上記のようにsetDefaultDriverを利用しています。 Log::channel('batch-a')->info('Something happened!'); また、下記のようにすればlogging.phpへ設定を行わなくてもログの設定ができるようですが、 この設定をsetDefaultDriverのように全体に反映する方法が見つからなかったため断念しました。 Log::build([ 'driver' => 'daily', 'path' => storage_path('logs/batch-a.log'), 'level' => env('LOG_LEVEL', 'debug'), 'days' => 30, 'permission' => 0777, 'ignore_exceptions' => false ])->info('Something happened!'); CloudWatchエージェントを使用してEC2からログを送る ここまででログの分離は完了したので、そのログをCloudWatch Logsへ連携していきます。 EC2のロールへ「CloudWatchLogsFullAccess」ポリシーを追加 対象となるインスタンスがCloudWatch Logsにアクセス可能とするために、EC2に割り当てるIAMロールを作成します。 こちらを参考に行いました。 EC2へssh接続しCloudWatchエージェントをインストール 以下のコマンドを実行しCloudWatchエージェントをインストールします。 $ wget https://s3.amazonaws.com/amazoncloudwatch-agent/ubuntu/amd64/latest/amazon-cloudwatch-agent.deb $ sudo dpkg -i -E ./amazon-cloudwatch-agent.deb $ sudo amazon-cloudwatch-agent-ctl -a start CloudWatchエージェントの定義ファイルを編集 ログファイルを転送する設定を書いていきます。 $ sudo vi /opt/aws/amazon-cloudwatch-agent/etc/amazon-cloudwatch-agent.d/default バッチのログだけでなく、API側のログやnginxのログの転送設定も行いました。 { "agent": { "run_as_user": "root" }, "logs": { "logs_collected": { "files": { "collect_list": [ { "file_path": "/アプリのパス/storage/logs/laravel*log", "log_group_name": "api-laravel-log", "log_stream_name": "ec2-{instance_id}-laravel-log" }, { "file_path": "/アプリのパス/storage/logs/batch-a*log", "log_group_name": "batch-laravel-log", "log_stream_name": "ec2-{instance_id}-batch-a-log" }, { "file_path": "/アプリのパス/storage/logs/batch-b*log", "log_group_name": "batch-laravel-log", "log_stream_name": "ec2-{instance_id}-batch-b-log" }, { "file_path": "/アプリのパス/storage/logs/batch-c*log", "log_group_name": "batch-laravel-log", "log_stream_name": "ec2-{instance_id}-batch-c-log" }, { "file_path": "/var/log/nginx/api.log", "log_group_name": "api-nginx-log", "log_stream_name": "ec2-{instance_id}-nginx-log" }, { "file_path": "/var/log/nginx/api-error.log", "log_group_name": "api-nginx-error-log", "log_stream_name": "ec2-{instance_id}-nginx-error-log" }, { "file_path": "/var/log/php7.4-fpm.log", "log_group_name": "php-fpm-log", "log_stream_name": "ec2-{instance_id}-php-fpm-log" } ] } } } } CloudWatchエージェント再起動,ステータス確認 $ sudo /opt/aws/amazon-cloudwatch-agent/bin/amazon-cloudwatch-agent-ctl -m ec2 -a stop $ sudo /opt/aws/amazon-cloudwatch-agent/bin/amazon-cloudwatch-agent-ctl -m ec2 -a start ログがCloudWatchLogsに転送されているか確認 AWSマネージメントコンソールへサインインし、 CloudWatch Logs > ロググループ > batch-laravel-log を確認。 バッチごとにLog Streamが別れていることが確認できました! 最後に 定義ファイルをバッチごとに書かなくてはならないので、 1つの定義でいい感じに設定する方法を模索中。 知っている方いたら是非教えて下さい。
- 投稿日:2022-03-22T23:26:11+09:00
Transcribe ではやぶさ2記者会見を文字起こししてみた
専門用語多く含む宇宙科学分野の内容を Transcribe で文字起こしするとどうなるか試しました。 また、カスタム語彙を追加した場合も試しました。 まずは普通にやってみる Input Data YouTube に公開された下記の記者会見動画のうち 4:26 以降、約 5 分間の音声を使用。 QuickTime Player で録音して iTunes で .m4a から .mp3 ファイルに変換。 【録画】小惑星探査機「はやぶさ2」の記者説明会(22/1/13) カスタム語彙なしの場合の結果 文字起こし結果全文 はい では スタート いたし ます 本日 は あの 記者 会見 として えっ と カタログ の えー 話 を し、 たい と 思い ます 皆さん お 集まり いただき まし て どうも ありがとう ござい ます えー 内容 と いたし まし て は 二 千 二 十 二 年 の 一月 十 三 日 つまり 本日 初 の 資料 の カタログ を 世界 に 向け て 一般 公開 え する という こと に なり まし た ので その お話 詳細 について ご 説明 差し上げ ます え ポイント は あ ここ に ある よう に 四つ あり ます 一つ 目 は えー サンプリング 三 次元 サンプリング え 人口 くれ た から の 物質 を 含む 表面 および 地下 物質 を、 含む 物質 が 記載 さ れ た カタログ で ある という こと そして その カタログ を 作る 時 に 我々 で 行っ て いる 布 ション 作業 で は サンプル を 編成 さ せ ず に 寄与 先 非破壊 非 暴露 の 条件 で 作成 さ れ た もの で ある という こと 三つ、 目 は その カタログ に 乗せ られ た 粒子 という の が あ 実際 の りゅう ぐう の 詳細 な 地質 図 と ひも 付け られ て いる という こと で 最後 四 点 目、 です けれども これから 現在 進行 し て いる 詳細 な 科学 分析 から 得 られる 科学 成果 を 担保 する ため に 作成 さ れ た カタログ で ある という こと を この、 四 点 を 順次 説明 し て いき たい と 思っ て おり ます で え? 田崎 運用 の 状況 に関して は え? 拡張 ミッション の 運用 継続 中 という こと それから 日本 エンジン ノルマ 運転 を 達成 し て い ます という こと です けれども こちら に関して は えーと 参考 資料 を ご 参照 ください 今日 は あ 目次 で 言う と 一番 と 二 番 優遇 資料 の カタログ の 詳細 を 渡し それ から ヤダ 岡田 の 三 名 で ご 説明 いたし ます で その後 今後 の 予定 に 着い て、 薄い が 説明 し て いき たい と 思い ます さて 最初 の ポイント 三 次元 サンプル による 小惑星 表面 及び 地下 物質 を 含む 物質 が 記載 さ れ た カタログ で ある という こと を これ どういう こと か と 言い ます と 記者 の 皆さん 御存じ だ と 思い ます けれども 危う さ つ で は 衝突 装置 を 使っ て 人工 クレーター を 形成 し、 その 付近 から えー サンプル を 採取 する こと に 成功 いたし まし た で それ を 含め て それ は 二 回 目 の タッチダウン で サンプル 採取 し た。 ん? です けど それ を 含め て 異なる 場所 第 一 回 目 の タッチダウン、 第 二 回 目 の タッチダウン 異なる 場所 として 人工 クレーター を 使っ て 異なる 深 さ から え 回収 さ れ た 資料 で ある という こと が ポイント に なっ て い ます えー 特に 深 さ な ん です けれども 小惑星 は 宇宙 線 や 太陽 風 など の よう に 影響 によって え 宇宙 風化 という プロセス を 経 て おり ます 地下 物質 は その 影響 が ああ ああ 小さい の で は ない か という 可能 性 を 秘め て い て とても 貴重 な 物質 で ある 可能 性 が 高い という こと が ポイント に なっ て いる ただし せっかく そう やっ て 二つ の 場所 から 異なる 場所 異なる 深 さ から 回収 さ れ た 物質 を 探査 機 が 取っ て 帰っ て き て も それ が 混ざっ て しまっ て は え? しょうが ない 訳 で え? はや ぶさ つ で は? え? サンプラ カプセル の 中 が え 三つ の 部屋 が 三つ の 部屋 に 区切ら れ て い て その 中 の シリンダー が 回転 する こと で? え え プレゼン の 部屋 の 資料 を 確立 し て いる 訳 です で 一 回 目 の タッチダウン に関して は 一番 大きな 絵 という 部屋 に 物質 が あ 入っ て おり 二 回 目 の タッチダウン ええ 人工 クレーター の 付近 で 採取 さ れ た 二 回 目 の タッチダウン の シ ステ 言わ れる と また 別 の 部屋 に えー サンプル が 開い て いる いっ た 状況 に なっ て い て これら が 区別 さ れ て 帰還 し て 当然 区別 さ れ た 形 で キュレーション 活動 が 進ん で おり ます え? さて ここ から は キュレーション グループ の 皆さん に 発表 映る わけ です けれども その 前 に 私 から ちょっと 一言 え エース と は 進出 それぞれ 異なる 場所 から あ 持っ て 帰っ て き た 資料 を 混ぜる と 意味 が ない という こと です けど 混ぜる だけ で は なく て これから 科学 分析 を する にあたって カタログ を 作り まし て カタログ という の は ポイント に なる の は え? 費用 船 非破壊 非 暴露 で 作ら れ なけれ ば いけ ない とか あ そう する こと によって えー これから そして 現在 進行 中 の え 科学 自分がさっと確認した限り、約 380 語中、下記の 20 語は、 人間(私)が聞き取った結果と差異があった。 Transcribe(カスタム辞書なし) 人間(私)聞き取り 初 リュウグウ くれ た クレーター 布 ション キュレーション 編成 変成 寄与 先 非汚染 田崎 探査機 ヤダ 矢田 薄い 臼井 危う さ つ はやぶさ2 いる います はや ぶさ つ はやぶさ2 ABC プレゼン それぞれ 絵 A室 シ ステ C室 エース A室 進出 C室 資料 試料 費用 船 非汚 まとめると、 「はやぶさ2」「(サンプラーの)A室」や人名などの固有名詞 「キュレーション」「非汚染」などの一般的でない用語 「資料/試料」「編成/変成」など文脈で変換が変わる漢字 などで差異が生じている印象だった。 カスタム語彙を使ってみる カスタム語彙作成 固有の用語が正しくレンダリングされない場合には、 カスタム語彙を使えば認識してもらえるかもと思い追加してみる。 固有名詞や用語、発表に登場する人物名を追加してみる。 (先生方呼び捨てですみません...) custom-vocabulary-hyb2.txt Phrase SoundsLike IPA DisplayAs はやぶさつう はやぶさ2 はやぶさつー はやぶさ2 きゅれーしょん キュレーション ええしつ A室 えーしつ A室 びいしつ B室 びーしつ B室 しいしつ C室 しーしつ C室 やだ 矢田 うすい 臼井 おかだ 岡田 警告 TAB 文字区切りなのでスペース区切りにならないよう注意 Transcribe コンソールの Custom vocabulary からファイルインポートして作成。 作成完了後、いったん Real-time transcription でカスタム語彙指定してリアルタイム書き出ししてみて効いてそうか試してみる。 (Real-time の方で「はやぶさ2」「A室」など認識されることを確認) カスタム語彙ありの場合の結果 文字起こし結果全文 はい では スタート いたし ます 本日 は あの 記者 会見 として えっ と カタログ の えー 話 を し たい と 思い ます 皆さん お 集まり いただき まし て どうも ありがとう ござい ます えー 内容 と いたし まし て は 二 千 二 十 二 年 の 一月 十 三 日 つまり 本日 初 の 資料 の カタログ を 世界 に 向け て 一般 公開 え する という こと に なり まし た ので その お話 詳細 について ご 説明 差し上げ ます え ポイント は あ? ここ に ある よう に 四つ あり ます 一つ 目 は えー サンプリング 三 次元 サンプリング え 人口 くれ た から の 物質 を 含む 表面 および 地下 物質 を、 含む 物質 が 記載 さ れ た カタログ で ある という こと そして その カタログ を 作る 時 に 我々 で 行っ て。 いる キュレーション 作業 で は サンプル を 編成 さ せ ず に 寄与 先 非破壊 非 暴露 の 条件 で 作成 さ れ た もの で ある という こと 三つ、 目 は その カタログ に 乗せ られ た 粒子 という の が あ 実際 の りゅう ぐう の 詳細 な 地質 図 と ひも 付け られ て いる という こと で 最後 四 点 目、 です けれども これから 現在 進行 し て いる 詳細 な 科学 分析 から 得 られる 科学 成果 を 担保 する ため に 作成 さ れ た カタログ で ある という こと を この、 四 点 を 順次 説明 し て いき たい と 思っ て おり ます で え? 田崎 運用 の 状況 に関して は え? 拡張 ミッション の 運用 継続 中 という こと それから 日本 エンジン ノルマ 運転 を 達成 し て い ます という こと です けれども こちら に関して は えーと 参考 資料 を ご 参照 ください 今日 は あ 目次 で 言う と 一番 と 二 番 優遇 資料 の カタログ の 詳細 を 渡し それ から 矢田 岡田 の 三 名 で ご 説明 いたし ます で その後 今後 の 予定 に 着い て、 臼井 が 説明 し て いき たい と 思い ます さて 最初 の ポイント 三 次元 サンプル による 小惑星 表面 及び 地下 物質 を 含む 物質 が 記載 さ れ た カタログ で ある という こと を これ どういう こと か と 言い ます と 記者 の 皆さん 御存じ だ と 思い ます けれども はやぶさ2 で は 衝突 装置 を 使っ て 人工 クレーター を 形成 し、 その 付近 から えー サンプル を 採取 する こと に 成功 いたし まし た で それ を 含め て、 それ は 二 回 目 の タッチダウン で サンプル 採取 し た。 ん? です けど それ を 含め て 異なる 場所 第 一 回 目 の タッチダウン、 第 二 回 目 の タッチダウン 異なる 場所 として 人工 クレーター を 使っ て 異なる 深 さ から え 回収 さ れ た 資料 で ある という こと が ポイント に なっ て い ます えー 特に 深 さ な ん です けれども 小惑星 は 宇宙 線 や 太陽 風 など の よう に 影響 によって え 宇宙 風化 という プロセス を 経 て おり ます 地下 物質 は その 影響 が ああ ああ 小さい の で は ない か という 可能 性 を 秘め て い て とても 貴重 な 物質 で ある 可能 性 が 高い という こと が ポイント に なっ て いる ただし せっかく そう やっ て 二つ の 場所 から 異なる 場所 異なる 深 さ から 回収 さ れ た 物質 を 探査 機 が 取っ て 帰っ て き て も それ が 混ざっ て しまっ て は え? しょうが ない 訳 で え はやぶさ2 で は? え? サンプラ カプセル の 中 が え 三つ の 部屋 が 三つ の 部屋 に 区切ら れ て い て その 中 の シリンダー が 回転 する こと で? え え プレゼン の 部屋 の 資料 を 確立 し て いる 訳 です で 一 回 目 の タッチダウン に関して は 一番 大きな 絵 という 部屋 に 物質 が あ 入っ て おり 二 回 目 の タッチダウン ええ 人工 クレーター の 付近 で 採取 さ れ た 二 回 目 の タッチダウン の シ ステ 言わ れる と また 別 の 部屋 に えー サンプル が 開い て いる いっ た 状況 に なっ て い て これら が 区別 さ れ て 帰還 し て 当然 区別 さ れ た 形 で キュレーション 活動 が 進ん で おり ます え? さて ここ から は キュレーション グループ の 皆さん に 発表 映る わけ です けれども その 前 に 私 から ちょっと 一言 え A室 と は 進出 それぞれ 異なる 場所 から あ、 持っ て 帰っ て き た 資料 を 混ぜる と 意味 が ない という こと です けど 混ぜる だけ で は なく て これから 科学 分析 を する にあたって カタログ を 作り まし て カタログ という の は ポイント に なる の は え? 費用 船 非破壊 非 暴露 で 作ら れ なけれ ば いけ ない とか あ そう する こと によって えー これから そして 現在 進行 中 の え 科学 カスタム語彙あり/なしを比較するとこんな感じ。 (変化のないものは省略しています) Transcribe(カスタム語彙なし) 人間(私)聞き取り Transcribe(カスタム語彙あり) 初 リュウグウ くれ た クレーター 布 ション キュレーション キュレーション 編成 変成 寄与 先 非汚染 田崎 探査機 ヤダ 矢田 矢田 薄い 臼井 臼井 危う さ つ はやぶさ2 はやぶさ2 いる います はや ぶさ つ はやぶさ2 はやぶさ2 ABC プレゼン それぞれ 絵 A室 シ ステ C室 エース A室 A室 進出 C室 資料 試料 費用 船 非汚 「はやぶさ2」と人名は改善された。 この検証の結果を踏まえると、 自分なら長時間の文字起こしをするなら はじめに一部だけ Transcribe にかけてどの用語が拾われなさそうかあたりをつける それを参考にカスタム語彙とか準備して使う みたいなことをしそう。登録語数とか限りがあるので、無理そうなら他の Speech-to-Text サービスとかも検討するとかするかも。
- 投稿日:2022-03-22T22:25:50+09:00
AWS CDK v1(TypeScript)でVPC作成時のAZを指定する
概要 AWS CDKでVPCと同時にサブネットを作成するとき、AZが自動で選択されてしまう 旧AZ(apne1-az3)1ではできないことがいくつかあるため、AZを指定したい 実行環境 :~ $ cdk version 1.148.0 (build 69a50f1) 解決方法 availabilityZones()を、指定したいAZ名を返すようにオーバーライドする こんな感じ import * as cdk from '@aws-cdk/core' import * as ec2 from '@aws-cdk/aws-ec2' export class MyStack extends cdk.Stack { constructor(scope: cdk.Construct, id: string, props?: cdk.StackProps) { super(scope, id, props); new ec2.Vpc(this, 'VPC', { cidr: '10.0.0.0/16', subnetConfiguration: [ { cidrMask: 24, name: 'subnet-test', subnetType: ec2.SubnetType.PRIVATE_ISOLATED, }, ] }) } get availabilityZones(): string[] { return ['ap-northeast-1a', 'ap-northeast-1c']; } } AZ名ではなくAZ IDで書いている。AZ IDについてはこちらを参照 ↩
- 投稿日:2022-03-22T21:37:47+09:00
新卒クラウドエンジニアの1年間を振り返ってみる③
昨日の記事の続きです 1、2月(覚醒期) 年が明けて2022年、ようやく覚醒期を迎えることが出来ました。 実を言うと2021年はプライベートの時間にJavaScriptやRubyなどのプログラミング言語の学習も並行でしていたのですが、なかなか継続的に続かず週に合計4~5時間がようやくという感じでした。結果として勉強は中途半端になりプログラミングスキルは身に付かず、クラウド知識も身に付くのが遅れてしまいました。 何故クラウドエンジニアなのにプログラミング言語の勉強をしていたかと言うと、自分もサービス開発をしたい思いがあったからです。 ですが時間は有限で、したいことを全部するにはあまりにも時間が足りません。 なので2022年の目標は「やるべきこと以上にやらないことを決断すること」としました。 そこで一旦プログラミング言語を学習するのは辞めて、1~2月はAWSの勉強だけに絞ることにしました。 その結果、以前とは比べ物にならないくらいAWSを理解し始め、少しずつですが自信が漲ってきました。 仕事にもどんどん勢いが出てきて、積極的にプロジェクトの改善案等を提案をするようになり、最終的にアカウント運用ルールや移行先の設計・構築もほとんど1人で完成させることが出来ました。 この2ヶ月ほどで色んな環境の設計・構築を行い、苦手だったネットワークの知識(エンドポイントやNATゲートウェイ、ドメイン周りや疎通確認など)やCI/CDも理解できるようになりました。 そんなこんなで2月末に案件が一段落し、完了まで持って行けたことは大きな自信に繋がりました。 3月(現在) 現在は4月から参画する案件の学習をしており、以下のスキルに携われるので非常に楽しみにしています。 ・GCP ・Docker、Kubernetes ・CI/CD ・Terraform 特にGCPを経験することで各クラウドサービスの比較が出来るようになり、より一層クラウドの理解が進むのではないかと思っています。 Terraformも少し前に勉強を始めてブログを書いたところ、すぐに案件で使えることになったので協力していて頂いた上司の方には感謝しきれません。 また約半年間の内定者研修も無事に終えました。 下半期も業務やプライベートが大変だった中で後輩の教育を全う出来たことは嬉しく、彼らの入社を非常に楽しみにしています。 内定者研修では他の社員の方と研修の改善点を話し合ったり、積極的にサブリーダー的働きをしたりと「チームの為にできること」を常に考えましたし、後輩の教育という目的に対して自分がどのような行動をすればいいのかを学ぶことが出来ました。 1年間を振り返って 人間の成長曲線は直線ではないことは多くの人がご存知だと思います。 ですがこの事実を知っていても、いざ自分がなかなか成長しないと不安と焦りでしんどくなります。それでも是非もがいて頂きたいです。 偉そうなことを言いつつ、僕自身エンジニア歴1年でこれから何度も壁にぶつかると思いますが、この一年の経験を糧に乗り越えていきたいです。 話は変わりますが、この一年はプライベートで勉強を頑張りつつもコロナに罹ったり、ポーカーにハマったり、仲の良い人と旅行に行ったりと結構充実していましたが、出来なかったことも多いです。 そこで社会人2年目で挑戦したいことを以下に記します。 ・本格的な後輩の教育経験。教えることで自分の中で言語化できなかったことが理解できるようになるし、個人ではなくチームを強化する力を養える。 ・アウトプットの量を増やす。1年目は主にブログの執筆にとどまったが、2年目からは外部で勉強会を主催で開き、AWSを中心にLTやハンズオンをしてみたい。 ・案件を通じてDevOpsエンジニアのスキルを身につける(ポートフォリオ作成も出来ればいいなあ)。 ・自分が将来的に何をやりたいか、何が幸せかを探す。 またこの一年で学んだことを以下に記します。 ・プライベートでの勉強は業務に関することを最優先。業務にあまり関係ないことは多少勉強しても身につきにくい。 ・勉強を頑張りつつも、プライベートの思い出作りも妥協しない。 ・出来ることからチームメンバーに与えられるものがないか意識する。Giverになることでチームへの帰属意識が高まり、貢献している感覚がメンタルの安定をもたらす。 以上です、もし社会人1年目で大変なことがあったらこの記事を思い出していただけると幸いです。
- 投稿日:2022-03-22T20:53:40+09:00
【SAA-C02】実務経験なしで9日間でAWSソリューションアーキテクトアソシエイト認定試験に合格した体験記
この記事は何か。 9日間(日曜日夕方に開始して丸一週間+月、火曜日)でAWSソリューションアーキテクトアソシエイト認定試験に合格できたので、その体験記です。ちなみに、私自身は、エンジニア職ではありますが、コーディングから離れて1年半、今はシステムエンジニア兼プロジェクトマネージャ的なポジションで仕事をしています。 ですので、情報処理的な素養はありつつ、AWSやAzure、GCPといったプラットフォームに触ったことがない人が、リアルタイムアタック的に受けるとこんな感じ、みたいな参考にして頂ければと思います。 様々な方が様々なエントリを書かれていたので記事を書いてみようかなと思えました!先駆者の方々の取り組み方は非常に参考になりました。ですので、この記事もその中の一つに入れていただけると幸いです。(あと、初めての記事なので反応貰えると嬉しいです……) 受験動機 簡単にいうと危機意識です。手元にある技術といえば、コーディング(UML書けますとか、テスト技法解ります、C++11/14使ってました)、OOP(デザインパターンがわかりますとか)とかで何か証明できるようなものが薄いな、と。あとはプロジェクトマネジメントの基本とドメイン知識に寄っていたので、これまずくねという気持ちが芽生えました。 そこで、プラットフォームの中で一番流行ってそうな「AWS」の知識をつけ、せっかくなら証明しよう!というのが動機です。 直接、今の職務で使うかは微妙ですが資格者がいるなら使ってみようになるかもしれませんし。 何をやったか Day1-3 書籍を購入して、ひたすら読む。この書籍、模擬試験を除けば、274ページしかないので、日曜2時間、月曜日の移動中で大体読み切れる分量でした。目的は、どこにどんな用語が書いてあるかを知ることです。テスト勉強は割と得意だったので、1周目は詰まっても何してもとりあえず流して、どこに何が書いてありそうかを把握して、すぐ問題演習に行ったほうがいいのはいつものこと。月曜日の最後に、巻末の模擬試験を実施して合格割合の72%にはちょっと届かないくらいです。 Day4-6 これをやりました。 【2022年版】AWS 認定ソリューションアーキテクト アソシエイト模擬試験問題集(6回分390問) https://www.udemy.com/course/aws-knan/ 難しいと書いてある通り、無茶苦茶難しかったです。ただ、書籍の模擬試験と違って、Udemyのアプリをポチポチすればいいので、1日につき2回分ずつ、行き帰りでやっていきました。この時も正答率は全く気にしてません。凹みましたが。ただ、6回分のうち①以外は高難易度と書いてある通りで、1セット目だけ正答率が確かに高かったので、逆に信用できましたね。 この辺りで、体感的にも以下の4分野とそれ以外に分けて勉強したほうが効率がいいということに気づいたので、間違えた問題のみを分野ごとに表示して覚えました。ひたすらと言いつつ、BlackBelt/マニュアルを読んだのがよかったですね。 EC2 データベース関連(DynamoDB、Aurora、Redshift、Athena、EMR) ストレージ関連(S3、EBS、EFS、FSx) VPC この「分析」は絶対にやった方が良いです。人によって違うと思うので。私の場合には特にS3が苦手でした。イメージが湧かないというかなんというか。触っていれば違ったのかもしれませんが。逆にECSとFargateの組み合わせみたいなのは、AWSでは触ったことがないまでも、Dockerをオンプレでやる面倒臭さみたいなのがあったので、ああいいサービスとか思えました。 ちなみに、読んだBlackBeltとかはこういうのです。一部だけ抜粋します。ただ、これを最初に読んでも???だったと思うので、問題を解いて、じゃあ本当にどうやって使うのさ?ってなってからの方が面白味もあっていいんじゃないかと思います。 注意点として、BlackBeltは検索で引っかかるものが少し古い可能性があります。例えば、EC2のインスタンスの種別というか、確保方法は2019から2022にかけて変わっています。そこは調べながらじゃないとダメですね。逆に言うと、問題を解いて乖離があったらどっちが正しいか確認する癖があるといいと思います。個人的にはAWS、凄い進化スピード早いんだなって思いました。 Day7-8 Day6でやった分析をもとにBlackBeltと模試解説→模試周回を繰り返しました。最終的には3周やりました。下に正答率の推移を示します。 テスト番号 正答率1回目 同2回目 同3回目 同4回目(③のみ) テスト① 58 76 83 - テスト② 35 66 72 - テスト③ 36 61 66 78 テスト④ 53 58 70 - テスト⑤ 44 47 63 - テスト⑥ 44 53 49 - 見てわかる通り、目安の72%を超えているのは3回分だけです。でも、ここまでくると問題を覚えて決まっているので、4回目は全部回るのはやめました。 Day9 当日なので、半分諦めつつ、最後まで間違え続けた問題の見直しと最初に買った本の見直しをしました。最初に買った本をここで見直すのは、問題に特化しすぎた部分を微修正する意味がありました。 で、そのまま受けてきて合格!これを書いている時に合格証も届き、781/1000でした。結構ギリギリですね。 ちなみに、ここまでにかかった勉強のためのお金は、書籍代2380円+Udemyの模試1200円(セール価格)です。 最後に せっかくSAAを取ったら3冠を狙いたいもの…。次はDVA(デベロッパーアソシエイト)を受けようと思います。頑張ります。ただ、このままだとペーパーAWSドライバーになってしまうので、Twitter botでも作ろうかなとか思ってます。
- 投稿日:2022-03-22T18:40:33+09:00
CloudFormationで作成したIAMポリシーのステートメント内のプロパティはいつも同じ順番になる/コンソールで作ったものとも順番が異なる
はじめに IAMポリシーのステートメント内のプロパティの順番について、IAMポリシーを作成する方法が異なるとその順番も異なるということに気が付きました。 前提 CloudFormationのテンプレートでステートメント内のプロパティを以下のようにしたとします。 myPolicy1: Sid, Action, Effect, Resource の順に記述 myPolicy2: Sid, Effect, Action, Resource の順に記述 テンプレート ActionやResourceは適当な内容にしています。 AWSTemplateFormatVersion: "2010-09-09" Resources: Policy1: Type: AWS::IAM::ManagedPolicy Properties: ManagedPolicyName: myPolicy1 PolicyDocument: Version: "2012-10-17" Statement: # Sid, Action, Effect, Resource の順に記載 - Sid: myPolicy1 Action: - ec2:* - s3:* Effect: Allow Resource: "*" Policy2: Type: AWS::IAM::ManagedPolicy Properties: ManagedPolicyName: myPolicy2 PolicyDocument: Version: "2012-10-17" Statement: # Sid, Effect, Action, Resourceの順に記載 - Sid: myPolicy2 - Effect: Allow Action: - ec2:* - s3:* Resource: "*" スタックを作成して、実際に出来上がったIAMポリシーを見ると、ステートメント内のプロパティの順番はテンプレートに書いた通りの順番とはならず、上記のテンプレートで記載した4つのプロパティの場合はAction, Resource, Effect, Sidの順になります。 myPolicy1 { "Version": "2012-10-17" "Statement": [ { "Action:" [ "ec2:*", "S3:*" ], "Resource": "*", "Effect": "Allow", "Sid": "myPolicy1" } ] } myPolicy2 { "Version": "2012-10-17" "Statement": [ { "Action:" [ "ec2:*", "S3:*" ], "Resource": "*", "Effect": "Allow", "Sid": "myPolicy2" } ] } AWS管理コンソールで作成した場合 なお、AWS管理コンソールでIAMポリシーを作成すると、以下のようになります。 { "Version": "2012-10-17" "Statement": [ { "Sid": "VisualEditor0", "Effect": "Allow", "Action:" [ "S3:*", "ec2:*" ], "Resource": "*", } ] } 何故このようなことを確認しようと思ったか? テンプレートでIAMポリシーを作成する前に、AWS管理コンソールを操作して作成してあったIAMポリシーがありました。そのIAMポリシーをテンプレートに記載して、スタックに含めておいてほしいという要望があり、対応をしました。両者は同じAWSアカウント上に作っています。 AWS管理コンソールで作成したIAMポリシーは試作で、試作した結果を受けてスタックに取り込んでほしいという要望でした。 それでスタックは無事に作成でき、テンプレートからIAMポリシーを作成できたのですが、その後で「スタックで作ったIAMポリシーの内容が違う」と言われました。 そう言われて内容を確認したところ、ポリシーとしては何も違うところはなかったのですが、ステートメント内のプロパティの順番が両者で異なっていたのです。「スタックで作ったIAMポリシーの内容が違う」と述べた人は、プロパティそのものの内容までは見ておらず、プロパティの順番・見た目が違うだけで両者の内容が違うと言っていたことがわかりました。 その人はAWSに触れて日が浅かったために、単に見た目が違うというだけでそれぞれのポリシーは別物だと判断されてしまったのですが、見た目が違っていたのは確かだったので、それで調べてみたということでした。
- 投稿日:2022-03-22T18:22:26+09:00
AWS Certified Data Analytics - Specialty(DAS) を取得しました
はじめに AWSの資格を毎年1~2個取得していますが、AWS Certified Data Analytics - Specialty(DAS)にチャレンジしてみました。 取得済みの資格は下記の通りとなります。 CLoud Practitioner Developer Associate Solutions Architect Associate SysOps Administrator Associate DevOps Engineer Professional Solutions Architect Professional Advanced Networking Specialty Security Specialty AWS Certified Data Analytics - Specialty(DAS) とは この辺を参照ください。 教材 Udemy:AWS Certified Data Analytics Specialty 2022 - Hands On! 講義+問題集です。 全て英語です。 データ分析関係のAWSサービスの基礎を学ぶことができます。 問題集はやや古く、且つ通常の試験よりも難易度が低いと思います。 Udemy:AWS Certified Data Analytics Specialty Practice Exams 100問の問題集です。 全て英語です。 上記よりも若干難易度高めです。より試験に近い難易度かと思います。 試験問題サンプル 公式の試験問題サンプルです。 Exam Readiness: AWS Certified Data Analytics – Specialty-A2T 公式の講義+問題集です。 AWS Certification Official Practice Question Sets 公式の模擬試験です。 無償となり、DAS以外も受けることができます。 受験までの流れ 仕事がとても忙しいこともあり、2カ月弱かけて勉強しました。上記各試験の正答率が100%になってから試験に挑みました。 最初は自宅で受けましたが、音声が届かない&試験アプリが起動するとCPU高負荷となると言った、システムトラブルによりキャンセルとなりました。2回目は近くの試験会場で受けました(再度システムトラブルになるのを避けたかったため)。 試験では、1週目は80分、2週目(見直しフラグの確認)は30分の計110分程要しています。 感想 難易度はやや高く、上記教材と同じような問題は3割程度、よく考えれば分かるが4割、でした。普段扱っていないと分からないような細かい設定の問題もありました。 上記教材ではカバーできていないサービスも登場しています。 次は、Database SpecialtyかMachine Learning SpecialyかCKS(Certified Kubernetes Security Specialist)を狙っていますが、初めて触る別のクラウドを扱う仕事を担当することになったため、そちらのキャッチアップに精一杯で難しいかもしれません。
- 投稿日:2022-03-22T16:58:47+09:00
【AWS】buildspec.ymlとは
buildspec.ymlとは buildspec.ymlとは、ビルド実行時に実行するコマンドを記述したYAML形式のファイルのこと。 このファイルをソースコードのルートディレクトリに配置することでCodeBuildがbuildspec.ymlを読み込んで実行される。 CodeCommitを使用する場合は、リポジトリのルートディレクトリに配置する。 buildspec.ymlには以下のような項目が記述される。 version これは必須項目でbuildspecのバージョンを指定する。参考文献では0.2が推奨されていた。 version: 0.2 env これはオプションの項目で環境変数を設定する。DB接続に関する情報などを設定したりする。 env: <環境変数名>:<値> phases これは必須項目でビルド実行時にCodeBuildが実行するコマンドを記述する。 また、CodeBuildではフェーズごとに実行する内容を以下のように分けることができる。 ■ install インストールの際にCodeBuildが実行する必要なコマンドを記述する。 ■ pre_build build前にCodeBuildが実行する必要なコマンドを記述する。 ■ build build実行中にCodeBuildが実行する必要なコマンドを記述する。 ■ post_build build後にCodeBuildが実行する必要なコマンドを記述する。 例 phases: pre_build: commands: - <コマンド> artifacts ビルドの出力結果に関するデータの保存先情報を記述する。 ■ files これは必須項目でビルド環境でのビルド出力アーティファクトを含む場所を表す。 参考 今回は自分が使った項目だけをまとめたが、他の項目や詳細は以下を参照。 https://docs.aws.amazon.com/ja_jp/codebuild/latest/userguide/build-spec-ref.html
- 投稿日:2022-03-22T16:56:23+09:00
ADOPをAWSのubuntuで動かす(ただしカクカク)
フォトグラメトリのADOPをAWSで動かすことに成功したので備忘メモ ADOPとは 以下です。 https://github.com/darglein/ADOP フォトグラメトリのライブラリで、NvidiaのGPUが載ったubuntu18とubuntu20に対応しています。 これをAWSで動かそうと悪戦苦闘したら動いたので報告 動作環境 動作確認環境は、 g3.4xlargeとg4dn.4xlarge。 ubuntu 20.04で動作確認。18では動作確認してません。 ハマリポイント NICE DCVでUbuntuに繋ぐ必要がある これは使用するOpenGLの問題で、RemoteDesktop(RDP)でつなぐとどうしてもOpenGLがMesaになってしまってうまく動作してくれない。 最初、MacからRDPでアクセスしても最後の最後でOpenGLエラーで動かなくなってしまっていたが、 Ubuntu内にNICE DCVサーバを立てて、NICE DCVでつなぐと、NvidiaのOpenGLが動いてくれる。 以下を参考にしながらインストールすると良い。 https://docs.aws.amazon.com/ja_jp/dcv/latest/adminguide/setting-up-installing.html Adop viewerがビルドされないときはライブラリが足りない このIssueが役に立つ https://github.com/darglein/ADOP/issues/43 以下を入れると生成される。 sudo apt install qtbase5-dev qttools5-dev-tools qt5-default LD_LIBRARY_PATHはフルパスで指定する README( https://github.com/darglein/ADOP/tree/main/src )には以下にように指定するように書いてあるが export LD_LIBRARY_PATH="${LD_LIBRARY_PATH}:~/anaconda3/envs/adop/lib #動かない可能性あり このままでは動作しなかった。 正しくは以下のように指定する必要がある([user]部分はご自身の環境に合わせて書き換えてください) export LD_LIBRARY_PATH="${LD_LIBRARY_PATH}:/home/[user]/anaconda3/envs/adop/lib 上記の3つのポイントを押さえると、うまく動かすことができます。 (ただし動作はカクカクです) インストール手順 上記の注意点を押さえながら公式の手順に従ってインストールをしていけばOKです。 https://github.com/darglein/ADOP/tree/main/src ただ、ここに書かれていないこととして build_adop.shというファイルがあります。 これは、4.Build ADOP の部分を補完してくれるので、install_pytorch.shが済んだあとはbuild_adop.shを実行しちゃえばOKです。 実行 ビルドさえ済んじゃえば、あとは sceneとexperimentsをダウンロードしてきて配置し、書いてあるとおり実行すれば動作します。 ただし、実行するときはNICE DCVで接続することをお忘れなく NICE DCVでつなぐときは、SSHでubuntuにつなぎ、以下を実行 # サーバ起動 sudo systemctl start dcvserver # セッションの作成 (my-session部分は好きに変更可能) dcv create-session my-session できたら、NICE DCVを起動して 接続先を以下のようにする([ubuntu_ip]部分はご自身のEC2のIPにしてください) [ubuntu_ip]:8443#my-session すると、なんかのSSLの警告画面が出るのでTrustかProseedを選ぶとID/PASSを入力する画面が出るので 作成したユーザでログインすればOKです。
- 投稿日:2022-03-22T16:35:48+09:00
Fleet Managerを利用したWindowsインスタンスへのRDP接続
概要 SSM(AWS Systems Manager) Session Managerは以下の理由で便利なのでよく使っていた。 踏み台サーバ構築する必要ない ポート(22,3389)開く必要ない AWSコンソールかCLIベースでアクセスできる CloudTrailとかS3とかCloudWatch Logsにログ残せる ひと昔前の運用方式を考えてみると、踏み台サーバたてて、そこから各サーバに接続する方式が多いと思う。かくいう私もそのケースが多い。 だがしかし、踏み台ベースの運用って怖いものがあって、例えば踏み台サーバがSPOFになる事もままある。 そうすると障害が発生した時に踏み台も死んでると何もできないという運用にはあってはならない状況が発生してしまう。 かといって踏み台サーバを冗長化しておくっていうのも費用がかかってしまうのでやっているケースは少ない。 また、他の考慮点として操作ログをどのように取得して保存しておくのか?といった事を考慮して仕組みを作るのも手間だったりする。 LDAP連携とかするのもありだが、結局OSのローカルユーザ作ってログ取るみたいな運用したり、サードパーティのツール入れたりする。 正直そういう仕組み作り自体面倒であったり、ユーザが増えるにしたがって運用が追い付かなかったりする例もよくある。 こういった悩みを解決してくれるサービスとして Session Manager があり便利であるので利用していました。 しかしながら、Windows Serverってコマンドライン(Powershell)よりかはGUI使いたい時ってありますよね。 そんな悩みを解決してくれる手段として Fleet Manager があります。 ※結局ログ取る部分はFleet Managerでは現状解決できてなくて、Session Managerのコマンドベースの運用であればログ取れるのだが。 WindowsインスタンスへのSSM経由での接続方法 という訳で使ってみた。 1. SSMマネージドインスタンスとして設定する 以下を参考に管理対象のWindowsインスタンスがマネージドインスタンスとなるようにVPCエンドポイントの設定、EC2インスタンスのIAMロールの設定、Security Groupのアウトバウンドの設定を実施します。 順を追って設定する人向け 2. 鍵またはパスワード認証を用いて接続する 今回はEC2インスタンスを起動する時に指定したキーペアを用いて接続する Fleet Managerのコンソールから接続対象のインスタンスを選択してノードアクションからRDP接続を開始する パスワード認証か鍵認証か聞かれるのでどちらか選択して接続を開始する デフォルトだとセッションの有効期限は60分となっている 使ってみた感想 ポートフォワードして、、みたいなのが要らないので凄く便利だと思いました。 しかしながら、実運用で使う場合はちょっと考えなければならないな~と思うところも多々ありました。 現状はSession Manager(CUI)でログ取りながら操作=>どうしてもGUI使わないと、って時はFleet Managerかなと思いました。 メリット そもそも踏み台サーバが必要ない EC2インスタンスに直接接続できるので踏み台サーバいらない インスタンスにGIP要らない SSMの良いところで、パブリックIPを持っていないインスタンスにもFleet Manager経由で接続できる もちろんSession Manager経由でPowershellも使える ブラウザ経由でクリップボードのコピー&ペーストができる ローカル<=>リモート間双方向でのコピペができる インスタンスのインバウンドポートを一切解放しなくてよい 余計なセキュリティホールをつくらなくていい GIP変更に伴う穴あけ等が必要ない フルスクリーンでの作業も可能 ブラウザ経由のRDPでもフルスクリーン対応しているので小文字が苦手な人でも大丈夫 OS側のグループポリシーで2セッションまで有効化すると同じユーザでFleet Managerから2セッションまでは接続できる 2セッションの両方でWindowsOS内のブラウザを起動した場合、片方のユーザでプロセス掴んでいてEdgeが片方のセッションで上がらなかったりするので使用するアプリケーションによっては同じユーザでの接続は考慮する必要あり デメリット ブラウザ経由でのファイルの受け渡しはできない フリードマネージャー経由でファイルシステムの表示はできるのですが、ファイルの受け渡しは現状ではできないようです 操作ログが取れない Session ManagerであればPowershellでの操作履歴をS3やCloudWatch Logsに操作ログを取れるのですが、Fleet Managerの場合RDP接続での画面操作になるので何かしらツールを入れないとログを取れないみたいです。ここはアップデートしてほしいですね。 画面操作に若干ラグがある 人によっては気にならないかもしれないですがフルスクリーンにした時の画面操作(特に入力)の若干のラグが気になりました パフォーマンスカウンターでCPU使用率とか取得できるみたいですが、KMSで暗号化していないと機能が使えない KMSの暗号化キーがマネージドインスタンス共通みたいなのでインスタンス毎に分離できるようにできるともっといいと思いました
- 投稿日:2022-03-22T15:57:10+09:00
FrontISTRをAWS ParallelCluster バージョン3で利用する①
0. はじめに この記事は『非線形並列有限要素法』(2022, 丸善出版)の第8章の内容を参照できることが前提となっています.書籍に掲載されている内容と同じ部分については,記事中では省略します. 1. シリーズの流れ ParallelCluster バージョン3用のカスタムAMIの作成 (この記事) ParallelCluster バージョン3用の設定ファイルの作成〜起動 Slurmを利用したFrontISTR並列実行 (準備中) 2. FrontISTRを導入したEC2インスタンスの作成 書籍8.1節のp. 205〜p. 220「S3バケットの作成」までは完了しているとして,p. 221「ParallelCluster用のEC2を作成」の部分を扱っていきます. ParallelClusterのカスタムAMIは,バージョンが更新されるごとに新たなものを作成しなくてはなりません.1書籍のサポートリポジトリで提供されているAMIはv2.11.1のものですので,バージョン3用には自身でAMIを作成する必要があります. 2.1. ベースとなるAMIの選択 書籍では,東京リージョンで利用できるv2.11.1のAMIのIDを,公式のリポジトリ2にある「amis.txt」から取得しています.しかしながら,リポジトリのタグでv3.0.03以降を選択すると,このファイルは見当たりません.これは該当するものが存在しないわけではなく,ただまとめられていないだけ(?)ですので,AWS マネジメントコンソールのEC2作成画面から検索することで,適切なものを選択します. 以下,執筆時点での最新バージョンであるv3.1.2を例にして説明していきます. マネジメントコンソールの EC2 > インスタンス の画面より,「インスタンスを起動」を選択します. AMIの選択画面が出ますので,検索フィールドに「parallelcluster-3.1.2」を入力します. 「コミュニティAMI」を選択すると,該当するAMIが表示されます.コンソール自体で東京リージョンを設定していれば,こちらに表示されるものは東京リージョンで利用可能なものになります.4 書籍にならい,OSが「Amazon Linux」,アーキテクチャが「x86_64」のもの(ami-064b00d4121ccc66a)を選択し,続行します. 2.2. 各種設定 次以降のステップでは,「インスタンスタイプ」「サブネット」などを設定していきます.全て書籍p. 223〜p. 226に記載のもので問題ありませんので,ここでは詳細を省略します. 2.3. FrontISTRのビルド 書籍p.227〜p. 229に従って,作成したEC2インスタンスへのアクセスとFrontISTRのビルドを行います.基本的には書籍に記載の通りで問題ありませんが,注意すべき点を取り上げておきます. Intel MKLのインストール Intelのガイドを基に設定していきます.2つ目のGPGキーをインポートするコマンドは,書籍では-importとハイフン1つのオプションとなっていますが,--importと2つが正しいようですので,注意して下さい.また,3つ目のコマンドで指定するMKLのバージョンは,ここではガイドに記載されている最新のものを利用しています. sudo yum-config-manager --add-repo https://yum.repos.intel.com/setup/intelproducts.repo sudo rpm --import https://yum.repos.intel.com/intel-gpg-keys/GPG-PUB-KEY-INTEL-SW-PRODUCTS-2019.PUB yum install intel-mkl-2020.0-088 ~/.bashrcの記述 書籍にもある通り,モジュール・MKLのパス・FrontISTRのパス設定を~/.bashrcに記述しておくことが望ましいです.この3点の内容を追記すると,以下のようなファイルができあがります. .bashrc # .bashrc # Source global definitions if [ -f /etc/bashrc ]; then . /etc/bashrc fi # Uncomment the following line if you don't like systemctl's auto-paging feature: # export SYSTEMD_PAGER= # User specific aliases and functions module load intelmpi source /opt/intel/mkl/bin/mklvars.sh intel64 export PATH=/home/ec2-user/autofistr/GCC_IMPI/FrontISTR/bin:$PATH 3. カスタムAMIの作成 書籍p. 229〜p. 230に従って,作成したEC2インスタンスの停止とAMIの作成を行います.特に変更点はありませんので,2.2.に同じく詳細を省略します. 4. AWS ParallelClusterのインストール ローカルPCで利用するAWS ParallelCluster (コマンドラインツール)は,利用するParallelClusterのバージョンに合わせる必要があります.よって,ここではv3.1.2のツールを導入します.執筆時点ではv3.1.2が最新版ですので,バージョンを指定しなくてもv3.1.2用のものがインストールされます. python3 -m pip install aws-parallelcluster より新しいバージョンがリリースされた後にv3.1.2を利用する場合は,==3.1.2とバージョンの指定を行ってください. python3 -m pip install aws-parallelcluster==3.1.2 AWS ParallelCluster バージョン3では,ローカルPCで記述するコマンドがバージョン2から大きく変更されています.これについては,次の記事で設定ファイルの内容とともに説明します. 次の記事: FrontISTRでAWS ParallelCluster バージョン3を利用する② https://docs.aws.amazon.com/parallelcluster/latest/ug/building-custom-ami-v3.html ↩ https://github.com/aws/aws-parallelcluster/tree/v2.11.1 ↩ https://github.com/aws/aws-parallelcluster/tree/v3.0.0 ↩ 書籍で利用しているv2.11.1のAMIも,この方法で選択することが可能です. ↩
- 投稿日:2022-03-22T15:26:21+09:00
Lambda Layersを使って処理をまとめてみた
背景 アカウントAの複数のLambdaから別のアカウントのEC2の情報を取得する実装を行っていて、Lambdaの中がほぼ同じ処理なのでLambda Layersを使ってmodule化してみます 今回話すこと Lambda Layersの概要 Lambda Layersの使い方 今回話さないこと クロスアカウントロール周り Lambdaのコードの解説 Lambda関数の作成方法 Lambda Layersの概要 公式には下記のような説明があります Lambda レイヤーは、追加のコードやデータを含めることができる .zip ファイルアーカイブです。 簡潔に言うと1つの関数を定義してそれを複数のLambda関数で使うことができるということです。 実際にLambda Layersを作成していく コードのzip化 mkidr python vi python/test.py zip -r lambda_layer_test.zip python/ 下記コードはtest.pyに入力してください import boto3 def ec2_access(acct_b): ACCESS_KEY = acct_b['Credentials']['AccessKeyId'] SECRET_KEY = acct_b['Credentials']['SecretAccessKey'] SESSION_TOKEN = acct_b['Credentials']['SessionToken'] ec2 = boto3.client( 'ec2', aws_access_key_id=ACCESS_KEY, aws_secret_access_key=SECRET_KEY, aws_session_token=SESSION_TOKEN, ) return ec2 def ec2_get_list(acct_b): ec2_instance_ids =[] ec2_instance_names =[] ec2_data = ec2_access(acct_b).describe_instances() for ec2_reservation in ec2_data['Reservations']: for ec2_instance in ec2_reservation['Instances']: instance_tag_name = list(filter(lambda item: item['Key'] == 'Name', ec2_instance["Tags"])) if instance_tag_name: ec2_instance_names.append(instance_tag_name[0]["Value"]) return { 'statusCode': 200, 'body': ec2_instance_names } なぜpythonフォルダを作らなければいけないかと思ったとおもいますが Layresは/optディレクトに展開されます pythonを例に出すと/opt/pythonに展開されるのでpythonディレクトリの下にファイルを配置します 公式の記事はこちらを参考にしてください Lambda Layersを作成 ①Lambaの画面からレイヤーを選択して、レイヤーの作成 ② 項目 値 名前 キャメルケース .zipファイルをアップロード zipファイルをアップロード 互換性のあるアーキテクチャ x86_64 ランタイム 今回は3.8を選択(複数選択することも可能) そして作成 Lambda関数からlambda Layersを読み込む 任意のLambda関数を作成する import test_layer import boto3 sts_connection = boto3.client('sts') acct_b = sts_connection.assume_role( RoleArn="arn:aws:iam::取得したいec2のアカウント番号:role/LambdaのRole名", RoleSessionName="cross_acct_lambda" ) def lambda_handler(event, context): return test_layer.ec2_get_list(instanse_tag_name,acct_b) layersを押してレイヤーの追加を押す カスタムレイヤーから先程作成したLayersを選択 LambdaのテストをするとEC2がprintされています Test Event Name hoge Response { "statusCode": 200, "body": [ "dev-ec2-1", "dev-ec2-2" ] } Function Logs START RequestId: 0c675016-70a4-4501-abfe-f97749dd1585 Version: $LATEST END RequestId: 0c675016-70a4-4501-abfe-f97749dd1585 REPORT RequestId: 0c675016-70a4-4501-abfe-f97749dd1585 Duration: 1283.40 ms Billed Duration: 1284 ms Memory Size: 128 MB Max Memory Used: 81 MB Init Duration: 961.56 ms Request ID 0c675016-70a4-4501-abfe-f97749dd1585 !!完!!
- 投稿日:2022-03-22T14:31:00+09:00
[RTX830]YAMAHAルーターでAWS-VPCに接続してVPNをはってみた
やりたいこと タイトル通り、AWS-VPCを作成しVPN接続する *プロバイダーさんにインターネット接続できる状態にしてもらっている前提です。 #環境 OS: Windows 10 Terminal: Tera Term Settings: AWS Router: YAMAHA RTX830 #AWS VPC設定 カスタマーゲートウェイ AWSでカスタマーゲートウェイの作成をします。 契約したプロバイダーから教えてもらったグローバルIPアドレスを入力します。他に名前を任意で設定し、後は全てデフォルトのままにしました。 仮想プライベートゲートウェイ AWS側の仮想プライベートゲートウェイは移転前の設定があったので、それを流用しました。 サイト間のVPN接続 名前タグ・・・任意の名前をつけます。 仮想プライベートゲートウェイ,カスタマーゲートウェイID・・・VPNでつなげたいゲートウェイを入力します。 入力の際、IDや名前タグで検索すればタイポが無くなります。 他にも入力欄はありましたが今回は全てデフォルトにしました。 VPN設定のダウンロード VPN接続の作成が完了したら画面上にある作成したVPN接続設定をダウンロードします。 RTX830設定 ダウンロードしたVPN設定のファイルを開き、tunnel毎にipsec ike local addressをプライベートIPアドレスに書き換えます。 tunnel select 1 tunnel name hoge ipsec tunnel 1 ipsec sa policy 1 1 esp aes-cbc sha-hmac ipsec ike keepalive log 1 off ipsec ike keepalive use 1 on heartbeat 10 6 ipsec ike local address 1 XXX.XXX.XXX.XXX ipsec ike pre-shared-key 1 text hoge ipsec ike remote address 1 XXX.XXX.XXX.XXX ip tunnel tcp mss limit auto tunnel enable 1 書き換えたらコマンド形式になっているので、全てコピーします。*余計な部分は省略しています。 今回はきしめんでPCとルーターを接続します。 Tera Termを開くと、シリアルを選択できるので選択し、OKを押します。 ユーザー→アドミンの順でログインして先ほどコピーした内容を貼り付けて実行します。 実行後、show configコマンドで内容が反映されていることを確認します。 内容に問題なければ、saveコマンドを実行します。これで設定は終了です。 きしめんとは USB-RJ45変換用のケーブルです。はじめて見ました。きしめんとも呼ばれているみたいです。
- 投稿日:2022-03-22T14:15:47+09:00
S3で静的ウェブサイトをホスティングする
はじめに AWSのS3の機能である静的サイトのホスティングを使ってウェブサイトを表示します。 S3を使用するメリット ・簡単 ・コスパがいい 前提 AWSアカウントを所持 html、cssファイルは作成済 表示まで 1.S3バケットの作成 ① S3のコンソール画面から「バケットを作成」をクリック ② バケット名を入力 バケット名は世界で一意である必要があります。 バケット名は3~63文字、小文字、数字、ドット、ハイフンのみで構成など他にもルールあり。 ③ 「パブリックアクセスをすべてブロック」のチェックを外す 今回はウェブサイトの表示なので、ブロックにチェックすると、アクセス出来なくなります。 ④ 「バケットの作成」をクリック その他はデフォルトで大丈夫です。 2.ファイルのアップロード バケットを作成するとコンソール画面にバケットが追加されています。 ① この画面で新しく作成したバケット名をクリックします。 ※ スクショの手違いでアクセスの欄が「公開」になっていますが、本来は「オブジェクトは公開することができます」と表示されます。 ② S3バケットにhtmlファイルとcssファイルをアップロードします。 オブジェクトタブの「アップロード」をクリック 「ファイルを追加」をクリックし、アップロードするファイルを選択 ファイルを追加すると、選択したファイルが表示されます。 追加したら、下部の「アップロード」をクリック 3.ホスティングの設定 ① 静的ウェブサイトホスティング バケットにファイルを追加したら、プロパティを開きます 静的ウェブサイトホスティングの「編集」をクリック 静的ウェブサイトホスティングを「有効にする」にチェック インデックスドキュメントにアップロードしたhtmlファイル名を入力 「変更の保存」をクリック ② アクセス設定 アクセス許可タブのバケットポリシーを編集 ポリシーエディターに { "Version": "2012-10-17", "Statement": [ { "Sid": "PublicReadGetObject", "Effect": "Allow", "Principal": "*", "Action": [ "s3:GetObject" ], "Resource": [ "arn:aws:s3:::Bucket-Name/*" ] } ] } を追加。 ResourceのBucket-Nameのところをバケット名に変更 例 "arn:aws:s3:::hello-aws-site/*" ポリシーを入力したら、変更の保存をクリック 4.サイトの表示 全て設定が完了したら、再度プロパティタブの静的ウェブサイトホスティングに戻ると、エンドポイントが表示されています。 これをクリックすると ブラウザでサイトが公開されました。 CloudFrontやRoute53を使用した高速化、ルーティングは今後やりたいと思います。 以上
- 投稿日:2022-03-22T14:01:45+09:00
AWSのec2-userにログイン出来なかった話
概要 local環境からawsに構築したEC2へ接続が出来なかった時の対処法について備忘録として記す 発生したエラー # ssh ec2-user@IPaddress Permission denied (publickey,gssapi-keyex,gssapi-with-mic). 対処法 # ssh -i 鍵.pem ec2-user@IPaddress ※鍵.pemはEC2作成時に指定した鍵のこと。KMSで管理されているはず。 結論 sshコマンドの-iオプションで鍵を指定して接続すれば問題なく繋がった。 -iで鍵を指定しても上手くいかない場合は、-vvvオプションを付与して接続時の詳細を確認すると良い。 まとめ 今回接続が上手くいかなかった時に検討したものは以下である。 作成したEC2にグローバルIPが割り当てられているのか セキュリティグループのインバウンドグループで自分のIPが通るように設定しているか port22が空いているか EC2作成時に指定した鍵が手元に存在するか EC2作成時に指定した鍵の権限が設定されているか
- 投稿日:2022-03-22T10:49:44+09:00
RedshiftでDROP DATABASEしたらエラー「ERROR: database "hogehoge" is being accessed by other users」
はじめに redshiftでDROP DATABASEしたらエラーが出たのでその対処方法を残します。 DROP DATABASE "hogehoge"; ERROR: database "hogehoge" is being accessed by other users 調査 ぐぐると、Postgresqlの文献ですが以下が見つかりました。 どうやら誰かのセッションが残っている様子。 対処 セッション一覧を出してprocpid列に出てきた値をメモります。複数件あれば全部メモります。 自分は4件のセッションがありました。 SELECT * FROM pg_stat_activity WHERE datname = 'hogehoge'; pg_terminate_backend関数でセッションを切断していきます。複数セッションが残っているのであればその回数分だけこのSQLをたたきます。 select pg_terminate_backend(procpidの値) from pg_stat_activity where datname = 'hogehoge'; 自分は、削除できないセッションが1件だけありました。 それはいま自分がつないでいるセッションなので消せないのだと思うんですが詳細調べる前に次に進んでしまいました... 結果 (1件だけ削除できないセッションがあったけど)無事にDROPできました。 DROP DATABASE "hogehoge"; 文献 とても参考になりました。ありがとうございます。
- 投稿日:2022-03-22T10:42:30+09:00
【AWS認定資格用】AWSのサービスを一挙見してみる
はじめに 概要 AWSの認定試験のうち、ソリューションアーキテクト-アソシエイトの資格勉強を行ったついでに、AWSのサービスを実務軸でまとめなおしてみました。メモがてらの投稿です。 AWSはサービスが非常に多いので、勉強するにも全部覚えるのは厳しいと思います。実務でよく一緒にでてくるものはできるだけ一つにまとめ、これに試験の要点を加えたうえで、まとめてみました。 (試験のみ!?) とついているものは、私が実務であまり関わっていないものになります。別途参考書で試験用に覚えたものです。 この資格の概要ですが、クラウドを使って組織のシステムを構築する上でビジネス上課題になるような目立った事例に対して、答えを提供できる人材かどうかを判定する試験かなと思っています。問題はビジネスシーンを例に出題され、回答の選択肢もその問題にあったものを選ばないと正解になりません。 この記事の対象はこんな人になるかと思います。 AWSを実務で使っている人 AWSを趣味で使っている人 資格取得意欲がある人 記事の情報ソースについて この記事を書くにあたり、調べものなどをしたサイトや書籍は以下になります。 以下の本を一回流し読みした 以下の本は試験問題含めてしっかりやった 適宜Qiitaのサイトで構築などを確認した これらにプラスして、日々の業務でAWSを使用した開発運用を行っているため、その知見もいくつか。 サービス選択 S3選択 基本 S3の選択の出題がとにかく目につきます。 Standard : デフォルトのS3 (0.023USD/GB)。これを基準と考える。とりあえずこれを選んでおけばいい感じはする。可用性99.9% Standard IA: アクセス頻度が低いが、すぐにアクセスする必要があるもの。最低取り出し期間が決まっているので、それより前に削除しても最低期間分課金される。またデータ取得に金がかかる。 One Zone IA: 単体IZのStandard IA。まあ使わないと思う。 Intelligent Tiering: 多分かなり出題される。アクセス頻度が読めないデータはこれに入れておくと、勝手に最適なクラスに配置する。モニタリング料金がかかる。 Glacier: アクセス頻度が低いものに向いている。0.004USD/GBで安価。取り出し時間にオプションがあるのと、一回データを書き込むと最低90日間の課金がある。標準で3~5時間かかるとおぼえておく。 Deep Archive: 標準12時間、**最大48時間(2日)**の取り出し時間がかかるので、2日待てるのであればこれに突っ込む。0.00099USD なお、Glacierのオプションは 迅速: 1~5分 標準: 3~5 時間 大容量: 5~12時間 ストレージ選択 基本 いろいろストレージがあります。これらから選択する必要があります。 EBS: EC2からリモートでアクセスして使用するストレージ。スループットがでるしサイズも選べる。一つのEC2に対して一つつける。 EFS: ネットワークファイルシステムで複数のEC2で共有することができる。共有できるものを選ぶ際に出題される。 EC2インスタンスストア: 簡単に言うと、EC2を構成するクラスタの揮発性領域のこと。つまり、作業時などに一時的に発生するようなローカルにおいておくキャッシュを保存する際にはここにする。 (試験のみ!?) S3: オブジェクトストアなので注意 FSx for Windows: EFSはLinux専用なので、WindowsのEC2であればこっちで確定 (試験のみ!?) FSx for Lustre: msecレベルのレイテンシと数百万IOPSをもつ。とにかく性能が必要な場合にはこっちを採用すること。 (試験のみ!?) よく見かけた出題としては複数のEC2から利用→EFS、tmpファイルを置きたい→インスタンスストア など。 またEBSはサイズなどを選択することができる。 SSDタイプ 汎用SSD: 1GB ~ 16TB, 16000IOPS プロビジョンドIOPS: 4G ~ 16TB, 64000IOPS 16000IOPSで収まるかどうかが出題されることが多いと感じた。 HDDタイプ スループット最適化HDD: シーケンシャルアクセスに最適。アクセス頻度がまあまああって安く済ませたいもの。500IOPS (試験のみ!?) コールドHDD: 250IOPSだが、一番安い (試験のみ!?) IOPS的に制約がない場合はこっちか。あんまり選択肢にならないイメージ。 コンピューティング選択 基本 とにかく出るのはサーバレス化できるかどうか。 lambda: サーバレスで、基本的にはSQSなどキューとセットで使う。15分 バッチタイミングが読めないものはこれ。 EC2: よくでる仮想マシン ECS: Containerのオーケストレーションツール EKS: Kubernetes版 (試験のみ!?) 下の二つはオーケストレーションツールであり、簡単に言うとDockerを動かすためのツールなので、動かす環境としてFargateとECが選べる。Fargateを選ぶとインフラを意識しなくて済むのでよいが、あんまり選択肢にならない感触だった。 EC2を採用する場合で、AutoScalingがだいたい必要。 あと, 複数のバッチ処理を束ねる場合には Step Function を用いること。(lambdaによりバッチ処理をつないでいくイメージ) AutoScalingの方法 SQSのキューを監視する方法 事前にきまった日時でスケジュールする方法 AZごとに最低いくつにするかが大事になる。例えば処理に最低4台必要であれば、1AZで4台をカバーする必要があるので、2AZとするなら最小数を8とする。また、ALBを前段に挟むことがよくある。 EC2インスタンスの選定 オンデマンドインスタンス: 基準。自由に使って落とせる リザーブドインスタンス: 1年とか3年とかの間契約しておくことで、70%くらい安くなるサービス。 スポットインスタンス: スポット的に使えるインスタンス。落ちても文句いえないやつ。短期のバッチや開発環境などに使う。 以下のように、例外もある。 スケジュールされたリザーブドインスタンス: 一日のうち数時間を年間使う場合、割引率が落ちるがこういう選択肢もある。 スポットブロック: 容量変更とかできないが、指定した期間(1~6時間)はインスタンス数に対し担保される。(安心) スポットフリート: vCPUレ¥ルで維持される。容量変更も可能。処理するコンピューティング量がおおよそ決まっており、特定時間のみ利用し、処理が完了しないといけないサービスに対してスポット的に利用する。 EC2プレイスメントグループ 参考 https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/placement-groups.html クラスタープレイスメントグループ 低いネットワークレイテンシー、高いネットワークスループット、またはその両方からメリットを受けるアプリケーションの場合は、クラスタープレイスメントグループの使用をお勧めします。 パーティションプレイスメントグループ 各パーティション内のインスタンスは、他のパーティション内のラックを共有しないため、単一のハードウェア障害の影響は関連付けられたパーティションのみに留まります。 スプレッドプレイスメントグループ スプレッドプレイスメントグループは、それぞれに独自のネットワークおよび電源がある異なるラックに別々に配置できるインスタンスのグループです。 あまり使ってこなかったコンピューティング(Streaming処理) バッチではなくストリーム処理に特化しているサービスあり。 Kinesis Data Stream: ストリームデータに独自処理をたして各方面にばらまく。 Kinesis Data Firehouse: S3やRedshift(SQLが読めるデータ分析用ストレージ)にばらまく。マネージドなので、見ないといけない範囲が狭くて済む。 Kinesis Data Analytics: 標準SQLで分析するサービス 試験では、選択肢になるのはData Firehouseかと思う。あとはSQLが読めるなら、AnalyticsかRedshiftを答えさせる感じかと思われる。 なお、Redshiftみたいなサービスをデータウェアハウスという。 ネットワークサービスの選択 基本 NATGW: 基本的にパブリックSubnetに置いておくと、インターネットへの出口になる。 インターフェースGW(Private Link): VPCに作っておくと、プライベートVPCの特定のエンドポイントになる。これをめがけて通信すれば、AWS内のネットワークを通ってプライベートに接続ができる。また、対応SaaSに直接アクセスもできる。対応はS3で、Dynamoは無理。 (試験のみ!?) VPCエンドポイント: S3とDynamoにVPCからアクセスするときにインターネットを通らないで済むようにするためのもの。 出題はVPCエンドポイントが圧倒的だと思う。DynamoDBはこれしか無理なので、注意。 オンプレとの接続方法 実務レベルではかなり大事。転送データ容量が多い場合にはダイレクトコネクトを引くことが多いか。 Direct Connect: 専用線。冗長構成が推奨。セキュアで大容量 Site to Site VPN: 構築が早く、暗号化されているためある程度セキュア (試験のみ!?) データ移行について聞かれることもある。 オンプレからのデータ移行 かなり大事と感じる。 Snowball edge: 物理HDDみたいなものにデータをつめてAmazon に送る (試験のみ!?) Snowball mobile: エクサバイトデータを物理につめて送るプラン (試験のみ!?) Storage Gateway: Snowballは時々刻々と変化するデータには無理。その場合にはこのVMをたてて、このStorageGatewayに書き込むと転送されるようになる。転送先はS3とか選べる。 (試験のみ!?) DataSync: StorageGWと似ているが、EFSが選べるのがポイントのデータ移行手段。StorageGWはVMたててNFSでアクセスする感じだったが、これはオンプレ側にAgentソフトを入れることが求められる。 (試験のみ!?) Storage Gatewayはいろいろあるので、それらから選ぶこと。(テープ、メモリなどなど) データベース選択 基本 RDS: リレーショナルデータベースと言われたらこれ。EC2みたいにインスタンスやAZなどを自分で選ぶのでマネージドの範囲が狭い。 DynamoDB: Key-Valueストアと言われたらこれ。リージョン間レプリケーションもできる。(グローバルテーブル) Aurora: マネージド範囲が広い。自動的に拡張され、3AZすべてにコピーされ、自動修復される。 (試験のみ!?) DBの可用性 DBの可用性はマルチAZ、マルチリージョンで別れるが、基本的にRDBは完全なマルチリージョンではない。なお、RDBは書き込み時にマスタサーバが必要なことが前提。 RDSの可用性: マルチAZでは自動でスタンバイが書き込みのマスタに昇格する。マルチリージョンはリードレプリカを用意することが考えられるが、リードレプリカはマスター昇格を行わないといけない。 Auroraの可用性: マルチAZは前述のとおりマネージドで実施。マルチリージョンはリードレプリカにとどまる。 データベースの高速化 キャッシュが聞かれる。 DynamoDB Accelerator (DAX): インメモリキャッシュでDynamoと互換性があるため、アプリ側改修が簡単。マイクロ秒まで性能改善。 (試験のみ!?) Memcache: レプリカ不可 (試験のみ!?) Redis: レプリカ可能 (試験のみ!?) 配信サービス CloudFront: CDNサービス。lambda EdgeというCF上で実行できるlambdaもある。 制的WebホスティングするS3: web公開ができる。署名付きURLの発行により、個別にデータを受け渡せる Global Accelerator : 複数のALBやEC2を束ねて一つのスタティックアドレスにし、ユーザはそのIPをたたくことで効率的にAWSネットワークを利用して高速にALBとかにアクセスできるようにするサービス。 (試験のみ!?) Route53: DNSサービス。加重や位置情報ベースのルーティングができる。 CFやWAFでの国内限定配信などがでる。CFなら地理的...でホワイトリストに日本を入れることで実施可能。 セキュアなシステム IAM IAMユーザ: ユーザの一覧。それぞれのユーザはPolicyによって許可された捜査権限を持つ。 IAM Role: 複数のPolicyを束ねたもの。ステージパスみたいなもの。 IAM Policy: 特定のサービスに対する特定の処理権限の最小単位 Roleは複数のPolicyを持つ。ユーザはRoleかPolicyをもつ。 IAMで大事な考え 基本的にIAMユーザは最小限にする動きが多い。 Rootユーザの凍結: RootユーザはMFAをかけ、デバイスを封印する。 Admin IAMユーザの作成: Rootユーザを凍結する前に、IAMがいじれるユーザを作ること 各処理のためにIAMユーザを作成: Policyはしぼること Roleについて STS: Lambdaなどに特定のRoleを許可することで、lambda→S3などのアクセスを可能にする。この用途では、この仕組みが推奨(実務でも使う) Roleベースのアクセスコントロール: S3とかはRoleやアカウントレベルで許可すること。例えばS3だと、バケットACLによるアクセス制限はアカウント単位でしか許可できず、色々不都合。IAMユーザやRoleで制限できるバケットPolicyで制御すること。 IDフェデレーション: 外部のIdPと連携する。 IDフェデレーションの連携手順について… 特定のIdPを用意する。ユーザ管理はここで行う SAMLアサーションをIdPから受け取る クライアントはSAMLアサーションをSSO urlに対して投げる SSO url はSTSが検証する。Roleと紐づけておく必要あり コンソールに転送する セキュリティ保護 SG: EC2とかALBにくっつけるやつ。許可したいものを羅列していく。ステートフルなので、インバウンドに許可を書いておけばつながる NACL: 一番下でdenyされていることが多いので、上で許可していく。ステートレスなので、明示的に許可をイン/アウトにかかないといけない。 WAF: ALB, Cloudfront, API GW, AppSync GraphQL APIにくっつけられるHTTP/SのFirewall GWLB: Network FWに対してルーティングするためのGW 組織として必要なこと AWS Org 基本的にAWSはアカウントが増えるため、統率を取らないといけない。このためにAWS Organizationがある。OUという組織単位にわけて制御できる。例えば "このOUにはS3:, rds: のみ許可させる" といった感じ。 コスト Budgets: 予算。アラートをだせる Cost Explorer: 可視化ができる Cost and Usage Report: コストとリソース使用状況の詳細レポート Trusted Advisor: AWSのコスト最適化の案をアドバイスしてもらえるサービス 可用性算出 いろいろなところに響くので、それぞれの可用性を考えながらシステム構築しなければいけないが、基本的には以下かと思われる。 EC2: ユーザがSPoF(Single Point of failure)を回避する。 VPC: ユーザがSPoF(Single Point of failure)を回避する。 ALB: 勝手にAZ RDS: ユーザがSPoF(Single Point of failure)を回避する。 Aurora: 勝手にAZ Lambda: 勝手にAZ Route53: グローバルなので意識なし CloudFront: グローバルなので意識なし S3: 勝手にAZ。リージョン間もCRR(Cross Region Replication)が可能。CRRは転送が早いのでAWS環境間のデータ転送にも使える。 可用性の面からもlambdaが有効なことがわかる。 おわりに 今回は通常のサービス軸とは切り離し、実務軸でサービスをまとめてみました。 試験のために覚えなおしたものについては、参考書などを参考にして別途覚える必要がありました。皆さんは聞きなれないサービスはありましたでしょうか?
- 投稿日:2022-03-22T10:36:40+09:00
自社のAzureADを使用してお客さんAWS環境へSSOする
概要 お客さんのAWS環境を使用する際、アカウント/パスワード管理の手間をなくしたいという場面は多々あると思います。 自社のAzureADを使ってAWSにフェデレーションログインさせることで、そうした手間が省けます。 手順 以下手順を元に作業すれば大体できます。 チュートリアル: Azure Active Directory シングル サインオン (SSO) と AWS Single-Account Access の統合 AWS側:お客さん側の作業 Azure側:自社側の作業 注意点 Azure AD SSOの構成 手順4で「[基本的な SAML 構成] セクションで、[識別子 (エンティティ ID)] と [応答 URL] の両方を同じ既定値 () に更新します。」という記載があるが、ここには要注意。 他の案件でデフォルトの「(略)signin.aws.amazon.com/saml」という識別子を使用している場合、別の値を命名する必要がある。(識別子はAzureAD内で一意の値である必要があるため。) その際、応答URLはデフォルトのままにすることに留意する。 例) 識別子:(略)signin.aws.amazon.com/saml#test-project 応答URL:(略)signin.aws.amazon.com/saml Azure AD テスト ユーザーの割り当て ユーザー追加はここの手順で実施するのではなく、AWS Single-Account Access でロール プロビジョニングを構成する方法の手順が完了してから実施する。 プロビジョニングが完了していないと、AWS側で作成したロールが取り込めないため、ログインするための適切な権限が割り当てられない模様。 AWS側のロールが1つだけだったら手順通りのDefault設定で問題ないかもしれないが、複数ロールが作成されている場合はプロビジョニングが完了してからユーザー追加画面で適切なロールを選択しないとログイン時にエラーが発生した。 プロビジョニングが完了すると権限選択の画面でAWS側のロールが表示されるようになる
- 投稿日:2022-03-22T08:56:25+09:00
ポッポッポー♪♪♪ 懐かしのSL機関車をAmazon Linux2で走らせてみよう!
はじめに 某ベンダで、クラウドの人材育成企画と研修トレーニングのデリバリを担当しています。 今回は、懐かしいネタで記事を書いてみようと思います。slコマンドを使って、Amazon Linux 2のターミナルにSL機関車を走らせてみたいと思います。 slについては、詳細がwikiに記載されています。ぜひこちらを参考をください。 sl (UNIX) - Wikipedia Debian/Ubuntuだとdebパッケージが提供されているので、apt-getで簡単にインストールできます。Amazon Linux 2のyum リポジトリではRPMパッケージが提供されていないようなので、今回はUbuntuのDEBパッケージをalienコマンドでRPMパッケージに変換してみようと思います。 alienを利用したslパッケージ(.rpm)の作成 UbuntuのEC2を立ち上げて、以下の手順でパッケージを作成します。手順は、全てroot権限で実施します。 1. slパッケージ(.deb)のダウンロード # apt-get -d install sl /var/cache/apt/archives以下にパッケージ(.deb)がダウンロードされます。 2. alienのインストール # apt-get install alien 3. .debから.rpmへの変換 # alien -r /var/cache/apt/archives/sl_5.02-1_amd64.deb sl-5.02-2.x86_64.rpm generated 4. 変換したパッケージ(.deb)の詳細確認 # rpm -qpi sl-5.02-2.x86_64.rpm Name : sl Version : 5.02 Release : 2 Architecture: x86_64 Install Date: (not installed) Group : Converted/games Size : 35525 License : see /usr/share/doc/sl/copyright Signature : (none) Source RPM : sl-5.02-2.src.rpm Build Date : Fri Mar 18 05:55:34 2022 Build Host : ip-172-31-34-123.ap-southeast-2.compute.internal Relocations : (not relocatable) Summary : Correct you if you type `sl' by mistake Description : Sl is a program that can display animations aimed to correct you if you type 'sl' by mistake. SL stands for Steam Locomotive. (Converted from a deb package by alien version 8.95.) alienで変換したエビデンスが残っています。 (Converted from a deb package by alien version 8.95.) 5. Amazon Linux 2へのインストール # rpm -Uvh sl-5.02-2.x86_64.rpm error: Failed dependencies: libncurses.so.6(NCURSES6_5.0.19991023)(64bit) is needed by sl-5.02-2.x86_64 libtinfo.so.6(NCURSES6_TINFO_5.0.19991023)(64bit) is needed by sl-5.02-2.x86_64 ライブラリの依存関係でエラーが出てます。単純にパッケージ変換で移植できると思ったのですが、失敗。。。ソースファイルからコンパイルする方針に変更して、再トライしてみます。 [再トライ] ソースファイルからコンパイルする 1. slコマンドのソース入手 Ubuntuからソースファイルを取得しようと思いましたが、GitHubに最新のソースコードが公開されています。最新のversion 5.03を入手します。 2. 必要ライブラリの追加 ヘッダファイルを確認するとcurses.hが必要になりそうです。EPEL(Extra Packages for Enterprise Linux)を有効にして、必要なライブラリを追加します。 # yum install epel-release # yum install ncurses-devel 3. コンパイル # make 4. 実行 # ./sl Amazon Linux 2 のターミナルにSL機関車が走ります。ポッポッポー♪♪♪ポッポッポー♪♪♪懐かしい〜。 おわりに パッケージ形式の移植で簡単に出来るかなーと思ったのが大きな見込違いで、3時間近く試行錯誤してしまいました。家の環境もMacになって久しく、自前でコンパイルしてPPをインストールする機会もなくなりました。でも、たまにはこういう作業も懐かしくていいですね。
- 投稿日:2022-03-22T07:56:57+09:00
AWS CDKで独自ドメインホスティング環境構築を自動化してみた
AWS CDKで独自ドメインホスティング環境構築を自動化してみました 以前の記事内容をAWS CDKで実現する方法をためしてみました! 今回の作成したテンプレートをGitHubで公開したのでぜひご利用ください! /lib/unique-domain-hosting-stack.ts import { Stack, StackProps, RemovalPolicy, CfnOutput } from 'aws-cdk-lib'; import { Construct } from 'constructs'; import * as cdk from 'aws-cdk-lib'; import * as acm from 'aws-cdk-lib/aws-certificatemanager'; import * as route53 from 'aws-cdk-lib/aws-route53'; import * as targets from 'aws-cdk-lib/aws-route53-targets'; import * as s3 from 'aws-cdk-lib/aws-s3'; import * as s3deploy from 'aws-cdk-lib/aws-s3-deployment'; import * as cloudfront from 'aws-cdk-lib/aws-cloudfront'; import * as origins from 'aws-cdk-lib/aws-cloudfront-origins'; export class UniqueDomainHostingStack extends Stack { constructor(scope: Construct, id: string, props?: StackProps) { super(scope, id, props); // ドメイン名取得 const domainName = this.node.tryGetContext('domainName'); // 擬似パラメータ取得 const { accountId, region, } = new cdk.ScopedAws(this); // ホストゾーンID取得 const hostedZoneId = route53.HostedZone.fromLookup(this, 'HostedZoneId', { domainName: domainName }); // Certificate Manager設定 const certificateManagerCertificate = new acm.DnsValidatedCertificate(this, 'CertificateManagerCertificate', { // ドメイン指定 domainName: domainName, // ホストゾーンID指定 hostedZone: hostedZoneId, // リージョン指定 (CloudFront固定) region: 'us-east-1', // 検証方法指定 validation: acm.CertificateValidation.fromDns(), }); // S3バケット作成 const s3Bucket = new s3.Bucket(this, 'S3Bucket', { // バケット名指定 bucketName: `${domainName}-${region}-${accountId}`, // ブロックパブリックアクセスをすべてON blockPublicAccess: s3.BlockPublicAccess.BLOCK_ALL, // リソース削除時にバケット削除 removalPolicy: RemovalPolicy.DESTROY, autoDeleteObjects: true, }); // CloudFrontOAI設定 const cloudFrontOAI = new cloudfront.OriginAccessIdentity(this, 'CloudFrontOriginAccessIdentityy', { comment: 'Unique Domain Hosting Environment', }) // CloudFront設定 const cloudFrontDistribution = new cloudfront.Distribution(this, 'CloudFrontDistribution', { // ドメイン指定 domainNames: [domainName], // キャッシュビヘイビア設定 defaultBehavior: { // オリジンID指定 origin: new origins.S3Origin(s3Bucket, { originAccessIdentity: cloudFrontOAI }), // 自動圧縮有無指定 compress: true, // HTTPメソッド指定 allowedMethods: cloudfront.AllowedMethods.ALLOW_GET_HEAD, cachedMethods: cloudfront.CachedMethods.CACHE_GET_HEAD, // ビューアプロトコルポリシー指定 viewerProtocolPolicy: cloudfront.ViewerProtocolPolicy.REDIRECT_TO_HTTPS, // キャッシュポリシー指定 (CachingOptimized) cachePolicy: cloudfront.CachePolicy.CACHING_OPTIMIZED, }, // SPA対応設定 errorResponses: [ { httpStatus: 403, responsePagePath: '/index.html', responseHttpStatus: 200, ttl: cdk.Duration.minutes(0), }, { httpStatus: 404, responsePagePath: '/index.html', responseHttpStatus: 200, ttl: cdk.Duration.minutes(0), }, ], // 料金クラス指定 priceClass: cloudfront.PriceClass.PRICE_CLASS_ALL, // ディストリビューション有効無効指定 enabled: true, // SSL証明書設定 certificate: certificateManagerCertificate, // セキュリティポリシー指定 minimumProtocolVersion: cloudfront.SecurityPolicyProtocol.TLS_V1_2_2021, // HTTPバージョン指定 httpVersion: cloudfront.HttpVersion.HTTP2, // ルートURL指定 defaultRootObject: 'index.html', // IPv6有無指定 enableIpv6: true, }) // Route53レコード設定 new route53.ARecord(this, 'Route53RecordSet', { // ドメイン指定 recordName: domainName, // ホストゾーンID指定 zone: hostedZoneId, // エイリアスターゲット設定 target: route53.RecordTarget.fromAlias( new targets.CloudFrontTarget(cloudFrontDistribution) ), }); // S3バケットにデプロイ new s3deploy.BucketDeployment(this, 'S3BucketDeploy', { // 対象ディレクトリ指定 sources: [s3deploy.Source.asset('./dist')], // S3バケット指定 destinationBucket: s3Bucket, // CloudFront指定 distribution: cloudFrontDistribution, distributionPaths: ['/*'], }); // デプロイ先URL表示 new CfnOutput(this, 'DeployURL', { value: `https://${domainName}`, }) } } /bin/unique-domain-hosting.ts #!/usr/bin/env node import 'source-map-support/register'; import * as cdk from 'aws-cdk-lib'; import { UniqueDomainHostingStack } from '../lib/unique-domain-hosting-stack'; const app = new cdk.App(); new UniqueDomainHostingStack(app, 'UniqueDomainHostingStack', { // アカウント情報設定 env: { account: process.env.CDK_DEFAULT_ACCOUNT, region: process.env.CDK_DEFAULT_REGION }, }); cdk.json { "app": "npx ts-node --prefer-ts-exts bin/unique-domain-hosting.ts", "watch": { "include": [ "**" ], "exclude": [ "README.md", "cdk*.json", "**/*.d.ts", "**/*.js", "tsconfig.json", "package*.json", "yarn.lock", "node_modules", "test" ] }, "context": { "@aws-cdk/aws-apigateway:usagePlanKeyOrderInsensitiveId": true, "@aws-cdk/core:stackRelativeExports": true, "@aws-cdk/aws-rds:lowercaseDbIdentifier": true, "@aws-cdk/aws-lambda:recognizeVersionProps": true, "@aws-cdk/aws-cloudfront:defaultSecurityPolicyTLSv1.2_2021": true, "@aws-cdk-containers/ecs-service-extensions:enableDefaultLogDriver": true, "@aws-cdk/aws-ec2:uniqueImdsv2TemplateName": true, "@aws-cdk/core:target-partitions": [ "aws", "aws-cn" ], "domainName": "ドメイン名設定" } } package.json { "name": "unique-domain-hosting", "version": "0.1.0", "bin": { "unique-domain-hosting": "bin/unique-domain-hosting.js" }, "scripts": { "build": "tsc", "watch": "tsc -w", "test": "jest", "cdk": "cdk" }, "keywords": [], "author": "Yasunori Kirimoto", "license": "ISC", "devDependencies": { "@types/jest": "^26.0.10", "@types/node": "10.17.27", "jest": "^26.4.2", "ts-jest": "^26.2.0", "aws-cdk": "2.15.0", "ts-node": "^9.0.0", "typescript": "~3.9.7" }, "dependencies": { "aws-cdk-lib": "2.15.0", "constructs": "^10.0.0", "source-map-support": "^0.5.16" } } 事前準備 AWS CLIのインストールと設定 AWS CDK #001 - TypeScript環境構築 Amazon Route 53による独自ドメインの取得 実行環境 node v16.10.0 npm v7.24.0 構築の流れ 各ファイル配置と設定ファイル更新 独自ドメインホスティング環境を自動デプロイ 各ファイル配置と設定ファイル更新 はじめに、各ファイル配置と設定ファイルを更新します。 「aws-cdk-templates-showcase」リポジトリ内の「unique-domain-hosting」ディレクトリをそのまま利用するか任意の場所にコピーします。 「cdk.json」にAmazon Route 53で取得した独自ドメイン名を設定します。 "domainName": "ドメイン名設定" 「dist」ディレクトリにデプロイしたいアプリケーションファイル一式をコピーします。 独自ドメインホスティング環境を自動デプロイ 最後に、独自ドメインホスティング環境を自動デプロイします。 パッケージをインストールします。 npm install デプロイ前に初回のみ下記コマンドを実行します。リージョンを変更した時にも実行します。 cdk bootstrap プロジェクトをデプロイします。 cdk deploy スタックが作成されたのを確認。各サービスも自動作成されているのを確認できます。 独自ドメインにアクセスするとデプロイしたWebSiteが表示されます。 AWS CDKを利用することで、独自ドメインホスティング等のさまざまなリソース構築を自動化することが可能です。今回は、ACMを固定リージョンで作成やCloudFront用のS3バケットポリシー自動生成やデプロイしたいアプリケーションをコード内で定義する等がコード量も少なく実装可能でした。各機能定義は、AWS CloudFormationと同様にドキュメントで学習する必要はありますが、すごく将来性を感じるツールで構築するのが楽しいです 今後も色々と自動化していければと思います! AWS CDKについて、他にも記事を書いています。よろしければぜひ tags - AWS CDK やってみたシリーズ tags - Try
- 投稿日:2022-03-22T07:33:11+09:00
あなたはAWS Configで損をしている!? ~ AWS提供サンプルテンプレートの罠 ~
はじめに 結論から言います。 AWSが提供している CloudFormation StackSets サンプルテンプレートを用いて、AWS Config を有効化している場合、余分なコストが発生している可能性があります。 対象読者 AWSが提供している CloudFormation StackSets サンプルテンプレートを用いて、 AWS Config を有効化している方(または、これから有効化しようと考えている方) AWS Config をすべてのリージョンで有効化していない方 AWS Config のベストプラクティスに興味のある方 CloudFormation StackSets とは 複数のアカウントとリージョンに対して、同じ CloudFormation スタックを作成する機能です。 マルチアカウントの印象が強いかもしれませんが、対象アカウントを一つにすることにより、同一アカウント内の複数リージョンのみを対象とすることも可能です。 本記事では、同一アカウントの複数リージョンを対象とします。 また、CloudFormation StackSets では長いので、以降は StackSets と略します。 引用:https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/what-is-cfnstacksets.html StackSets の使いどころ StackSets は複数リージョンに対して、同じリソースを作成したい場合に効果を発揮します。 例えば、AWS アカウントの初期設定 です。 本記事のテーマである AWS Config だけでなく、 CloudTrail, GuardDuty, Security Hub などのサービスは、すべてのリージョンで有効化することが推奨されています。 しかし、これらのサービスをマネジメントコンソールからすべてのリージョンで有効化するのは大変です。 このような場合に StackSets を使うと、すべてのリージョンで一括設定することが可能です。 AWSが提供しているサンプルテンプレートの問題点 本題に入りましょう。 AWS は、いくつかの StackSets サンプルテンプレートを提供しています。 この中には AWS Config を有効にする テンプレートも含まれています。 引用:https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/stacksets-sampletemplates.html なお、マネジメントコンソールから StackSet を作成する際にもサンプルテンプレートを選ぶことができます。 CloudFormation > StackSets > StackSet の作成 なにが問題なのか? 問題は、このサンプルテンプレートをそのまま使うと、すべてのリージョンでグローバルリソースの記録が有効になってしまうこと です。 グローバルリソースとは IAM などのグローバルサービスのリソースのことです。 AWS Config では、各リージョンの記録にグローバルリソースを含めるか否かを選択することができます。 すべてのリージョンでグローバルリソースの記録が有効にした場合、以下の問題が発生します。 AWS Config の料金が増える AWS Config はルールの評価件数に応じて課金されるため、各リージョンでグローバルリソースを重複して記録している場合、余分な料金が発生します。 グローバルリソースに関する通知が重複する ルールの評価結果に対して通知を設定している場合、各リージョンでグローバルリソースに関するチェックが実行されるため、通知も重複します。 通知の重複については、以下のブログで検証されています。 AWS Config のベストプラクティス ここで AWS Config のベストプラクティスを見てみましょう。 実は、グローバルリソースの記録は1つのリージョンのみで有効としたほうがよい、という話は AWS Config のベストプラクティスにも書かれています。 3.1 つのリージョンでのみグローバルリソース (IAM リソースなど) を記録します。 これにより、IAM 設定アイテムの冗長コピーをすべてのリージョンで取得することがなくなります。それは費用の節約にもなります。 引用:https://aws.amazon.com/jp/blogs/news/aws-config-best-practices/ しかし、残念ながら提供されているサンプルテンプレートは、このベストプラクティスに準拠していません。 改善しよう 問題点ばかり指摘しても仕方がないので、サンプルテンプレートを改善してみましょう。 サンプルテンプレートの分析 グローバルリソースを記録するか否かは AWS::Config::ConfigurationRecorder リソースの IncludeGlobalResourceTypes プロパティで指定します。 サンプルテンプレートでは、このプロパティの値をパラメータで指定する形になっています。 StackSets は、指定したリージョンに対して、同じテンプレートからスタックを作成するため、パラメータで指定した値(True または False)がすべてのリージョンに反映されます。 これが原因です。 EnableAWSConfig.yml(オリジナル抜粋) Parameters: IncludeGlobalResourceTypes: Type: String Default: False Description: Indicates whether AWS Config records all supported global resource types. AllowedValues: - True - False (中略) Resources: ConfigRecorder: Type: AWS::Config::ConfigurationRecorder DependsOn: - ConfigBucketPolicy Properties: RoleARN: !GetAtt ConfigRecorderRole.Arn RecordingGroup: AllSupported: !Ref AllSupported IncludeGlobalResourceTypes: !Ref IncludeGlobalResourceTypes ResourceTypes: !If - IsAllSupported - !Ref AWS::NoValue - !Ref ResourceTypes 改善版テンプレート では、どのように改善したらよいか? 答えは、特定のリージョンの場合に限り IncludeGlobalResourceTypes を True にする です。 具体的な方法を解説していきます。 グローバルリソースの記録を有効にするリージョンをパラメータとして追加します。 Parameter: HomeRegion 疑似パラメータの AWS::Region を用いて、スタックを作成するリージョンが HomeRegion か否かを判定する Condition を作成します。 Condition: IsHomeRegion 条件式を用いて、IsHomeRegion が真 = スタックを作成するリージョンが HomeRegion と一致した場合に限り、IncludeGlobalResourceTypes の値を True に設定します。 元々あった IncludeGlobalResourceTypes パラメータは不要なので、削除します。 EnableAWSConfig.yml(改善版抜粋) Parameters: HomeRegion: Type: String (中略) Conditions: IsHomeRegion: !Equals [!Ref AWS::Region, !Ref HomeRegion] (中略) Resources: ConfigRecorder: Type: AWS::Config::ConfigurationRecorder DependsOn: - ConfigBucketPolicy Properties: RoleARN: !GetAtt ConfigRecorderRole.Arn RecordingGroup: AllSupported: !Ref AllSupported IncludeGlobalResourceTypes: !If - IsHomeRegion - True - False ResourceTypes: !If - IsAllSupported - !Ref AWS::NoValue - !Ref ResourceTypes これで HomeRegion パラメータで指定したリージョンに限り、グローバルリソースを記録することができました。 【要検証】2022年2月以降はグローバルリソースの扱いが変わっている!? ここまでサンプルテンプレートの問題点と改善方法を解説してきましたが、最後に重要なお知らせがあります。 なんと、公式ドキュメントに以下の記載がありました。 引用:https://docs.aws.amazon.com/ja_jp/config/latest/developerguide/select-resources.html 2022 年 2 月以前にオンボードされたものは変更されず、今後も AWS Config で有効化されているすべてのリージョン内の設定項目を配信します。この変更は、2022 年 2 月以降にオンボードされた新しいグローバルリソースタイプのみに影響します。 この記載によると、2022 年 2 月以降はグローバルリソースの扱いが変わっているそうです。 ただし、私が 2022/03/21 時点で動作を確認した限りでは、従来動作からの差異は確認できませんでした。 ■確認手順 既存の AWS Config 関連リソース(AWS::Config::ConfigurationRecorder および AWS::Config::DeliveryChannel)を削除。 新しい AWS Config 関連リソース(AWS::Config::ConfigurationRecorder および AWS::Config::DeliveryChannel)を作成。 IncludeGlobalResourceTypes は東京リージョン(ap-northeast-1)のみ True とし、他リージョンは False とした。 新しい IAM リソース(AWS::IAM::Group)を作成。 ■確認結果 東京リージョン(ap-northeast-1)の AWS Config に新たに作成した IAM リソース(AWS::IAM::Group)が表示された。 バージニア北部リージョン(us-east-1)の AWS Config には新たに作成した IAM リソース(AWS::IAM::Group)が表示されなかった。 また、念のため、API リファレンスも確認してみましたが、動作変更に関する記載はありませんでした。 時間が取れたらさらに検証してみようと思いますが、AWS サポートに確認した方が確実かつ早いかもしれません。 もし、詳細をご存じの方がいらっしゃいましたら教えてください。 おわりに 本記事では、サンプルテンプレートの問題点を指摘・改善しましたが、サンプルの提供元を批判する意図は一切ありません。 サンプルの提供元に関わらず、利用者が内容を理解した上で利用することと、ベストプラクティスの理解が重要と考えます。 最後まで読んでいただき、ありがとうございます。 本記事が少しでも役に立てば幸いです。
- 投稿日:2022-03-22T07:19:57+09:00
駆逐してやる!!AWS Security Hubの指摘を…この世から…一匹残らず!! ~ S3編 (CLI) ~
Security Hub の指摘、駆逐してますか? とりあえず、Security Hub を有効化したけど、セキュリティスコアが低くて困っている… Security Hub の検出結果 (Findings) にどう対処すればよいのかわからない… S3 のセキュリティを強化したい… そんな方々のために、本記事では Security Hub の S3 に関する指摘事項を一匹残らず駆逐する方法を解説します。 また、解説と合わせて、Security Hub に指摘されない S3 バケットを作成するための CLI スクリプトも紹介していきます。 「解説はいいから早よ CLI をよこせ」という方はこちらをどうぞ。 ↓ ↓ ↓ CLI を捧げよ! 本記事は 駆逐してやる!!AWS Security Hubの指摘を…この世から…一匹残らず!! ~ S3編 (CloudFormation) ~ の CLI 版です。CLI 以外の内容(解説等)は同じです。 CLI のパラメータ指定方法について 本記事では CLI のパラメータ指定方法として --cli-input-yaml オプションを使用しています。 コマンドによってはパラメータの数が多く、それらをすべてコマンドのオプションで指定するのは大変なので、パラメータを YAML 形式で定義できる -cli-input-yaml オプションを使用しています。(まぁ、好みです) 詳しくは以下を参照してください。 AWS Security Hub とは 一言でいうと、複数のAWSサービスのセキュリティアラートを集約して一元管理するためのサービスです。 セキュリティ標準 (Standards) Security Hub は、AWS のベストプラクティスや業界標準に基づいたセキュリティチェック機能 を備えています。 投稿時点 (2022/03/21) では、以下の セキュリティ標準 (Standards) が用意されています。 AWS 基礎セキュリティのベストプラクティス (AWS Foundational Security Best Practices) CIS AWS Foundations Benchmark Payment Card Industry Data Security Standard (PCI DSS) コントロール (Controls) セキュリティ標準に含まれる個々のチェック項目を コントロール (Controls) と呼びます。 例えば、AWS Foundational Security Best Practices には以下のようなコントロール (Controls) が含まれます。 AWS Foundational Security Best Practices [S3.1] S3 ブロックパブリックアクセス設定を有効にする必要があります [S3.2] S3 バケットではパブリック読み取りアクセスを禁止する必要があります ・・・ 検出結果 (Findings) セキュリティチェックにより検出された結果を 検出結果 (Findings) と呼びます。 ただし、本記事ではわかりやすくするために 指摘 と表現します。 駆逐してやる!! ここからは指摘の駆逐方法を解説していきます。 既存バケットの設定を変更する場合、変更による影響を十分に検証してください。 投稿内容を利用したことにより生じた損害について、著者は一切の責任を負いません。 AWS Foundational Security Best Practices AWS Foundational Security Best Practices は名前のとおり、AWS における基礎的なベストプラクティスに基づいたセキュリティ標準です。 [S3.1] S3 ブロックパブリックアクセス設定を有効にする必要があります [S3.1] S3 Block Public Access setting should be enabled 重大度:中 この指摘を駆逐するには、アカウントレベルのブロックパブリックアクセス設定を有効にします。 ブロックパブリックアクセス設定には、アカウントレベルとバケットレベルの2種類の設定が存在します。 [S3.1] はアカウントレベルの設定です。バケットレベルの設定は [S3.8] が該当します。 アカウントレベルの設定は、マネジメントコンソール、または、CLI で設定します。 CloudFormation では設定できません。 マネジメントコンソール 以下の画面から設定します。 Amazon S3 > このアカウントのブロックパブリックアクセス設定 CLI 以下のコマンドで設定します。 s3control put-public-access-block #=========================================================== # アカウントレベルのブロックパブリックアクセス設定 #=========================================================== INPUT_YAML=$(cat << EOS AccountId: "${AWS_ACCOUNT_ID}" PublicAccessBlockConfiguration: BlockPublicAcls: true IgnorePublicAcls: true BlockPublicPolicy: true RestrictPublicBuckets: true EOS ) aws s3control put-public-access-block --cli-input-yaml "$INPUT_YAML" ${AWS_ACCOUNT_ID} には、対象のAWSアカウントID(数字12桁)を指定してください。 参考 [S3.2] S3 バケットではパブリック読み取りアクセスを禁止する必要があります [S3.2] S3 buckets should prohibit public read access 重大度:重大 この指摘の駆逐方法は [S3.8] に含まれます。 以下を参照してください。 AWS Foundational Security Best Practices [S3.8] S3 ブロックパブリックアクセス設定は、バケットレベルで有効にする必要があります [S3.3] S3 バケットはパブリック書き込みアクセスを禁止する必要があります [S3.3] S3 buckets should prohibit public write access 重大度:重大 この指摘の駆逐方法は [S3.8] に含まれます。 以下を参照してください。 AWS Foundational Security Best Practices [S3.8] S3 ブロックパブリックアクセス設定は、バケットレベルで有効にする必要があります [S3.4] S3 バケットでは、サーバー側の暗号化を有効にする必要があります [S3.4] S3 buckets should have server-side encryption enabled 重大度:中 この指摘を駆逐するには、S3 バケットのサーバー側の暗号化を有効にします。 デフォルトのサーバー側の暗号化は以下の2種類から選択できます。 S3 で管理されたキーを使用する SSE-S3 KMS に保存されたキーを使用する SSE-KMS CLI s3api put-bucket-encryption コマンドで設定します。 SSE-S3 #=========================================================== # サーバー側の暗号化設定 (SSE-S3) #=========================================================== INPUT_YAML=$(cat << EOS Bucket: ${BUCKET_NAME} ServerSideEncryptionConfiguration: Rules: - ApplyServerSideEncryptionByDefault: SSEAlgorithm: AES256 EOS ) aws s3api put-bucket-encryption --cli-input-yaml "$INPUT_YAML" SSE-KMS #=========================================================== # サーバー側の暗号化設定 (SSE-KMS) #=========================================================== INPUT_YAML=$(cat << EOS Bucket: ${BUCKET_NAME} ServerSideEncryptionConfiguration: Rules: - ApplyServerSideEncryptionByDefault: SSEAlgorithm: aws:kms KMSMasterKeyID: ${KMS_KEY_ID} BucketKeyEnabled: true EOS ) aws s3api put-bucket-encryption --cli-input-yaml "$INPUT_YAML" ${BUCKET_NAME} はパラメータです。対象のバケット名を指定します。 ${KMS_KEY_ID} はパラメータです。暗号化に使用する KMS Key ID を指定します。 BucketKeyEnabled はオプションですが、SSE-KMS の場合は有効化することをおすすめします。バケットキーを有効化することにより、S3 から KMS へのリクエストを減らし、コストを削減することができます。 参考 [S3.5] S3 バケットは、Secure Socket Layer を使用するためのリクエストが必要です [S3.5] S3 buckets should require requests to use Secure Socket Layer 重大度:中 この指摘を駆逐するには、S3 バケットに対する操作が HTTPS リクエストのみを受け入れる(HTTP リクエストは拒否する)ように設定します。 CLI s3api put-bucket-policy コマンドを用いて、バケットポリシーに以下のステートメントを追加します。 ポイントは aws:SecureTransport です。 aws:SecureTransport が false の場合= HTTPS リクエストではない場合、S3 バケットおよびオブジェクトに対するすべての操作を拒否します。 put-bucket-policy コマンドでバケットポリシーを更新する場合、既存のバケットポリシーを上書きしてしまわないようご注意ください。既存のバケットポリシーがある場合、POLICY_JSON は既存のバケットポリシーに DenyInsecureRequests ステートメントを追加する形としてください。 #=========================================================== # HTTP拒否ポリシー #=========================================================== POLICY_JSON=$(cat << EOS { "Version": "2012-10-17", "Statement": [ { "Sid": "DenyInsecureRequests", "Effect": "Deny", "Principal": "*", "Action": [ "s3:*" ], "Resource": [ "arn:aws:s3:::${BUCKET_NAME}", "arn:aws:s3:::${BUCKET_NAME}/*" ], "Condition": { "Bool": { "aws:SecureTransport": false } } } ] } EOS ) INPUT_YAML=$(cat << EOS Bucket: ${BUCKET_NAME} Policy: '${POLICY_JSON}' EOS ) aws s3api put-bucket-policy --cli-input-yaml "$INPUT_YAML" ${BUCKET_NAME} はパラメータです。対象のバケット名を指定します。 参考 [S3.6] 他のユーザーに付与された Amazon S3 のアクセス許可AWSバケットポリシーのアカウントは制限する必要があります [S3.6] Amazon S3 permissions granted to other AWS accounts in bucket policies should be restricted 重大度:高 この指摘は、他アカウントのユーザーやロールに対して、以下のいずれかの操作を明示的に許可している場合に指摘されます。 s3:DeleteBucketPolicy s3:PutBucketAcl s3:PutBucketPolicy s3:PutEncryptionConfiguration s3:PutObjectAcl つまり、他アカウントのユーザーやロールに対して、これらの操作を明示的に許可していなければ、指摘されることはありません。 なお、他アカウントのユーザーやロールに対する 明示的な拒否 を設定しておくと、意図せずに許可してしまうことを防ぐことができます。 CLI s3api put-bucket-policy コマンドを用いて、バケットポリシーに以下のステートメントを追加します。 ポイントは NotPrincipal です。 NotPrincipal に自アカウントIDを指定することにより、自アカウント以外=他アカウントに対する明示的な拒否を設定しています。 put-bucket-policy コマンドでバケットポリシーを更新する場合、既存のバケットポリシーを上書きしてしまわないようご注意ください。既存のバケットポリシーがある場合、POLICY_JSON は既存のバケットポリシーに DenyInsecureRequests ステートメントを追加する形としてください。 #=========================================================== # 他アカウントからの機密API操作拒否ポリシー #=========================================================== POLICY_JSON=$(cat << EOS { "Version": "2012-10-17", "Statement": [ { "Sid": "DenySensitiveActionsFromOtherAccounts", "Effect": "Deny", "NotPrincipal": { "AWS": "${AWS_ACCOUNT_ID}" }, "Action": [ "s3:DeleteBucketPolicy", "s3:PutBucketAcl", "s3:PutBucketPolicy", "s3:PutEncryptionConfiguration", "s3:PutObjectAcl" ], "Resource": [ "arn:aws:s3:::${BUCKET_NAME}", "arn:aws:s3:::${BUCKET_NAME}/*" ] } ] } EOS ) INPUT_YAML=$(cat << EOS Bucket: ${BUCKET_NAME} Policy: '${POLICY_JSON}' EOS ) aws s3api put-bucket-policy --cli-input-yaml "$INPUT_YAML" ${AWS_ACCOUNT_ID} には、対象のAWSアカウントID(数字12桁)を指定してください。 ${BUCKET_NAME} はパラメータです。対象のバケット名を指定します。 参考 [S3.7] (欠番) [S3.7] は存在しません。欠番のようです。 [S3.8] S3 ブロックパブリックアクセス設定は、バケットレベルで有効にする必要があります [S3.8] S3 Block Public Access setting should be enabled at the bucket level 重大度:高 この指摘を駆逐するには、バケットレベルのブロックパブリックアクセス設定を有効にします。 「[S3.1] S3 ブロックパブリックアクセス設定を有効にする必要があります」は、アカウントレベルの設定でしたが、こちらはバケットレベルの設定です。 アカウントレベルで設定していても、Security Hub はバケットレベルの設定も要求してきます。 CLI s3api put-public-access-block コマンドで設定します。 #=========================================================== # バケットレベルのブロックパブリックアクセス設定 #=========================================================== INPUT_YAML=$(cat << EOS Bucket: ${BUCKET_NAME} PublicAccessBlockConfiguration: BlockPublicAcls: true IgnorePublicAcls: true BlockPublicPolicy: true RestrictPublicBuckets: true EOS ) aws s3api put-public-access-block --cli-input-yaml "$INPUT_YAML" 参考 [S3.9] S3 バケットサーバーアクセスログを有効にする必要があります [S3.9] S3 bucket server access logging should be enabled 重大度:中 この指摘を駆逐するには、S3 バケットに対するアクセスログを有効にします。 ただし、アクセスログ保存用バケット自体のロギング設定は留意する必要があります。 以下のとおり、ソースバケット(ロギング対象)とターゲットバケット(ログ保存先)が同じ場合、いくつかの留意事項があるため、アクセスログ保存用バケット自体のロギングは設定しない判断が好ましいケースもあります。 この場合、アクセスログ保存用バケットに対する [S3.9] の指摘は抑制するのがよいでしょう。 ソースバケットとターゲットバケットが同じである場合、バケットに書き込まれるログに関する追加のログが作成されます。これは、ストレージの請求額がいくらか増える可能性があるため、望ましくない場合があります。また、ログに関する追加のログのために、必要なログを見つけにくくなります。 引用:https://docs.aws.amazon.com/ja_jp/AmazonS3/latest/userguide/ServerLogs.html CLI s3api put-bucket-logging コマンドで設定します。 #=========================================================== # ロギング設定 #=========================================================== INPUT_YAML=$(cat << EOS Bucket: ${BUCKET_NAME} BucketLoggingStatus: LoggingEnabled: TargetBucket: ${LOGGING_BUCKET_NAME} TargetPrefix: ${BUCKET_NAME} EOS ) aws s3api put-bucket-logging --cli-input-yaml "$INPUT_YAML" ${BUCKET_NAME} はパラメータです。対象のバケット名を指定します。 ${LOGGING_BUCKET_NAME} はパラメータです。ログ保存先のバケット名を指定します。 TargetPrefix はオプションですが、複数バケットのアクセスログをひとつのバケットに集約する際に、どのバケットのアクセスログかを判別できるよう、バケット名をプレフィックスとして設定することをおすすめします。 参考 CIS AWS Foundations Benchmark CIS AWS Foundations Benchmark は CIS (Center of Internet Security) のベンチマークに基づいたセキュリティ標準です。 2.3 — CloudTrail ログが記録する S3 バケットがパブリックにアクセスできないことを確認します 2.3 – Ensure the S3 bucket CloudTrail logs to is not publicly accessible 重大度:重大 この指摘を駆逐するには、CloudTrail ログバケットに対して、ブロックパブリックアクセスを設定します。 ブロックパブリックアクセスの設定方法は、以下を参照してください。 AWS Foundational Security Best Practices [S3.8] S3 ブロックパブリックアクセス設定は、バケットレベルで有効にする必要があります 2.6 — CloudTrail S3 バケットアクセスログ記録が CloudTrail S3 バケットで有効になっていることを確認します 2.6 – Ensure S3 bucket access logging is enabled on the CloudTrail S3 bucket 重大度:低 この指摘を駆逐するには、CloudTrail ログバケットに対して、アクセスログ記録を設定します。 アクセスログ記録の設定方法は、以下を参照してください。 AWS Foundational Security Best Practices [S3.9] S3 バケットサーバーアクセスログを有効にする必要があります Payment Card Industry Data Security Standard (PCI DSS) Payment Card Industry Data Security Standard (PCI DSS) は、クレジットカード業界のセキュリティ標準です。 [PCI.S3.1] S3 バケットはパブリック書き込みアクセスを禁止する必要があります [PCI.S3.1] S3 buckets should prohibit public write access 重大度:重大 以下の指摘と同様です。 AWS Foundational Security Best Practices [S3.3] S3 バケットはパブリック書き込みアクセスを禁止する必要があります 駆逐方法 [S3.8] S3 ブロックパブリックアクセス設定は、バケットレベルで有効にする必要があります [PCI.S3.2] S3 バケットではパブリック読み取りアクセスを禁止する必要があります [PCI.S3.2] S3 buckets should prohibit public read access 重大度:重大 以下の指摘と同様です。 AWS Foundational Security Best Practices [S3.2] S3 バケットではパブリック読み取りアクセスを禁止する必要があります 駆逐方法 [S3.8] S3 ブロックパブリックアクセス設定は、バケットレベルで有効にする必要があります [PCI.S3.3] S3 バケットでクロスリージョンレプリケーションを有効にする必要があります [PCI.S3.3] S3 buckets should have cross-region replication enabled 重大度:低 この指摘を駆逐するには、S3 バケットのクロスリージョンレプリケーションを有効にします。 なお、レプリケーションを有効にするには、予めレプリケート元とレプリケート先の両方のバケットで、バージョニングを有効にしておく必要があります。 CLI クロスリージョンレプリケーションを設定するにあたり、レプリケーション用の IAM Role が必要になります。 クロスリージョンレプリケーションの設定は s3api put-bucket-replication コマンドで設定します。 #=========================================================== # IAMポリシー作成 #=========================================================== POLICY_JSON=$(cat << EOS { "Version": "2012-10-17", "Statement": [ { "Sid": "AllowSourceBucketAccess", "Effect": "Allow", "Action": [ "s3:GetReplicationConfiguration", "s3:ListBucket" ], "Resource": [ "arn:aws:s3:::${BUCKET_NAME}" ] }, { "Sid": "AllowSourceObjectAccess", "Effect": "Allow", "Action": [ "s3:GetObjectVersionForReplication", "s3:GetObjectVersionAcl", "s3:GetObjectVersionTagging" ], "Resource": [ "arn:aws:s3:::${BUCKET_NAME}/*" ] }, { "Sid": "AllowDestinationObjectAccess", "Effect": "Allow", "Action": [ "s3:ReplicateObject", "s3:ReplicateDelete", "s3:ReplicateTags" ], "Resource": [ "arn:aws:s3:::${REPLICATION_BUCKET_NAME}/*" ] } ] } EOS ) INPUT_YAML=$(cat << EOS PolicyName: ${POLICY_NAME} PolicyDocument: '${POLICY_JSON}' EOS ) aws iam create-policy --cli-input-yaml "$INPUT_YAML" #=========================================================== # IAMロール作成 #=========================================================== POLICY_JSON=$(cat << EOS { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "Service": [ "s3.amazonaws.com" ] }, "Action": [ "sts:AssumeRole" ] } ] } EOS ) INPUT_YAML=$(cat << EOS RoleName: ${ROLE_NAME} AssumeRolePolicyDocument: '${POLICY_JSON}' EOS ) aws iam create-role --cli-input-yaml "$INPUT_YAML" #=========================================================== # IAMポリシーのアタッチ #=========================================================== INPUT_YAML=$(cat << EOS RoleName: ${ROLE_NAME} PolicyArn: arn:aws:iam::${AWS_ACCOUNT_ID}:policy/${POLICY_NAME} EOS ) aws iam attach-role-policy --cli-input-yaml "$INPUT_YAML" #=========================================================== # バージョニング有効化 #=========================================================== INPUT_YAML=$(cat << EOS Bucket: ${BUCKET_NAME} VersioningConfiguration: Status: Enabled EOS ) aws s3api put-bucket-versioning --cli-input-yaml "$INPUT_YAML" #=========================================================== # レプリケーション有効化 #=========================================================== INPUT_YAML=$(cat << EOS Bucket: ${BUCKET_NAME} ReplicationConfiguration: Role: arn:aws:iam::${AWS_ACCOUNT_ID}:role/${ROLE_NAME} Rules: - Status: Enabled Priority: 1 Filter: Prefix: "" DeleteMarkerReplication: Status: Disabled Destination: Bucket: arn:aws:s3:::${REPLICATION_BUCKET_NAME} EOS ) aws s3api put-bucket-replication --cli-input-yaml "$INPUT_YAML" ${AWS_ACCOUNT_ID} には、対象のAWSアカウントID(数字12桁)を指定してください。 ${BUCKET_NAME} はパラメータです。対象のバケット名を指定します。 ${REPLICATION_BUCKET_NAME} はパラメータです。レプリケーション先のバケット名を指定します。 ${POLICY_NAME} はパラメータです。作成するIAMポリシー名を指定します。 ${ROLE_NAME} はパラメータです。作成するIAMロール名を指定します。 ここではクロスリージョンレプリケーションを実現する上で最低限の設定を掲載しています。s3api put-bucket-replication コマンドの設定は多岐に渡りますので、ユースケースに応じて適宜設定を見直してください。 参考 [PCI.S3.4] S3 バケットでは、サーバー側の暗号化を有効にする必要があります [PCI.S3.4] S3 buckets should have server-side encryption enabled 重大度:中 以下の指摘と同様です。 AWS Foundational Security Best Practices [S3.4] S3 バケットでは、サーバー側の暗号化を有効にする必要があります [PCI.S3.5] S3 バケットは、Secure Socket Layer を使用するリクエストを要求する必要があります [PCI.S3.5] S3 buckets should require requests to use Secure Socket Layer 重大度:中 以下の指摘と同様です。 AWS Foundational Security Best Practices [S3.5] S3 バケットは、Secure Socket Layer を使用するためのリクエストが必要です [PCI.S3.6] S3 ブロックパブリックアクセス設定を有効にする必要があります [PCI.S3.6] S3 Block Public Access setting should be enabled 重大度:中 以下の指摘と同様です。 AWS Foundational Security Best Practices [S3.1] S3 ブロックパブリックアクセス設定を有効にする必要があります Security Hub 指摘以外でやるべき設定 ここからは Security Hub では指摘されませんが、やっておいたほうがよい推奨する設定を紹介します。 ACL無効化 ACL (Access Control List) の無効化は AWS re:Invent 2021 で発表された機能です。 AWS も無効化を推奨しています。 CLI s3api put-bucket-ownership-controls コマンドで設定します。 ObjectOwnership の値に BucketOwnerEnforced を設定することにより、ACL が無効化されます。 #=========================================================== # ACL無効化設定 #=========================================================== INPUT_YAML=$(cat << EOS Bucket: ${BUCKET_NAME} OwnershipControls: Rules: - ObjectOwnership: BucketOwnerEnforced EOS ) aws s3api put-bucket-ownership-controls --cli-input-yaml "$INPUT_YAML" ${BUCKET_NAME} はパラメータです。対象のバケット名を指定します。 参考 バージョニング S3 バケットのバージョニングを有効にすると、オブジェクトを誤って削除したり上書きしてしまっても、復元することができます。 ただし、複数のバージョンを保持する分、ストレージコストは増加するので、その点は理解した上で使用しましょう。 CLI s3api put-bucket-versioning コマンドで設定します。 #=========================================================== # バージョニング設定 #=========================================================== INPUT_YAML=$(cat << EOS Bucket: ${BUCKET_NAME} VersioningConfiguration: Status: Enabled EOS ) aws s3api put-bucket-versioning --cli-input-yaml "$INPUT_YAML" ${BUCKET_NAME} はパラメータです。対象のバケット名を指定します。 参考 S3 のセキュリティベストプラクティス ベストプラクティスは読んでおきましょう。 CLI を捧げよ! ここまで解説してきた内容をすべて含めた CLI スクリプトがこちらです。 必ずしも、すべての設定が必要とは限らないので、ユースケースに応じて適宜見直してください。 アカウントレベルのブロックパブリックアクセス設定 secure_s3_account.sh #=========================================================== # アカウントレベルのブロックパブリックアクセス設定 #=========================================================== INPUT_YAML=$(cat << EOS AccountId: "${AWS_ACCOUNT_ID}" PublicAccessBlockConfiguration: BlockPublicAcls: true IgnorePublicAcls: true BlockPublicPolicy: true RestrictPublicBuckets: true EOS ) aws s3control put-public-access-block --cli-input-yaml "$INPUT_YAML" ${AWS_ACCOUNT_ID} には、対象のAWSアカウントID(数字12桁)を指定してください。 レプリケーション用IAMロールの作成 s3_replication_role.sh #=========================================================== # IAMポリシー作成 #=========================================================== POLICY_JSON=$(cat << EOS { "Version": "2012-10-17", "Statement": [ { "Sid": "AllowSourceBucketAccess", "Effect": "Allow", "Action": [ "s3:GetReplicationConfiguration", "s3:ListBucket" ], "Resource": [ "arn:aws:s3:::${BUCKET_NAME}" ] }, { "Sid": "AllowSourceObjectAccess", "Effect": "Allow", "Action": [ "s3:GetObjectVersionForReplication", "s3:GetObjectVersionAcl", "s3:GetObjectVersionTagging" ], "Resource": [ "arn:aws:s3:::${BUCKET_NAME}/*" ] }, { "Sid": "AllowDestinationObjectAccess", "Effect": "Allow", "Action": [ "s3:ReplicateObject", "s3:ReplicateDelete", "s3:ReplicateTags" ], "Resource": [ "arn:aws:s3:::${REPLICATION_BUCKET_NAME}/*" ] } ] } EOS ) INPUT_YAML=$(cat << EOS PolicyName: ${POLICY_NAME} PolicyDocument: '${POLICY_JSON}' EOS ) aws iam create-policy --cli-input-yaml "$INPUT_YAML" #=========================================================== # IAMロール作成 #=========================================================== POLICY_JSON=$(cat << EOS { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "Service": [ "s3.amazonaws.com" ] }, "Action": [ "sts:AssumeRole" ] } ] } EOS ) INPUT_YAML=$(cat << EOS RoleName: ${ROLE_NAME} AssumeRolePolicyDocument: '${POLICY_JSON}' EOS ) aws iam create-role --cli-input-yaml "$INPUT_YAML" #=========================================================== # IAMポリシーのアタッチ #=========================================================== INPUT_YAML=$(cat << EOS RoleName: ${ROLE_NAME} PolicyArn: arn:aws:iam::${AWS_ACCOUNT_ID}:policy/${POLICY_NAME} EOS ) aws iam attach-role-policy --cli-input-yaml "$INPUT_YAML" ${AWS_ACCOUNT_ID} には、対象のAWSアカウントID(数字12桁)を指定してください。 ${BUCKET_NAME} はパラメータです。対象のバケット名を指定します。 ${REPLICATION_BUCKET_NAME} はパラメータです。レプリケーション先のバケット名を指定します。 ${POLICY_NAME} はパラメータです。作成するIAMポリシー名を指定します。 ${ROLE_NAME} はパラメータです。作成するIAMロール名を指定します。 バケットレベルの設定 secure_s3_bucket.sh #=========================================================== # サーバー側の暗号化設定 (SSE-KMS) #=========================================================== INPUT_YAML=$(cat << EOS Bucket: ${BUCKET_NAME} ServerSideEncryptionConfiguration: Rules: - ApplyServerSideEncryptionByDefault: SSEAlgorithm: aws:kms KMSMasterKeyID: ${KMS_KEY_ID} BucketKeyEnabled: true EOS ) aws s3api put-bucket-encryption --cli-input-yaml "$INPUT_YAML" #=========================================================== # バケットレベルのブロックパブリックアクセス設定 #=========================================================== INPUT_YAML=$(cat << EOS Bucket: ${BUCKET_NAME} PublicAccessBlockConfiguration: BlockPublicAcls: true IgnorePublicAcls: true BlockPublicPolicy: true RestrictPublicBuckets: true EOS ) aws s3api put-public-access-block --cli-input-yaml "$INPUT_YAML" #=========================================================== # ロギング設定 #=========================================================== INPUT_YAML=$(cat << EOS Bucket: ${BUCKET_NAME} BucketLoggingStatus: LoggingEnabled: TargetBucket: ${LOGGING_BUCKET_NAME} TargetPrefix: ${BUCKET_NAME} EOS ) aws s3api put-bucket-logging --cli-input-yaml "$INPUT_YAML" #=========================================================== # バージョニング有効化 #=========================================================== INPUT_YAML=$(cat << EOS Bucket: ${BUCKET_NAME} VersioningConfiguration: Status: Enabled EOS ) aws s3api put-bucket-versioning --cli-input-yaml "$INPUT_YAML" #=========================================================== # レプリケーション有効化 #=========================================================== INPUT_YAML=$(cat << EOS Bucket: ${BUCKET_NAME} ReplicationConfiguration: Role: arn:aws:iam::${AWS_ACCOUNT_ID}:role/${ROLE_NAME} Rules: - Status: Enabled Priority: 1 Filter: Prefix: "" DeleteMarkerReplication: Status: Disabled Destination: Bucket: arn:aws:s3:::${REPLICATION_BUCKET_NAME} EOS ) aws s3api put-bucket-replication --cli-input-yaml "$INPUT_YAML" #=========================================================== # ACL無効化設定 #=========================================================== INPUT_YAML=$(cat << EOS Bucket: ${BUCKET_NAME} OwnershipControls: Rules: - ObjectOwnership: BucketOwnerEnforced EOS ) aws s3api put-bucket-ownership-controls --cli-input-yaml "$INPUT_YAML" #=========================================================== # HTTP拒否ポリシー # 他アカウントからの機密API操作拒否ポリシー #=========================================================== POLICY_JSON=$(cat << EOS { "Version": "2012-10-17", "Statement": [ { "Sid": "DenyInsecureRequests", "Effect": "Deny", "Principal": "*", "Action": [ "s3:*" ], "Resource": [ "arn:aws:s3:::${BUCKET_NAME}", "arn:aws:s3:::${BUCKET_NAME}/*" ], "Condition": { "Bool": { "aws:SecureTransport": false } } }, { "Sid": "DenySensitiveActionsFromOtherAccounts", "Effect": "Deny", "NotPrincipal": { "AWS": "${AWS_ACCOUNT_ID}" }, "Action": [ "s3:DeleteBucketPolicy", "s3:PutBucketAcl", "s3:PutBucketPolicy", "s3:PutEncryptionConfiguration", "s3:PutObjectAcl" ], "Resource": [ "arn:aws:s3:::${BUCKET_NAME}", "arn:aws:s3:::${BUCKET_NAME}/*" ] } ] } EOS ) INPUT_YAML=$(cat << EOS Bucket: ${BUCKET_NAME} Policy: '${POLICY_JSON}' EOS ) aws s3api put-bucket-policy --cli-input-yaml "$INPUT_YAML" ${AWS_ACCOUNT_ID} には、対象のAWSアカウントID(数字12桁)を指定してください。 ${BUCKET_NAME} はパラメータです。対象のバケット名を指定します。 ${LOGGING_BUCKET_NAME} はパラメータです。ログ保存先のバケット名を指定します。 ${REPLICATION_BUCKET_NAME} はパラメータです。レプリケーション先のバケット名を指定します。 ${ROLE_NAME} はパラメータです。作成するIAMロール名を指定します。 ${KMS_KEY_ID} はパラメータです。暗号化に使用する KMS Key ID を指定します。 CloudFormation を捧げよ! CloudFormation 版はこちらをご参照ください。 ↓ ↓ ↓ あとがき 最後まで読んでいただき、ありがとうございます。 本記事によって一匹でも多くの Security Hub 指摘を駆逐できれば幸いです。 本記事が好評でしたら、S3 以外の続編も書いていこうと思います。
- 投稿日:2022-03-22T05:15:49+09:00
KMS カスタムキーで暗号化された s3 バケット内のオブジェクトのダウンロードに失敗
カスタムキーを作成して、S3 バケットからファイルをダウンロードしようとしたが、失敗した。 どうやら、カスタムキーの key policy を変更しなければならないようだ。 以下は、AWS KMS の s3 用の managed policy。ここの、一部分をコピーして、作成した KMS の key policy に貼り付けて保存した。 { "Version": "2012-10-17", "Id": "auto-s3-2", "Statement": [ { "Sid": "Allow access through S3 for all principals in the account that are authorized to use S3", "Effect": "Allow", "Principal": { "AWS": "*" }, "Action": [ "kms:Encrypt", "kms:Decrypt", "kms:ReEncrypt*", "kms:GenerateDataKey*", "kms:DescribeKey" ], "Resource": "*", "Condition": { "StringEquals": { "kms:CallerAccount": "<ACCOUNT_ID>", "kms:ViaService": "s3.<REGION>.amazonaws.com" } } }, { "Sid": "Allow direct access to key metadata to the account", "Effect": "Allow", "Principal": { "AWS": "arn:aws:iam::<ACCOUNT_ID>:root" }, "Action": [ "kms:Describe*", "kms:Get*", "kms:List*" ], "Resource": "*" } ] } KMS key を作成したばかりの key policy { "Version": "2012-10-17", "Id": "key-consolepolicy-3", "Statement": [ { "Sid": "Enable IAM User Permissions", "Effect": "Allow", "Principal": { "AWS": "arn:aws:iam::<ACCOUNT_ID>:root" }, "Action": "kms:*", "Resource": "*" }, { "Sid": "Allow access for Key Administrators", "Effect": "Allow", "Principal": { "AWS": "arn:aws:iam::<ACCOUNT_ID>:user/<USER>" }, "Action": [ "kms:Create*", "kms:Describe*", "kms:Enable*", "kms:List*", "kms:Put*", "kms:Update*", "kms:Revoke*", "kms:Disable*", "kms:Get*", "kms:Delete*", "kms:TagResource", "kms:UntagResource", "kms:ScheduleKeyDeletion", "kms:CancelKeyDeletion" ], "Resource": "*" }, { "Sid": "Allow use of the key", "Effect": "Allow", "Principal": { "AWS": "arn:aws:iam::<ACCOUNT_ID>:user/<USER>" }, "Action": [ "kms:Encrypt", "kms:Decrypt", "kms:ReEncrypt*", "kms:GenerateDataKey*", "kms:DescribeKey" ], "Resource": "*" }, { "Sid": "Allow attachment of persistent resources", "Effect": "Allow", "Principal": { "AWS": "arn:aws:iam::<ACCOUNT_ID>:user/<USER>" }, "Action": [ "kms:CreateGrant", "kms:ListGrants", "kms:RevokeGrant" ], "Resource": "*", "Condition": { "Bool": { "kms:GrantIsForAWSResource": "true" } } } ] } AWS の s3用の managed key policy の一部を貼り付けて完成させた key policy。 { "Version": "2012-10-17", "Id": "key-consolepolicy-3", "Statement": [ { "Sid": "Enable IAM User Permissions", "Effect": "Allow", "Principal": { "AWS": "arn:aws:iam::<ACCOUNT_ID>:root" }, "Action": "kms:*", "Resource": "*" }, { "Sid": "Allow access for Key Administrators", "Effect": "Allow", "Principal": { "AWS": "arn:aws:iam::<ACCOUNT_ID>:user/<USER>" }, "Action": [ "kms:Create*", "kms:Describe*", "kms:Enable*", "kms:List*", "kms:Put*", "kms:Update*", "kms:Revoke*", "kms:Disable*", "kms:Get*", "kms:Delete*", "kms:TagResource", "kms:UntagResource", "kms:ScheduleKeyDeletion", "kms:CancelKeyDeletion" ], "Resource": "*" }, { "Sid": "Allow use of the key", "Effect": "Allow", "Principal": { "AWS": "arn:aws:iam::<ACCOUNT_ID>:user/<USER>" }, "Action": [ "kms:Encrypt", "kms:Decrypt", "kms:ReEncrypt*", "kms:GenerateDataKey*", "kms:DescribeKey" ], "Resource": "*" }, { "Sid": "Allow attachment of persistent resources", "Effect": "Allow", "Principal": { "AWS": "arn:aws:iam::<ACCOUNT_ID>:user/<USER>" }, "Action": [ "kms:CreateGrant", "kms:ListGrants", "kms:RevokeGrant" ], "Resource": "*", "Condition": { "Bool": { "kms:GrantIsForAWSResource": "true" } } }, { "Sid": "Allow access through S3 for all principals in the account that are authorized to use S3", "Effect": "Allow", "Principal": { "AWS": "*" }, "Action": [ "kms:Encrypt", "kms:Decrypt", "kms:ReEncrypt*", "kms:GenerateDataKey*", "kms:DescribeKey" ], "Resource": "*", "Condition": { "StringEquals": { "kms:ViaService": "s3.<REGION>.amazonaws.com", "kms:CallerAccount": "<ACCOUNT_ID>" } } } ] } ダウンロードするためのコマンド aws s3 cp s3://<BUCKET_NAME>/<OBJECT_NAME> . --sse aws:kms --sse-kms-key-id <CUSTOM_KEY_ID> (参考リンク) https://aws.amazon.com/jp/premiumsupport/knowledge-center/s3-object-encryption-keys/ https://docs.aws.amazon.com/kms/latest/developerguide/key-policies.html#key-policy-example
- 投稿日:2022-03-22T00:48:02+09:00
AWS Distro for OpenTelemetryのCollectorとGo SDK on Traces Instrumentation
AWS Distro for OpenTelemetry OpenTelemetryは、オープンソースのプロジェクトで、 アプリケーション監視用の分散トレースとメトリックを収集するために、 ライブラリ・API・エージェントが提供されています。 AWS Distro for OpenTelemetryはOpenTelemetryをAWSで使うためのディストリビューションです。 OpenTelemetry自体については、freeCodeCamp.orgの動画が参考になるかと思います。 AWS Distro for OpenTelemetry Collector OpenTelemetry Collectorについてはこちらが参考になります。 こちらのdocker版サンプルを実施します。 以下のソースコードをcheckoutし、exampleフォルダへ移動します。 % git clone https://github.com/aws-observability/aws-otel-collector.git % cd aws-otel-collector/examples/docker/ 以下コマンドで実行します。 % docker-compose up すると、X-Rayでトレースが確認できます。 OpenTelemetry Go SDK on Traces Instrumentation 以下を参考に実施します。 Global Tracerの設定 以下のサンプルアプリを使います。 OpenTelemetry Protocol (OTLP) Exporterの作成 OpenTelemetry Goではバックエンドにトレースを送信する場合には、Exporterが必要になるようです。 ここではADOT Collectorへ送信するため、以下のようにExporterを作成します。 sampleapp/main.go // Create and start new OTLP trace exporter traceExporter, err := otlptracegrpc.New(ctx, otlptracegrpc.WithInsecure(), otlptracegrpc.WithEndpoint("0.0.0.0:4317"), otlptracegrpc.WithDialOption(grpc.WithBlock())) if err != nil { log.Fatalf("%s: %v", "failed to create new OTLP trace exporter", err) } Tracer Providerの作成 Traceの生成用に、Tracer Providerを作成します。 上記で作成したExporterと、ID generatorを設定します。 sampleapp/main.go idg := xray.NewIDGenerator() tp := trace.NewTracerProvider( trace.WithSampler(trace.AlwaysSample()), trace.WithBatcher(traceExporter) trace.WithIDGenerator(idg), ) アプリケーションの実装 エンドポイントが2つ用意されています。 /aws-sdk-callと sampleapp/main.go r.HandleFunc("/aws-sdk-call", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "application/json") ctx := r.Context() xrayTraceID := getXrayTraceID(trace.SpanFromContext(ctx)) json := simplejson.New() json.Set("traceId", xrayTraceID) payload, _ := json.MarshalJSON() _, _ = w.Write(payload) })) /outgoing-http-call こちらはhttpリクエストのタイミングと、その後のカスタム計装の2箇所でspanが作成されています。 sampleapp/main.go r.HandleFunc("/outgoing-http-call", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "application/json") client := http.Client{Transport: otelhttp.NewTransport(http.DefaultTransport)} ctx := r.Context() xrayTraceID, _ := func(ctx context.Context) (string, error) { req, _ := http.NewRequestWithContext(ctx, "GET", "https://aws.amazon.com", nil) res, err := client.Do(req) if err != nil { handleErr(err, "HTTP call to aws.amazon.com failed") } _, _ = ioutil.ReadAll(res.Body) _ = res.Body.Close() return getXrayTraceID(trace.SpanFromContext(ctx)), err }(ctx) ctx, span := tracer.Start( ctx, "CollectorExporter-Example", trace.WithAttributes(commonLabels...)) defer span.End() json := simplejson.New() json.Set("traceId", xrayTraceID) payload, _ := json.MarshalJSON() _, _ = w.Write(payload) })) 以下のコマンドで実行します。 % go build -o sampleapp % ./sampleapp Aws-OTel-Collectorインスタンスの実行 先ほどのdocker版サンプルのシングルインスタンス版を使用します。 AWS_ACCESS_KEY_IDとAWS_SECRET_ACCESS_KEYを環境変数に設定した上で、以下を実行します。 % cd aws-otel-collector/examples/docker/ % docker run --rm -p 4317:4317 -p 55680:55680 -p 8889:8888 \ -e "AWS_ACCESS_KEY_ID=${AWS_ACCESS_KEY_ID}" \ -e "AWS_SECRET_ACCESS_KEY=${AWS_SECRET_ACCESS_KEY}" \ -e AWS_REGION=us-west-2 \ -v "${PWD}/examples/docker/config-test.yaml":/otel-local-config.yaml \ --name awscollector public.ecr.aws/aws-observability/aws-otel-collector:latest \ --config otel-local-config.yaml; この状態で、localhost:8080/aws-sdk-callにアクセスすると、X-Rayで以下トレースが確認できます。 また、localhost:8080/outgoing-http-callにアクセスすると同じく以下が確認できます。 CollectorExporter-Exampleの方のメタデータは以下になっていました。
- 投稿日:2022-03-22T00:13:14+09:00
AWS Chalice で AWS Data Wrangler を利用する
はじめに AWS 上のデータを Pandas1 で処理したいときには、各種 AWS サービス(RDS, DynamoDB, Athena, S3 など)からのデータの load/unload を簡単化してくれる Python モジュール AWS Data Wrangler2 が超便利です。しかも、AWS 自体が開発してオープンソース公開しているものなので、ある程度安心して使えます。 なんですが、この AWS Data Wrangler を Lambda で利用する際には、デプロイパッケージのサイズに適用されるクォータ(未圧縮で 250MB、zip 圧縮済みで 50MB)が問題になります。具体的には、AWS Data Wrangler を普通に pip でインストールすると、それだけでパッケージサイズが 250MB を超えてしまいデプロイすることができません。 実はこの問題、AWS Data Wrangler のドキュメントに示されているとおり、Lambda Layer を活用することで解決できます。本記事では、これを Lambda 開発のための Python フレームワークである AWS Chalice3 を使ったプロジェクトに適用する方法をまとめます。 準備 説明のために、まずは Chalice でシンプルなプロジェクトを用意します。公式のチュートリアル4などにある通り、chalice new-project app_skelton で新たなプロジェクトを作り、生成された app.py に、AWS Data Wrangler のバージョンを出力するだけの Lambda 関数を定義します。 app.py from chalice import Chalice import awswrangler as wr app = Chalice(app_name='app_skelton') @app.lambda_function() def func(event, context): return {'version': wr.__version__} 通常の外部モジュール利用時と同じように、requirements.txt に awswrangler==2.14.0 を追加して、chalice deploy してみると、、、パッケージサイズクォータに引っかかってデプロイできません。 このシンプルなプロジェクトを例に、AWS Data Wrangler を利用できるようにするための方法を説明します。 以下に説明する方法では、requirements.txt に awswrangler に関するモジュール情報を記載しません(追加する必要はありません)。 方法 AWS Chalice で AWS Data Wrangler を利用するためには、Lambda Layer を活用する必要があります。具体的には2つの方法があるのでそれぞれ説明します。 方法1 「AWS が公開している Lambda Layer を活用する」 特定の AWS リージョン5とバージョン6については、AWS Data Wrangler がデプロイされた Lambda Layer を、AWS が公開してくれています。Chalice プロジェクトの設定ファイルでそれらの Layer ARN を指定すれば利用できる、ということです。Chalice プロジェクト側で手を入れる必要がある箇所は、設定ファイルの .chalice/config.json のみで、デフォルトからの差分(diff)は以下のとおり2行(行頭に + のある行)の追加だけです。 .chalice/config.json { "version": "2.0", "app_name": "app_skelton", + "automatic_layer": true, + "layers": ["arn:aws:lambda:ap-northeast-1:336392948345:layer:AWSDataWrangler-Python38:2"], "stages": { "dev": { } } } ちなみに、上記の例で指定している Layer ARN は、Python 3.8 用の AWS Data Wrangler 2.13.0 です6。 方法2 「AWS が配布している Layer 用パッケージを活用する」 方法1 はお手軽ではあるのですが、特定リージョン5以外のリージョンで利用したいときや、公開されている Managed Layer に何らかの原因でアクセスできなくなる等のリスクを回避したいとき、などのために、代替手段が用意されています。それは、AWS が github で配布している Layer 用パッケージ(Lambda のパッケージサイズクォータに引っかからないサイズにコンパクト化したパッケージ)7の活用です。 例えば、Python 3.8 用の AWS Data Wrangler 2.14.0 に対応する Layer 用パッケージを利用する場合、手順は以下のとおりです。 Layer 用パッケージ(awswrangler-layer-2.14.0-py3.8.zip)をダウンロード ダウンロードした zip ファイルを解凍 解凍された python ディレクトリ内を、Chalice プロジェクトのディレクトリ直下の vendorディレクトリに配置8 .chalice/config.json に "automatic_layer": true を追加 .chalice/config.json { "version": "2.0", "app_name": "app_skelton", + "automatic_layer": true, "stages": { "dev": { } } } これで、クォータに引っかかることなく chalice deploy できるようになります。実際にデプロイすると、Lambda 関数などを含むメインパッケージとは別に、AWS Data Wrangler 一式が格納された Lambda Layer が新たに生成されます。デプロイされた Lambda Layer をダウンロードしてサイズを確認すると 44MB ほどでした。上限 50MB に収まる絶妙なサイズです。 おわりに 今回は、Jupyter Notebook 上で書いた ETL 処理を Lambda に移植しようとしたときに必要になったことをまとめてみました。AWS Data Wrangler に限らず、Chalice プロジェクトでサイズが大きめのモジュールを使う場合に活用できると思います。 pandas - Python Data Analysis Library ↩ What is AWS Data Wrangler? — AWS Data Wrangler documentation ↩ Documentation — AWS Chalice ↩ Quickstart — AWS Chalice ↩ 2022年3月21日時点でのドキュメント(Install — AWS Data Wrangler 2.14.0 documentation)によると、ap-northeast-1, ap-southeast-2, eu-central-1, eu-west-1, us-east-1, us-east-2, us-west-2 の計7リージョンで利用できるようです。 ↩ ↩2 2022年3月21日時点でのドキュメント(Install — AWS Data Wrangler 2.14.0 documentation)によると、Python の 3.7 から 3.9、AWS Data Wrangler の 2.12.0 と 2.13.0 に対応する Layer ARN が利用できるとあります。最新版である 2.14.0 用の Layer ARN は記載されていないのですが、Lambda の管理コンソールで調査できる範囲では、Python 3.8 用の AWS Data Wrangler 2.14.0 に対応する Layer ARN(arn:aws:lambda:ap-northeast-1:336392948345:layer:AWSDataWrangler-Python38:3)が存在していて利用もできるようです。 ↩ ↩2 Releases · awslabs/aws-data-wrangler · GitHub ↩ App Packaging — AWS Chalice ↩