20220214のAWSに関する記事は14件です。

CloudWatchアラームで設定した請求金額を超えたらメール通知する

はじめに 個人開発でAWSを利用している方やサーバー周りの経費を削減したい会社さんは少なからずいらっしゃると思います。 あらかじめアラートを受けることができたらサーバーをサイズダウンするなどして対策が取れるかと思います。 請求金額を超えたらメールでアラート通知がほしいといった方のためにぜひ参考にしていただけたらです。 目次 AWS SNSでトピックを作成する(通知を受け取るメールアドレスの登録) AWS SNSでサブスクリプションを作成する 請求設定の請求アラートを有効化する CloudWatchアラーム設定をする AWS SNSでトピックを作成する(通知を受け取るメールアドレスの登録) Amazon SNS>左のメニュー トピック>トピックの作成を押下 タイプはスタンダードを選択 名前を入 トピックの作成を押下 AWS SNSでサブスクリプションを作成する Amazon SNS>左のメニュー トピック>サブスクリプション>サブスクリプションの作成を押下 プロトコルは今回「Eメール」を選択します。 エンドポイントにアラートを受け取るメールアドレスを記入します。 サブスクリプションの作成を押下します。 トピック>サブスクリプション に先程追加したメールアドレスが表示されています。このメールアドレスにAWSから認証確認のメールが届くので、開いたら「confirm subscription」をします。 するとステータスが「保留中の確認」から「確認済み」となるはずです。 請求設定の請求アラートを有効化する 右上のアカウント>アカウント>左メニューの請求設定から以下のチェックボックスにチェックします。 CloudWatchアラーム設定をする cloudwatchのコンソールに移動し、リージョンは「米国東部バージニア北部」にします。 ちなみに、リージョンをバージニアにするのは 請求メトリクスデータは米国東部 (バージニア北部) リージョンに保存され、世界全体の請求額として表されます。 ↑東京リージョンもその他リージョンも請求はバージニアで管理しているかららしいです。 左メニューのアラーム>すべてのアラーム>アラームの作成と進みます。 メトリクスの選択を押下します。 請求>概算合計請求額>EstimatedChargesをチェック>メトリクスの選択を押下します。 請求アラートの金額を設定>次へを押下 今回はテストとしてしきい値に 1 USDと設定しました。 ・SNSのトピックの選択 →既存のSNSトピックを選択 ・通知の送信先 →先程作成した「billing-alarm-topic」を選択 次へを押下 ・アラーム名を入力>次へ>アラームの作成 確認 今回は$1を設定したので予想請求金額が$1を超えたらメールが届くことを確認できると思います。 最後に アラーム作成時点で設定したしきい値が現在の予想請求金額より低い場合は、アラームを作成したら即時にメールが配信されます。 参考
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

TerraformのAWS Provider v4メジャーアップデートは破壊的変更あり

この記事の要約 2022/02/10に、TerraformからAWS Provider v4.0.0がリリースされました。このメジャーアップデートには破壊的変更が含まれおり、今まで利用していたTerraformのソースコードが動かなくなる恐れがあります。安易にAWS Provider のバージョンを上げてしまうと今までのソースコードがエラーを吐くようになります。特にS3に関する破壊的変更は影響範囲が大きいと思われます。情報をまとめておければと思います。 S3に関する破壊的変更 v4.0.0の変更点の全容 リリースノート中にdeprecatedと書かれていますが破壊的変更です。ご注意を。 暫定対応 AWS Providerの最新リリースを利用しないように設定する。 公式サイトより terraform { required_providers { aws = "~> 3.74" } } エラー文言 エラーが発生するコードとそのエラー文言を https://github.com/hashicorp/terraform-provider-aws/issues/23103 より引用 s3.tf resource "aws_s3_bucket" "mybucket" { bucket_prefix = "myname-" acl = "private" versioning { enabled = true } server_side_encryption_configuration { rule { apply_server_side_encryption_by_default { sse_algorithm = "AES256" } } } } error_output Error: Value for unconfigurable attribute │ │ with module.common.aws_s3_bucket.mybucket, │ on ../../s3.tf line 1, in resource "aws_s3_bucket" "mybucket": │ 1: resource "aws_s3_bucket" "mybucket" { │ │ Can't configure a value for "server_side_encryption_configuration": its value will be decided automatically based on the result of applying this configuration. ╵ ╷ │ Error: Value for unconfigurable attribute │ │ with module.common.aws_s3_bucket.mybucket, │ on ../../s3.tf line 1, in resource "aws_s3_bucket" "mybucket": │ 1: resource "aws_s3_bucket" "mybucket" { │ │ Can't configure a value for "versioning": its value will be decided automatically based on the result of applying this configuration. ╵ ╷ │ Error: Value for unconfigurable attribute │ │ with module.common.aws_s3_bucket.mybucket, │ on ../../s3.tf line 3, in resource "aws_s3_bucket" "mybucket": │ 3: acl = "private" │ │ Can't configure a value for "acl": its value will be decided automatically based on the result of applying this configuration. v4系へのアップグレードガイド 公式アップグレードガイド 特にS3リソースのアップグレードはこちら そもそもなんでこういう変更を加えたのか v4.0.0に関する公式ブログ 「aws_s3_bucketリソースは最も古くて大きくてよく使われているけれど、バケットの設定や管理に関するAPIの呼び出しを、この一つのリソースの中で設定するとかなり複雑になってしまい、ユーザにとっても大変である。設定をよりシンプルに、きめ細かくできるよう、aws_s3_bucketリソース一つで負っていた責務を分散することにした。」 という感じ(適当訳) 参考になったIssueなど v4へのアップデートに関して書かれた良い記事↓ https://www.infoq.com/news/2022/02/terraform-aws-provider-s3/ https://github.com/hashicorp/terraform-provider-aws/issues/20433 https://github.com/hashicorp/terraform-provider-aws/issues/23103 https://github.com/hashicorp/terraform-provider-aws/issues/23106 https://github.com/hashicorp/terraform-provider-aws/issues/23125 私見 上にあげたようなIssueの他にも、今回のメジャーバージョンアップデートによる影響と思われるIssueが、この数日でいくつも挙げられています。私自身、情報が追えておらず、突然動かなくなってびっくりしました。(バージョン管理が甘かった。) S3自体はAWSの中でも最も古いサービスの1つだと思うので、長年のAWS側の機能拡張をterraform側に取り込んできたことによって、aws_s3_bucketの設定項目が複雑化・肥大化してしまい、分割せざるを得なかったのだろうと感じます。 それにしても、破壊的な変更は・・・とか、巨大組織で既に運用されてるtfファイルを簡単に移行できないよ・・・とか、terraformより良いツールあるよ・・・とか、今回のメジャーアップデートに関してはみなさん色々な意見があると思います。 気づいたことがあればコメントください。熱が冷めていないうちは記事を更新します。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Kinesis Data Analytics概要

背景・目的 仕事で触る機会があるので、Kinesis Data Analytics(以降、KDAと呼ぶ。)とFlinkを学ぶ。 本ページでは、KDAについて学ぶ。 内容 概要 AWSのページを見ると「サーバーレスでフルマネージドな Apache Flink でストリーミングデータから実用的なインサイトを取得」とある。 ユースケースは、以下の通り。 ストリーミングデータを数秒で配信。OpenSearchやS3などに配信 インタラクティブにクエリを実行し分析する。 長時間実行されるステートフルな計算を使用して、過去のデータトレンドに基づく異常検出などのリアルタイムアクションをトリガーする。 特徴 サーバレス 継続処理するためのインフラの自動プロビジョニング 自律的な伸縮性と従量課金 着信データストリームに含まれる任意の量のデータに対応するために、アプリケーションを伸縮自在にスケールする。 ストリーミングアプリケーションの実行に使用されるリソースに対してのみ料金が発生する。 ミリ秒単位の処理速度 アラート、ダッシュボード、および実用的なインサイトをリアルタイムで生成可能。 Apache Flink を使用したストリーム処理アプリケーション OSS KDAには、Apache Flink、Apache Beam、Apache Zeppelin、AWS SDK、AWS のサービス統合などのオープンソースライブラリが含まれている。 Apache Flink は、高可用性で正確なストリーミングアプリケーションを構築するためのオープンソースのフレームワークおよびエンジンである。 Apache Beam は、複数の実行エンジンで実行できるストリーミングおよびバッチデータ処理アプリケーションを定義するためのオープンソースの統合モデルである。 AWS SDK は、好みの言語で API を提供することで多くの AWS のサービスでのコーディングの複雑さを解消する。 柔軟な API ステートフルなイベント処理、ストリーミング ETL、リアルタイム分析など、さまざまなユースケースに特化した柔軟な API が Java、Scala、Python、SQL で提供される。 事前に構築された演算子と分析機能を使用して、数時間で Apache Flink ストリーミングアプリケーションを構築可能。 AWSのサービスとの統合 KDAライブラリを使用して、以下のサービスと統合可能 S3 Amazon Managed Streaming for Apache Kafka (Amazon MSK) Amazon OpenSearch Service Amazon DynamoDB(DDB) Amazon Kinesis Data Streams(KDS) Amazon Kinesis Data Firehose(KFH) Amazon CloudWatch AWS Glue Schema Registry アドバンスト統合機能 KDAライブラリには、 Apache Flink からの 10 以上のコネクタと、カスタム統合の構築機能が含まれる。 AWS Glue スキーマレジストリとの互換性 Flink向けKDAは、AWS Glue スキーマレジストリと互換性がある。 登録済みの Apache Avro スキーマを使用してストリーミングデータの進化を検証および制御する。 スキーマレジストリは、Apache Kafka に接続するための Apache Flink ワークロード向け KDA、MSK、KDSのスキーマをソースまたはシンクとして管理するのに役立つ。 データストリーミングアプリケーションがスキーマレジストリと統合している場合、スキーマの進化を管理する互換性チェックを利用して、データ品質を向上し、予期しない変更から保護する事が可能。 正確に 1 回の処理 Exactly Once. サービスはすべてのデータが処理され、重複するデータが存在しないことを保証可能。 ステートフル処理 実行中のアプリケーションストレージに、以前のまたは実行中の計算や状態を保存する。 リアルタイムおよび過去の結果を任意の期間にわたって比較することができ、アプリケーション中断時に迅速なリカバリが可能。 状態は常に暗号化され、実行中のアプリケーションストレージに増分として保存可能。 耐久性のあるアプリケーションのバックアップ 簡単な API コールを使用して、耐久性のあるアプリケーションのバックアップを作成および削除可能。 中断後すぐに最新のバックアップからアプリケーションの復元や、以前のバージョンにアプリケーションを復元も可能。 Amazon Kinesis Data Analytics Studio ストリームの検査と可視化 KDA Studioを使えば、組み込み可視化機能を備えている。 1秒未満のクエリをサポート。 アドホックなクエリを実行して、データ ストリームをすばやく検査し、数秒で結果を表示することが可能。 シンプルなビルドと実行の環境 コードの開発、デバッグ、およびストリーム処理アプリケーションの実行のための単一インターフェイスによる開発エクスペリエンス体験を提供する。 SQL、Python、Scala を使用した処理 KDA Studioは、同じ開発環境で SQL、Python、Scala をサポートしている。 サーバーレスの、ストリーム処理アプリケーションの迅速な開発 プロビジョニング、管理、スケーリングするサーバーはなく、コードを書くだけ アプリケーションが消費するリソースについて料金を支払うのみ。 ノートブック内のコードを、自動スケーリングと永続的な状態で継続的に実行されるストリーム処理アプリケーションに簡単にデプロイ可能。 OSS KDA Studioは、本番環境で使用される Apache Flink アプリケーション上で実行および生成される。 Apache Zeppelin ノートブックは、選択した言語でストリーミング アプリケーションを作成するための使い慣れた使いやすいエクスペリエンスを提供. AWS Glue データカタログの使用開始 KDA Studio は、ソーステーブルと宛先テーブルのスキーマを定義できる AWS Glue データカタログと互換性がある。 Kinesis Data Analytics SQL アプリケーション 新しいプロジェクトでは、SQL アプリケーション用の KDA ではなく、新しい KDA Studio の使用をお勧め。 KDA Studio は使いやすさと高度な分析機能を組み合わせており、洗練されたストリーム処理アプリケーションでも数分で構築可能。 標準 SQL のサポート 標準 ANSI SQL がサポート 統合された入力および出力 KDAは、KDSとKFHと統合されているので、ストリーミングデータをかんたんに取り込むことが可能。 コンソールベースの SQL エディタ コンソールベースのエディタを利用することで、ストリーミングデータを使用して、スライディング時間枠平均のように SQL クエリを構築可能。 ライブデータを使用してストリーミングの結果やエラーを表示することで、デバッグしたり、インタラクティブにスクリプトを改良したりすることが可能. 簡単に使用できるスキーマエディタ KDAが提供する使いやすいスキーマエディタを利用することにより、入力データの構造を把握して編集可能。 事前構築 SQL テンプレート インタラクティブな SQL エディタには、集計、イベントごとの変換、フィルタリングなど、最も一般的な操作のベースライン SQL コードを提供する SQL テンプレートのコレクションが付属。 分析タスクに適切なテンプレートを選択して、SQL エディタを使用して提供されているコードを編集し、特定のユースケースに合わせてカスタマイズするだけで済む。 高度なストリーム処理機能 KDA にはストリーム処理向けに最適化された機能が備わっているため、ストリーミングデータの異常検出や top-K 分析といった高度な分析を簡単に実施可能。 参考
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

AWSの学習をするうえでわからなかった横文字をひたすらまとめておく

はじめに はじめにもなにも題名の通り。ひたすら書いていく。 ダウンタイム 常に使用できることが期待されているシステムとかサービスが停止・中断してしまっている時間のこと。 レイテンシー データの転送に関しての指標のひとつ。データの転送を要求してから実際にデータが送られてくるまでに生じる通信の遅延時間のこと。 マネージド型 通信サービスやITサービスなどで、そのサービスの利用に必要な機器やソフトウェアの導入や管理、運用などの業務もすべて請け負うサービスのこと。 スパイク 何かが急激に増加すること。 スティッキーセッション ロードバランサーの機能の1つ。セッションがつづいている間は同じクライアントを同じサーバーに誘導すること。 スナップショット ある時点(瞬間)でのソースコードやファイル、データベースファイルなどの情報(状態)を保存したもののこと。 シーケンス あらかじめ決められた順序で処理を行うこと。 スループット 一定時間にどれだけの処理ができるのか、そのデータ量のこと。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Everything (It's you)をComprehendしてみた

Mr.Childrenの言わずと知れた名曲をComprehendに投入してみました。 ミスチル好きなものでして。 Amazon Comprehendとは テキストを分析し、感情の判定やキーフレーズ検出などを行うことができる、機械学習を利用した自然言語処理(NLP)サービスです。コンソールから1分もかからずに分析できてしまいます。 解析されるインサイトは以下の6つ。 エンティティ キーフレーズ PII 言語 感情 構文 リアルタイム解析を実行 Input text に解析したい文章を入力しAnalyze! これだけです。たったこれだけで解析されちゃいます。Everything (It's you)の歌詞を入力し解析実行! 解析結果 6つのインサイト Entities 人、場所、位置などの情報に自動的に分類される情報。 STAY は人名と認識されたようです。 API Response.json { "Entities": [ { "Score": 0.6422388553619385, "Type": "DATE", "Text": "少年時代", "BeginOffset": 8, "EndOffset": 12 }, { "Score": 0.7727364897727966, "Type": "DATE", "Text": "今", "BeginOffset": 100, "EndOffset": 101 }, { "Score": 0.5865667462348938, "Type": "QUANTITY", "Text": "両手", "BeginOffset": 233, "EndOffset": 235 }, { "Score": 0.5952135920524597, "Type": "PERSON", "Text": "STAY", "BeginOffset": 322, "EndOffset": 326 }, { "Score": 0.5447555780410767, "Type": "QUANTITY", "Text": "一つ", "BeginOffset": 395, "EndOffset": 397 } ] } Key phrases 「キーフレーズ」と分析されたフレーズとその信頼スコア 「世間」「少年時代」「自分」などが上位のようです。 API Response.json { "KeyPhrases": [ { "Score": 0.9991187453269958, "Text": "世間", "BeginOffset": 0, "EndOffset": 2 }, { "Score": 0.994473397731781, "Text": "少年時代", "BeginOffset": 8, "EndOffset": 12 }, { "Score": 0.9939662218093872, "Text": "自分", "BeginOffset": 14, "EndOffset": 16 }, { "Score": 0.9875624179840088, "Text": "心", "BeginOffset": 26, "EndOffset": 27 }, { "Score": 0.9364995956420898, "Text": "人の支えの中", "BeginOffset": 29, "EndOffset": 35 }, { "Score": 0.98807293176651, "Text": "現在の僕", "BeginOffset": 43, "EndOffset": 47 }, { "Score": 0.985284149646759, "Text": "弱音", "BeginOffset": 48, "EndOffset": 50 }, { "Score": 0.9150426983833313, "Text": "グチ", "BeginOffset": 56, "EndOffset": 58 }, { "Score": 0.9841071963310242, "Text": "他人の傷み", "BeginOffset": 64, "EndOffset": 69 }, { "Score": 0.9866365790367126, "Text": "ふり", "BeginOffset": 76, "EndOffset": 78 }, { "Score": 0.6099014282226562, "Text": "すぎ", "BeginOffset": 83, "EndOffset": 85 }, { "Score": 0.7314071655273438, "Text": "事", "BeginOffset": 89, "EndOffset": 90 }, { "Score": 0.9500252604484558, "Text": "今", "BeginOffset": 100, "EndOffset": 101 }, { "Score": 0.8240435719490051, "Text": "言葉さえも見つからぬまま", "BeginOffset": 106, "EndOffset": 118 }, { "Score": 0.6586101055145264, "Text": "時間", "BeginOffset": 118, "EndOffset": 120 }, { "Score": 0.716262936592102, "Text": "途方", "BeginOffset": 124, "EndOffset": 126 }, { "Score": 0.6114963889122009, "Text": "人よ", "BeginOffset": 134, "EndOffset": 136 }, { "Score": 0.5545666217803955, "Text": "君", "BeginOffset": 137, "EndOffset": 138 }, { "Score": 0.721443772315979, "Text": "に", "BeginOffset": 143, "EndOffset": 144 }, { "Score": 0.6975231766700745, "Text": "苦しみに似た", "BeginOffset": 144, "EndOffset": 150 }, { "Score": 0.6116013526916504, "Text": "想いを", "BeginOffset": 151, "EndOffset": 154 }, { "Score": 0.8357267379760742, "Text": "STAY", "BeginOffset": 159, "EndOffset": 163 }, { "Score": 0.7455344200134277, "Text": "何", "BeginOffset": 163, "EndOffset": 164 }, { "Score": 0.9078458547592163, "Text": "犠牲", "BeginOffset": 165, "EndOffset": 167 }, { "Score": 0.9965271353721619, "Text": "もの", "BeginOffset": 176, "EndOffset": 178 }, { "Score": 0.9996755123138428, "Text": "僕", "BeginOffset": 184, "EndOffset": 185 }, { "Score": 0.9795992374420166, "Text": "今", "BeginOffset": 189, "EndOffset": 190 }, { "Score": 0.5885325074195862, "Text": "君", "BeginOffset": 190, "EndOffset": 191 }, { "Score": 0.9860681295394897, "Text": "それ", "BeginOffset": 193, "EndOffset": 195 }, { "Score": 0.9740948677062988, "Text": "夢追い人", "BeginOffset": 205, "EndOffset": 209 }, { "Score": 0.9694126844406128, "Text": "旅路", "BeginOffset": 210, "EndOffset": 212 }, { "Score": 0.5604091286659241, "Text": "一体", "BeginOffset": 216, "EndOffset": 218 }, { "Score": 0.6506443619728088, "Text": "何", "BeginOffset": 218, "EndOffset": 219 }, { "Score": 0.516764760017395, "Text": "手", "BeginOffset": 220, "EndOffset": 221 }, { "Score": 0.9917513728141785, "Text": "嘘や矛盾", "BeginOffset": 228, "EndOffset": 232 }, { "Score": 0.8492306470870972, "Text": "両手", "BeginOffset": 233, "EndOffset": 235 }, { "Score": 0.9291658401489258, "Text": "それも人", "BeginOffset": 239, "EndOffset": 243 }, { "Score": 0.9886345863342285, "Text": "人", "BeginOffset": 256, "EndOffset": 257 }, { "Score": 0.9289801716804504, "Text": "君", "BeginOffset": 259, "EndOffset": 260 }, { "Score": 0.995627760887146, "Text": "これ", "BeginOffset": 268, "EndOffset": 270 }, { "Score": 0.8548830151557922, "Text": "恋", "BeginOffset": 272, "EndOffset": 273 }, { "Score": 0.8810998797416687, "Text": "STAY僕", "BeginOffset": 279, "EndOffset": 284 }, { "Score": 0.8819072246551514, "Text": "荷物", "BeginOffset": 297, "EndOffset": 299 }, { "Score": 0.9923756718635559, "Text": "君", "BeginOffset": 302, "EndOffset": 303 }, { "Score": 0.9759371280670166, "Text": "ドア", "BeginOffset": 307, "EndOffset": 309 }, { "Score": 0.7493122816085815, "Text": "STAY", "BeginOffset": 322, "EndOffset": 326 }, { "Score": 0.8759680390357971, "Text": "何", "BeginOffset": 326, "EndOffset": 327 }, { "Score": 0.9159817099571228, "Text": "犠牲", "BeginOffset": 328, "EndOffset": 330 }, { "Score": 0.9839121699333191, "Text": "もの", "BeginOffset": 340, "EndOffset": 342 }, { "Score": 0.9930424690246582, "Text": "それ", "BeginOffset": 348, "EndOffset": 350 }, { "Score": 0.9922454953193665, "Text": "僕", "BeginOffset": 351, "EndOffset": 352 }, { "Score": 0.5670811533927917, "Text": "もう", "BeginOffset": 359, "EndOffset": 361 }, { "Score": 0.5696842670440674, "Text": "君", "BeginOffset": 361, "EndOffset": 362 }, { "Score": 0.9778668284416199, "Text": "自分", "BeginOffset": 371, "EndOffset": 373 }, { "Score": 0.6204937100410461, "Text": "犠牲", "BeginOffset": 374, "EndOffset": 376 }, { "Score": 0.9709562063217163, "Text": "もの", "BeginOffset": 389, "EndOffset": 391 }, { "Score": 0.8189772963523865, "Text": "ただ一つ君", "BeginOffset": 393, "EndOffset": 398 }, { "Score": 0.9007982611656189, "Text": "いつ", "BeginOffset": 402, "EndOffset": 404 }, { "Score": 0.8109763264656067, "Text": "君", "BeginOffset": 407, "EndOffset": 408 } ] } Language 言語判定です。もちろん日本語として解析されています。 API Response.json { "Languages": { "LanguageCode": "ja", "Score": 0.9694656729698181 } } PII 個人識別情報を検出できるようですが、日本語はまだ未対応のようです。 Sentiment 感情が以下の4つに分類されます。77%でポジティブとなりました。 Neutral(ニュートラル) Positive(ポジティブ) Negative(ネガティブ) Mixed(混在) API Response.json { "Sentiment": { "Sentiment": "POSITIVE", "SentimentScore": { "Positive": 0.7775697112083435, "Negative": 0.015565356239676476, "Neutral": 0.19310088455677032, "Mixed": 0.013764000497758389 } } } Syntax 名詞、形容詞、動詞などの構文解析(シンタックス)も日本語には対応していないようです。 まとめ とりあえず分析してみると思わぬ見え方ができて面白いかも。 いろんな歌詞を試してみたい!
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

AWSのチュートリアルでハマった話

チュートリアルなのにハマる AWSは一年ほど前に少しだけ勉強したことがあったので、簡単って言ってるlambdaなら楽勝でしょ? から、数時間ハマったので備忘録として投稿 試したチュートリアル テストでエラー チュートリアル通りに進めて行って、「コンソールでテストする」の箇所でエラー。 公式のチュートリアルなんだから手順通りにやっていれば必ず上手くいくはずと思って、何度もチュートリアルを見直して初めからやったりしたがダメ An error occurred (AccessDenied) when calling the GetObject operation: Access Denied 解決した方法 諦めてエラーメッセージなどで調べたらIAMの設定がダメっぽいので、試しにlambdaに設定しているIAMロールにAmazonS3ReadOnlyAccessを追加してみたら普通に成功 よくよくエラーメッセージを読んでみれば、GetObjectの呼び出しでエラーって書いてある… その後、AmazonS3ReadOnlyAccessをロールから削除して、IAMポリシーの"GetObject"の部分を"Get*"に変更してみたら普通に動きました。 反省 様々にサービスが追加され続けているので、チュートリアル記載時点から変更があった影響なのかな?と思いました。 教訓として、エラーメッセージをきちんと読んで自分で考えること!
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

AWS App Runner に ECR をトリガーに自動デプロイをしてみた

はじめに 前回の記事では、ECR に Push したコンテナイメージを App Runner にデプロイする方法を紹介しました。 今回の記事では、ECR に新しいバージョンのコンテナイメージを Push することで、自動でバージョンアップ(Blue Green デプロイ)されることを確認します。 デプロイの詳細な流れは、下記の App Runner 入門動画に公開されています。 前提条件 App Runner の Service を構成するときに、Deployment settings を Automatic に設定していることが条件です。 バージョンアップ前 App Runner で稼働しているアプリケーションは、次の状態になっています。 コンテナをバージョンアップして ECR に Push Go言語のプログラムを変更して、バージョンに関する文字列を付与します。 package main import ( "database/sql" "fmt" "net" "net/http" "os" "time" _ "github.com/go-sql-driver/mysql" ) var db *sql.DB func handler(w http.ResponseWriter, r *http.Request) { // バージョンの表示 fmt.Fprintf(w, "バージョン2\n") fmt.Fprintf(w, "\n") // MySQL のデータを表示 row := db.QueryRow(`select * from sample`) var id, name string row.Scan(&id, &name) println(name) fmt.Fprintf(w, name+"\n") fmt.Fprintf(w, "\n") // ローカルのIPアドレスを表示 fmt.Fprintf(w, "IPアドレス一覧"+"\n") interfaces, err := net.Interfaces() if err != nil { fmt.Println(err) return } for _, inter := range interfaces { addrs, err := inter.Addrs() if err != nil { fmt.Println(err) return } for _, a := range addrs { if ipnet, ok := a.(*net.IPNet); ok { if ipnet.IP.To4() != nil { fmt.Println(ipnet.IP.String()) fmt.Fprintf(w, ipnet.IP.String()+"\n") } } } } } func main() { // MySQL のコネクションを取得 mysql_hostname := os.Getenv("MYSQL_HOSTNAME") mysql_port := os.Getenv("MYSQL_PORT") mysql_username := os.Getenv("MYSQL_USERNAME") mysql_password := os.Getenv("MYSQL_PASSWORD") var err error db, err = sql.Open("mysql", mysql_username+":"+mysql_password+"@tcp("+mysql_hostname+":"+mysql_port+")/sugi01") if err != nil { println("MySQL のコネクション接続に失敗") panic(err) } defer db.Close() db.SetConnMaxLifetime(time.Minute * 3) db.SetMaxOpenConns(10) db.SetMaxIdleConns(10) http.HandleFunc("/", handler) // ハンドラを登録してウェブページを表示させる http.ListenAndServe(":8080", nil) } アプリケーションを動かし、動作確認をします。 go run app.go トップに「バージョン2」という文字を表示するようにしました。これで、どのバージョンが稼働しているかわかりやすいです。 go プログラムをビルドします。 go build -o app Docker Image を Build します。 docker image build -t xxxxxxxxxxxx.dkr.ecr.ap-northeast-1.amazonaws.com/app-runner-testapp:0.0.2 . docker image build -t xxxxxxxxxxxx.dkr.ecr.ap-northeast-1.amazonaws.com/app-runner-testapp:latest . ECR に Push します docker push xxxxxxxxxxxx.dkr.ecr.ap-northeast-1.amazonaws.com/app-runner-testapp:0.0.2 docker push xxxxxxxxxxxx.dkr.ecr.ap-northeast-1.amazonaws.com/app-runner-testapp:latest ECR に Push されました App Runner で自動更新 ECR に Push したことをトリガーに、新しいバージョンのデプロイプロセスが走ります。 この Operation 中でも、問題なく前のバージョンのアプリケーションにアクセスできます。この記事の環境だと、約2分ほど待つと Status が Running になりました。 App Runner の Service にアクセスしてみると、正常にバージョンアップがされています。 まとめ App Runner の設定で自動デプロイを有効にすることで、ECR の更新をトリガーにした 自動 Blue Green デプロイメントを行うことが出来ました。CD パイプラインを自分たちで組む必要がないので、とても簡単で体験が良いですね。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

静的WEB via CloudFrontにRUMを入れてモニタリングしてみる

TL;DR re:Invent 2021で発表されたCloudWatchの新機能「CloudWatch RUM(Real-User Monitoring)」を使ってCloudFrontで配信中のNext.js製WEBをモニタリングしてみました。 CloudWatch RUM is 何? 以下、公式ドキュメント より引用。 CloudWatch RUM を使用すると、現実的なユーザーモニタリングを実行できます。ウェブアプリケーションのパフォーマンスに関するクライアント側のデータを、ほぼリアルタイムで実際のユーザーセッションから収集し、それを表示できます。ページの読み込み時間、クライアント側のエラー、およびユーザーの活動などのデータを、視覚化および分析することが可能です。この表示機能では、すべてのデータを集約的に見ることができ、同時に、顧客が使用しているブラウザやデバイスに関する詳細も確認できます。 はい、WEBのアクセス解析サービスですね。 他社サービスだと、Google AnalyticsやAdobe Analyticsがあります。アクセス解析サービスとしては他社と比較すると後発ですが、本機能の登場でAWSでホスティング〜アクセス解析まで一気通貫で実現できるようになりました。「WEBはAWSでホスティングしているけど、アクセス解析は他社サービスを利用」といった具合の泣き別れも解消できるはず! Next.js製WEBに導入してみる 全体構成 CloudWatch RUMでは、S3に格納している静的コンテンツにRUM用JavaScriptを仕込んでおき、クライアントからのリクエスト時にトラッキング用スクリプトが発火、CloudWatch RUMに対してデータを投げ込む、という仕組みです。 1. アプリケーションモニターを追加 CloudWatchコンソールからRUMの設定をしていきます。デフォ設定のままでトレースできます。優しい。 設定項目を何個かピックアップ - データストレージ - 「CloudWatch RUM により収集されたエンドユーザーデータは、30日間保持された後で自動的に削除されます」と公式ドキュメントに記載が。30日以上前のデータに遡及して分析したい場合はこのチェックをONにしておきましょう。CloudWatchLogsにデータを保存してくれます。(CWLogs側の期限設定も忘れずに) - 承諾(Authorization) - 日本語訳に違和感ありですが、原文だとAuthorizationです。Cognito IDプールを利用してクライアントからのデータ送信を許可する模様。Cognitoでは無認証のIDがサポートされており、この機能を利用することでクライアント側にてCloudWatch RUMへのデータ送信が許可されたIAMロール(※)を引き受けることが可能となります。「新しいIDEAプールを作成する」を選択でOK。 - (※) rum:PutRumEvents のAllow権限が付与されます - アクティブトレース - X-Rayトレースを有効化することができます。有効化することでセッション中のXMLHttpRequestおよびfetchリクエストをトレースする事が可能になり、RUMダッシュボード、CloudWatch ServiceLensコンソール、X-Rayコンソール上で確認できるようになります。今回はONに設定を変更。設定項目「セッションサンプル」で100%指定しているので、今回の場合だと全セッショントレース対象となります。 2. スニッペスト取得 必要項目の入力が完了すると、コードスニッペストが表示されます。これを控えて静的コンテンツに貼り付けます。(控えるの忘れても後で再確認可能) 3. スニッペストを埋め込み ぶっちゃけ、ここが一番苦労しました。。 Next.jsでは_app.tsxに全ページ共通の項目を記載するのですが、<Head>タグの中にスクリプトを埋め込むとエラーが複数発生。 SyntaxError: '}' expected. だの Cannot find name 'sessionSampleRate'.ts、等 エラー吐きまくりでSSGできませんでした。 結局、静的コンテンツを生成した後の生HTMLファイルに先程のスニッペストを貼り付けてデプロイをすると問題なく動きました。(フロント強者の方、是非良い方法を教えていただきたく、、!) ダッシュボードを眺めてニヤニヤする ダッシュボードに表示できる物が多すぎるので、全量は紹介しきれませんが、幾つか面白いものをピックアップしてみます。 パフォーマンス>リソースリクエスト 各種リソース取得にかかったロード時間を表示することが可能です。 WEBページの表示が遅いんだけど!といった際に、どこがボトルネックになっているのかを確認することができます。 (今回のパターンだと、RUM実行用スクリプトの取得に一番時間がかかっています) パフォーマンス>経時的なリソースリクエスト リクエスト数を可視化することができます。今回の例だとCloudFront+S3なのであまり考慮する必要はありませんが、EC2やECSでWEBホスティングをしている場合、リクエスト数が多い時間帯は事前にスケールアウトしておく、といったリソース戦略を実現することが可能となります ユーザージャーニー ページ遷移をマッピングし、ドロップオフ(=WEB離脱)を確認することができます。 例えば複数ページにまたがるフォームを実装している際に、どのページで離脱したか?を確認することでページ構成を最適化するためのヒントとして活用、コンバージョン率の向上を期待できます。 ブラウザとデバイス WEBにアクセスしてきたブラウザ内訳を確認することができます。 クライアントから飛んでくるUserAgentを元に集計して統計を出してくれます。 エンタープライズのシステムだと、エンドユーザに対して動作保証ブラウザを設定していたりしますが、その際の保証ブラウザ×バージョン選定に役立てることができそうですね。IE対応しなきゃいけないんだよ!といってくる人にはこの画面を見せつけましょう。 まとめ とうとうAWS純正のWEBアクセス解析サービスが登場したので使ってみました。 他社製品と比べても利用できる機能は遜色なく、ようやくAWSだけでWEB監視やトレースを完結させることが可能となりました。 もちろんAWSの他サービスとの連携も可能で、RUMのメトリクスを監視、CloudWatch Alarmを仕込んで閾値を超えたらLambdaやSlackをフック といった使い方も可能です。外形監視のCloudWatch Synthetics等も組み合わせるとより信頼性の高いWEB運用が可能になるのではないでしょうか。 備考 GoogleAnalyticsについて調べていると、日経新聞にこんな記事がありました。 米にGoogleアナリティクスの情報送信 仏当局「違法」 フロントエンド界隈では3rdパーティ製Cookieも制限されたことですし、そのうちWEBアクセス解析ツールも規制されるのか..!?
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

AWS Lambda (Node.js) 上で discord.js を使おうとしてつまずいた

何につまずいたのか ざっくり言うと、 Node.js で記載した AWS Lambda の関数上で最新版の discord.js を使おうとしたら使えなかった。 なぜ使えなかったのか AWS Lambda で使える Node.js のバージョンが現状 v14 系までなのに対し、最新版の discord.js は v16.6.0 以上でしか動かない。 現状の打開策 どうしても使いたいなら古いバージョンの discord.js ( 12.5.3 がギリギリ Node.js v14 系に対応している模様)を使うしかない。ただし、非推奨になっているのでオススメはできない。しっかり対策したいなら他のライブラリを探すか、AWS Lambda が Node.js v16 系に対応するのを待つしかなさそう・・・。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

AWS CLIの振り返り ~CloudFront入門編~

本記事の目的 JAWS-UG CLI オンラインハンズオンの復習として、ハンズオンで取り上げられたAWSサービスに関する用語と、使用したAWS CLI コマンドを箇条書きでまとめる。 今回はCloudFront入門編を取り上げる。 主なAWSサービス用語 オリジンサーバー オリジナルとして定めたオブジェクトを保存するコンテンツサーバ。リージョンに存在するS3バケット等を設定できる。 エッジサーバ オリジンサーバのオブジェクトをコピーし、様々な場所から配信するキャッシュサーバ。エッジロケーションに存在する。 ディストリビューション オリジンサーバ及びエッジサーバにおけるコンテンツ配信設定の単位。 デフォルトルートオブジェクト ディストリビューションのルートURLにアクセスした際に表示されるオブジェクト。 ETag HTTPにおけるレスポンスヘッダの1つ。ETagを使用する事で、HTTPにおけるキャッシュの有効性を確認できる。 主なAWS CLI コマンド一覧 CloudFrontディストリビューションの作成 aws cloudfront create-distribution \ --origin-domain-name "${CLOUDFRONT_ORIGIN_DOMAIN_NAME}" \ --default-root-object ${CLOUDFRONT_DISTRIBUTION_DEFAULT_ROOT_OBJECT} オプション 引数 必須/任意 備考 --origin-domain-name オリジンドメイン名 任意 --default-root-object デフォルトルートオブジェクト名 任意 CloudFrontディストリビューションの付加 aws cloudfront tag-resource \ --resource ${CLOUDFRONT_TAG_RESOURCE} \ --tags "${STRING_CLOUDFRONT_TAGS}" オプション 引数 必須/任意 備考 --resource タグ対象リソース(ARN) 必須 引数の例:Items=[{Key=<タグのキー名>,Value=<タグの値>}] --tags タグ文字列 必須 CloudFrontディストリビューションの一覧表示 aws cloudfront list-distributions CloudFrontディストリビューションのタグ別一覧表示 aws cloudfront list-tags-for-resource \ --resource ${CLOUDFRONT_TAG_RESOURCE} オプション 引数 必須/任意 備考 --resource タグ対象リソース(ARN) 必須 ※list-distributionsコマンドではタグ表示ができない。そのため、代わりに全てのディストリビューションに対してlist-tags-for-resourceコマンドを使用する事で、タグの有無を確認する。 CloudFrontディストリビューションの詳細表示 aws cloudfront get-distribution \  --id ${CLOUDFRONT_DISTRIBUTION_ID} オプション 引数 必須/任意 備考 --id ディストリビューションID 必須 CloudFrontディストリビューションの詳細設定表示 aws cloudfront get-distribution-config \ --id ${CLOUDFRONT_DISTRIBUTION_ID} オプション 引数 必須/任意 備考 --id ディストリビューションID 必須 CloudFrontディストリビューションの更新 aws cloudfront update-distribution \ --id ${CLOUDFRONT_DISTRIBUTION_ID} オプション 引数 必須/任意 備考 --id ディストリビューションID 必須 CloudFrontディストリビューションの削除 aws cloudfront delete-distribution \ --id ${CLOUDFRONT_DISTRIBUTION_ID} \ --if-match ${CLOUDFRONT_ETAG} オプション 引数 必須/任意 備考 --id ディストリビューションID 必須 --if-match ETag 任意 CloudFrontキャッシュ無効化の作成 aws cloudfront create-invalidation \ --distribution-id ${CLOUDFRONT_DISTRIBUTION_ID} \ --paths ${CLOUDFRONT_PATHS} オプション 引数 必須/任意 備考 --distribution-id ディストリビューションID 必須 --paths キャッシュ無効化対象オブジェクトパス 任意 CloudFrontキャッシュ無効化の一覧表示 aws cloudfront list-invalidations \ --distribution-id ${CLOUDFRONT_DISTRIBUTION_ID} オプション 引数 必須/任意 備考 --distribution-id ディストリビューションID 必須 参考文献 AWSCLIコマンドリファレンス:cloudfront JAWS-UG CLI専門支部:ハンズオン(簡易版): CloudFront入門
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

AWS App Runner で、VPC Connector を使って Amazon RDS に接続してみた

はじめに 2022年2月8日(米国時間)に、AWS App Runner にて Amazon VPC 接続用の機能が追加されました。アップデート前は、VPC 内にホストされている Amazon RDS などのサービスに接続することが出来ませんでした。このアップデートにより、VPC 内にホストされている RDS をはじめとした、各種サービスと連携ができるようになりました! AWS では、VPC 内でホストされているサービスがあるため、ユースケースが広がるアップデートとなります。詳細は次のブログを参照してください。 また、このアップデートの留意点としては、App Runner にアクセスする経路は変わらずインターネットをつかったアクセスが必要です。アクセス元 → App Runner 方向のインバウンドトラフィックは、インターネットを経由した接続が必要で、App Runner → なにか 方向のアウトバウンドトラフィックは、自分たちが管理している VPC の経路をつかった接続となります。詳細は次のブログを参照してください。 今回の記事は、Go 言語で作成した Docker Image を使って、VPC 内に構成している RDS for MySQL と接続する App Runner を作成してみる記事となります。 Go言語で動作確認用プログラムを作成 MySQL と接続するための Go言語のプログラムをローカル環境で作成します。エラーハンドリングなどは省略しているので、本番環境での利用はダメです。ローカルで開発するため、接続先の MySQL の情報は環境変数化しています。 package main import ( "database/sql" "fmt" "net" "net/http" "os" "time" _ "github.com/go-sql-driver/mysql" ) var db *sql.DB func handler(w http.ResponseWriter, r *http.Request) { // MySQL のデータを表示 row := db.QueryRow(`select * from sample`) var id, name string row.Scan(&id, &name) println(name) fmt.Fprintf(w, name+"\n") fmt.Fprintf(w, "\n") // ローカルのIPアドレスを表示 fmt.Fprintf(w, "IPアドレス一覧"+"\n") interfaces, err := net.Interfaces() if err != nil { fmt.Println(err) return } for _, inter := range interfaces { addrs, err := inter.Addrs() if err != nil { fmt.Println(err) return } for _, a := range addrs { if ipnet, ok := a.(*net.IPNet); ok { if ipnet.IP.To4() != nil { fmt.Println(ipnet.IP.String()) fmt.Fprintf(w, ipnet.IP.String()+"\n") } } } } } func main() { // MySQL のコネクションを取得 mysql_hostname := os.Getenv("MYSQL_HOSTNAME") mysql_port := os.Getenv("MYSQL_PORT") mysql_username := os.Getenv("MYSQL_USERNAME") mysql_password := os.Getenv("MYSQL_PASSWORD") var err error db, err = sql.Open("mysql", mysql_username+":"+mysql_password+"@tcp("+mysql_hostname+":"+mysql_port+")/sugi01") if err != nil { println("MySQL のコネクション接続に失敗") panic(err) } defer db.Close() db.SetConnMaxLifetime(time.Minute * 3) db.SetMaxOpenConns(10) db.SetMaxIdleConns(10) http.HandleFunc("/", handler) // ハンドラを登録してウェブページを表示させる http.ListenAndServe(":8080", nil) } ローカル環境では、Docker を使って MySQL を動かしている必要があります。詳細はこちらの記事に記載しております。 ローカルで、MySQL を動かしたうえで、Go 言語のプログラムの動作確認をしていきます。 go run app.go ブラウザからアクセスすると、MySQL から取得した「MySQLのデータ」と、コンテナに付与されている IP アドレス一覧が表示されます。 Go言語のプログラムをBuildします。 go build -o app app ファイルがビルドされました。 > ls -la total 6576 drwxr-xr-x 2 ec2-user docker 76 Feb 14 01:31 . drwxr-xr-x 5 ec2-user docker 74 Feb 14 00:00 .. -rwxr-xr-x 1 ec2-user docker 6714375 Feb 14 01:31 app -rw-r--r-- 1 ec2-user docker 1567 Feb 14 01:28 app.go -rw-r--r-- 1 ec2-user docker 87 Feb 14 01:30 Dockefile -rw-r--r-- 1 ec2-user docker 101 Feb 14 00:55 go.mod -rw-r--r-- 1 ec2-user docker 179 Feb 14 00:10 go.sum ECR Repository 作成 これから Docker Image を作成していくのですが、Docker Image を保管するための ECR Repository を用意していきます。ECR の画面を開いて、Create Repository を押します。 Repository 名を入力します。 Create Repository を選択します。 作成されました。 Docker Image Build 次に、手元の環境で Docker Image を Build していきます。次のように Dockerfile を作成します。 ベースのイメージは、ECR Public にある Golang 1.16 のものを利用 Build した Go 言語のプログラムを、/workdir に格納 8080 ポートを EXPOSE FROM public.ecr.aws/docker/library/golang:1.16 RUN mkdir /workdir COPY app /workdir EXPOSE 8080 CMD ["/workdir/app"] 作成した ECR Repository を指定して、Docker Build を行います。 docker image build -t xxxxxxxxxxxx.dkr.ecr.ap-northeast-1.amazonaws.com/app-runner-testapp:0.0.1 . 作成した Docker Image を使って、動作確認をします。 MySQL はローカルの Docker で稼働している前提 (172.17.0.2 の IP アドレスは、MySQL コンテナの IP アドレス) docker run \ -it \ --env MYSQL_HOSTNAME=172.17.0.2 \ --env MYSQL_PORT=3306 \ --env MYSQL_USERNAME=root \ --env MYSQL_PASSWORD=mypassword \ -e BIND-ADDRESS=0.0.0.0 \ -p 8080:8080 \ xxxxxxxxxxxx.dkr.ecr.ap-northeast-1.amazonaws.com/app-runner-testapp:0.0.1 ブラウザから動作確認をします。正常に稼働しています。 ECR に Push 正常に Docker Image が作成できたので、ECR に Push していきます。まず、Login をします。 aws ecr get-login-password --region ap-northeast-1 | docker login --username AWS --password-stdin xxxxxxxxxxxx.dkr.ecr.ap-northeast-1.amazonaws.com Login 後、ECR に Push を行います。 docker push xxxxxxxxxxxx.dkr.ecr.ap-northeast-1.amazonaws.com/app-runner-testapp:0.0.1 ECR に Push されています。 latest tag も付与して Push をします。 docker image build -t xxxxxxxxxxxx.dkr.ecr.ap-northeast-1.amazonaws.com/app-runner-testapp:latest . docker push xxxxxxxxxxxx.dkr.ecr.ap-northeast-1.amazonaws.com/app-runner-testapp:latest RDS の準備 App Runner から接続するための、RDS for MySQL を作成しました。 これに、テストデータを入れていきましょう。 mysql -u admin -h single-rds01.chuxmuzmrpgx.ap-northeast-1.rds.amazonaws.com -p テストデータを入れます。 CREATE DATABASE sugi01; USE sugi01; CREATE TABLE sample( id INT(11) NOT NULL AUTO_INCREMENT, name VARCHAR(10) NOT NULL, PRIMARY KEY (id) ); INSERT INTO sample(name) VALUES ("RDSのデータ"); テストデータが格納されているか確認です。 mysql> SELECT * FROM sugi01.sample; +----+-----------------+ | id | name | +----+-----------------+ | 3 | RDSのデータ | +----+-----------------+ 1 row in set (0.00 sec) App Runner の作成 それでは、App Runner で Service を作成していき、ECR に Push したコンテナイメージを動かしていきましょう。Create service を選びます。 ECR 上で作成したコンテナイメージを指定します。 Deployment settings は、Automatic にしておきます。これにより、latest イメージが更新されたときに、自動デプロイを行うようにします。 Service の名前や、環境変数などを指定していきます。Go 言語のアプリケーションに渡すための、RDS の接続情報を与えましょう。 MYSQL_HOSTNAME single-rds01.chuxmuzmrpgx.ap-northeast-1.rds.amazonaws.com MYSQL_PORT 3306 MYSQL_USERNAME admin MYSQL_PASSWORD yourpassword Auto Scaling デフォルトのままにします。 Health Check はデフォルトのままにします。 Security もデフォルトのままにします。 Networking では、RDS と接続するために、VPC Connector を作成していきます。 VPC connector の名前や、接続する VPC, Subnet, Security Group などを指定します。 指定された状態です。 Next Create & Deploy を押します。 Service の Deploy が走ります。 一定時間後、Deploy が完了します。 アクセス確認 該当のドメインにアクセスすると、作成したコンテナイメージが正常に稼働していることがわかります。RDS と接続が出来ており、「RDSのデータ」と表示さされています。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

ControlTower⑦SecurityHubの有効化

ControlTower関連リンクまとめ ・ControlTower①マルチアカウント環境をセットアップする ・ControlTower②環境確認 ・ControlTower③SSOの確認・アカウントの追加・削除 ・ControlTower④ガードレールの設定 ・ControlTower⑤Auditアカウントに作成されるリソースについて ・ControlTower⑥LogArchiveアカウントに作成されるリソースについて ・ControlTower⑦SecurityHubの有効化←今ここ ・ControlTower⑧GuardDutyの有効化 ・ControlTower⑨CloudWatchクロスアカウントダッシュボードの設定 ・ControlTower⑩LogArchiveアカウント内バケットへのCloudWatchLogs集約 設定する内容の確認 ControlTower①~⑥までの記事で、ControlTowerにより作成される初期リソースについて確認を行いました。ControlTowerでは各アカウントのAWS Config、CloudTrailは自動で有効化され、Auditアカウントに集約されます。今回はこの環境に各アカウントでSecurityHubを有効化し、Auditアカウントに集約する設定を追加します。 SecurityHubによるセキュリティチェックやコントロールも、Configルールにより実行されます。そのため、SecurityHubの親アカウントをControlTowerのAuditアカウントに指定することで、SecurityHubの通知もAuditアカウントに集約することができます。 ControlTower環境でのSecurityHubの有効化手順 AuditアカウントはSecurityOUに所属しています。各SecurityHubはOrganizationsと統合されたサービスの為、まずは管理(Root)アカウントのOrganizationsでSecurityHubのアクセスを有効化し、SecurityHubの委任を行う必要があります。 Organizationsと統合できるAWSサービスはこちらからご確認ください。 マスターアカウントのOrganizationsでSecurityHubのアクセスを有効化する 管理(Root)アカウントにログインし、Organizationsのサービスページに移動します。 左メニューの「サービス」からサービス一覧を表示し、「Security Hub」を探します。 Security Hubのサービス名のリンクを押下すると、信頼されたアクセスの設定画面に移動できます。 「信頼されたアクセスを有効にする」ボタンを押下します。 「Security Hub コンソールを通じて信頼されたアクセスを有効にすると、そのサービスは必要な追加のセットアップタスクを完了できます。」とありますが、今回は順を追ってSecurityHubの設定を行いたいため、「追加のセットアップタスクを実行せずに Security Hub の信頼されたアクセスを有効にするオプションを表示します。」のチェックボックスにチェックを入れます。 テキストボックスに指定の文字列を入力し、「信頼されたアクセスを有効にする」を押下します。 上部に「Security Hub に対する信頼されたアクセスを正常に有効にしました」と表示が出ることを確認します。次はSecurity Hubのサービスページに移動し、Security Hubの有効化を行いましょう。 マスターアカウントでSecurityHubの有効化・委任設定を行う Security Hubのサービスページに移動します。 右上の「Security Hubに移動」を押下します。 SecurityHubの設定ページが表示されます。 有効化したいセキュリティ基準のチェックボックスにチェックを入れ、画面をスクロールします。 今回はAuditアカウントにSecurityHubを集約します。そのため、「委任された管理者」のテキストボックスに、AuditアカウントのアカウントIDを入力し、「委任」を押下します。 「お客様の代わりに組織内の Security Hub を管理するアカウントを承認しました。この指定は、いつでも取り消しまたは変更することができます。」と表示されます。この表示が出たら、「SecurityHubの有効化」ボタンを押下します。 これで、管理(Root)アカウントでのSecurity Hub設定作業が完了しました。 Security Hubの「設定」ページに移動し、「一般」タブを表示します。 委任された管理者として、先ほど入力したAuditアカウントのアカウントIDが表示されていることが確認できます。これで、管理(Root)アカウント側での作業は完了です。 AuditアカウントのSecurityHub画面確認 マスターアカウントでの作業が完了したら、AuditアカウントにログインしSecurityHubの状況を確認しましょう。マスターアカウントにてSecurityHubの委任を行ったことで、Auditアカウント側のSecurityHubは既に有効化されています。 画面上部に表示されている「このリージョンで組織のSecurity Hubを有効にする」という通知から、組織全体でSecurityHubを有効化することができます。通知の右側に表示されている「設定」ボタンを押下します。 確認画面が表示されます。「有効化」を押下すると、組織全体でSecurityHubが有効化されます。 組織全体に対してSecurityHubを有効化したら、左メニューから「設定」画面に移動します。 「アカウント」タブを表示すると、Organizationsに所属するすべてのアカウントが表示されています。 もしSecurityHubの管理対象から外したいアカウントがある場合は、対象のアカウントのチェックボックスにチェックを入れ、右上の「Actions」から「Diassociate account」を押下します。 確認画面が表示されます。「diassociate account」のボタンを押下すると、アカウントがSecurityHubの管理対象から外れます。 SecurityHubのメンバー出ないアカウントは、「Status」に「Not a member」と表示されます。 メンバーアカウントでのSecurityHub画面確認 LogArchiveアカウントにログインし、SecurityHubのトップページを表示します。 LogArchiveアカウントでも既にSecurityHubの有効化が完了しています。 SecurityHubを集約しているAuditアカウントではメンバーアカウントのセキュリティチェック結果がすべて参照できるのに対して、メンバーアカウント側では自分のアカウント内の情報しか参照できないように設定されます。 左メニューから「設定」画面に移動すると、「Security Hub メンバーとしてログインしています。メンバーアカウントはアカウント設定を管理できません。」と表示されることが確認できます。 SecurityHubの通知について Security Hubによるセキュリティチェックは、Configルールにより実行されます。 ControlTowerを有効にすると、ConfigはすべてAuditアカウントに集約されます。 そのため、現状でも追加設定なしでSecurityHubのセキュリティチェック結果がAuditのSNSトピックから発報されるようになっています。 もちろん、Configの通知とSecurityHubの通知を別々に設定することも可能です。ConfigとSecurityHubの通知を別々にする場合は、Config通知の中からSecurityHub関連ルールの通知を除外する設定を追加することをご検討ください。 また、Configからの通知は追加設定なしだとJson形式の文面で発報されます。 Security Hub関連ルールの通知例 { "version": "0", "id": "4287572c-7b5c-9db6-5bf4-ff4a7325a72f", "detail-type": "Config Rules Compliance Change", "source": "aws.config", "account": "****", "time": "2022-02-14T02:52:03Z", "region": "ap-northeast-1", "resources": [], "detail": { "resourceId": "*****", "awsRegion": "ap-northeast-1", "awsAccountId": "****", "configRuleName": "securityhub-iam-inline-policy-blocked-kms-actions-d24d29c6", "recordVersion": "1.0", "configRuleARN": "arn:aws:config:ap-northeast-1:****:config-rule/aws-service-rule/securityhub.amazonaws.com/config-rule-4clfd2", "messageType": "ComplianceChangeNotification", "newEvaluationResult": { "evaluationResultIdentifier": { "evaluationResultQualifier": { "configRuleName": "securityhub-iam-inline-policy-blocked-kms-actions-d24d29c6", "resourceType": "AWS::IAM::Role", "resourceId": "*****" }, "orderingTimestamp": "2021-09-16T02:12:44.852Z" }, "complianceType": "COMPLIANT", "resultRecordedTime": "2022-02-14T02:52:02.874Z", "configRuleInvokedTime": "2022-02-14T02:52:02.743Z" }, "notificationCreationTime": "2022-02-14T02:52:03.673Z", "resourceType": "AWS::IAM::Role" } } 実際の運用を行う際は、LambdaやEventBridgeで通知の文面を整形してからメール発報を行う構成をご検討ください。 ここまでお読みくださりありがとうございました。 次回はControlTower環境下でのGuardDutyの有効化設定について確認します。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

AWS Amplifyの公開設定を色々とためしてみた

AWS Amplifyの公開設定を色々とためしてみました AWS Amplifyには主に3パターンの公開方法があります。 AWSコンソールから利用するAmplify Consoleで公開 Amplify CLIから利用するAmplify Consoleで公開 Amplify CLIから利用するカスタム公開 詳細として下記について説明します。 Amplify Consoleで公開 Amplify ConsoleでBasic認証公開 Amplify Consoleでルーティング対応 Amplify Consoleで公開(Amplify CLI) カスタム公開(Amplify CLI) 公開削除(Amplify CLI) Amplify Consoleで公開 Amplify Consoleで公開する方法です。 AWSコンソール → AWS Amplifyをクリック。 Amplify Hostingの「使用を開始する」をクリック。 今回はシンプルにするため「Gitプロバイダーなしでデプロイ」をクリック。 アプリケーション名と環境名を任意で設定。公開したいファイル一式をドラッグ&ドロップ → 「保存してデプロイ」をクリック。今回はサンプルとして、Vue.jsで構築したアプリケーションを手動でビルドしたものを利用。 アップロードするファイルは下記コマンドでZip化。Mac標準のGUIによる圧縮だとデプロイしても表示できません。 zip -r xxxxx.zip * アップロードが終わるとURLが発行されるのでアクセスします。 アップロードしたWebSiteが表示されます。 コンソール上には表示されませんが、内部的にはAmazon S3とAmazon CloudFrontを利用してデプロイをしているようです。 Amplify ConsoleでBasic認証公開 Amplify ConsoleでBasic認証公開する方法です。 事前準備として、Amplify ConsoleでWebSite表示。 アクセスコントロール → 「アクセスの管理」をクリック。 アクセス設定を制限に設定。ユーザーとパスワードを設定 → 「Save」をクリック。 設定を確認。 URLにアクセスするとユーザーとパスワードの入力画面が表示されます。 設定したユーザーとパスワードを入力するとWebSiteが表示されます。 Amplify Consoleでルーティング対応 Amplify Consoleでルーティング対応する方法です。 事前準備として、Amplify ConsoleでWebSite表示。 書き換えて、リダイレクト → 「編集」をクリック。 送信元アドレス・ターゲットアドレス・入力を設定 → 「編集」をクリック。 設定値は「AWS Amplify User Guide」を参考に入力。 Original address </^[^.]+$|\.(?!(css|gif|ico|jpg|js|png|txt|svg|woff|woff2|ttf|map|json)$)([^.]+$)/> Destination Address /index.html Redirect Type 200 設定を確認。 これでルーティングのページも表示されます。 Amplify Consoleで公開(Amplify CLI) Amplify CLIによるAmplify Consoleで公開する方法です。このホスティング環境は、「Amplify Consoleで公開」と同じ環境になります。 事前準備として、AWS Amplifyの環境構築。 AWS Amplify #002 - 環境構築 [Vue.jsバージョン] 実行環境 node v16.10.0 npm v7.24.0 ホスティング環境を設定します。実行時に「Hosting with Amplify Console」を選択します。 amplify add hosting 設定確認をします。 amplify status アプリケーションを自動でビルドしクラウドにデプロイします。 amplify publish デプロイが終わるとAWSコンソールでURLが発行されるのでアクセスします。 デプロイしたWebSiteが表示されます。 カスタム公開(Amplify CLI) Amplify CLIによるカスタム公開する方法です。 事前準備として、AWS Amplifyの環境構築。 AWS Amplify #002 - 環境構築 [Vue.jsバージョン] 実行環境 node v16.10.0 npm v7.24.0 ホスティング環境を設定します。実行時に「Amazon CloudFront and S3」を選択します。 amplify add hosting 設定確認をします。 amplify status アプリケーションを自動でビルドしクラウドにデプロイします。 amplify publish AWS Amplify Consoleにはデプロイされていないのを確認します。 Amazon S3に自動でデプロイされているのを確認します。 Amazon CloudFrontに自動でデプロイされているのを確認します。作成されたURLにアクセスします。 デプロイしたURLにアクセスしても、リージョンによってはすぐには表示できません。「Amplify Docs - Hosting」によると24時間後までには表示されるらしいです。すぐに表示したいかたは下記設定で表示可能です。 オリジン → 対象のオリジン選択 → 「編集」をクリック。 同一のオリジンドメインを再選択(ドメインにリージョンが追加される) → 「変更を保存」をクリック。 デプロイしたWebSiteが表示されます。 カスタム公開で、IP制限やBasic認証を設定したい場合は下記記事を参考に追加で設定。または、プロジェクト内のAWS CloudFormationの設定ファイルを編集。 公開設定削除(Amplify CLI) Amplify CLIによる公開設定を削除する方法です。カスタム公開の場合は、Amazon CloudFrontは自動で削除されますが、Amazon S3のバケットは削除されないようなので別途削除する必要があります。 ホスティング環境の削除を設定します。 amplify remove hosting 設定確認をします。 amplify status ホスティング環境の削除をします。 amplify push AWSコンソールでホスティング環境が自動で削除されているのを確認。 AWS Amplifyを利用することで、Amplify Consoleでの公開やカスタム公開やBasic認証が可能です 次回は、AWS Amplifyの独自ドメインホスティング環境の構築方法も紹介できたらと思います。 AWS Amplifyについて、他にも記事を書いています。よろしければぜひ tags - AWS Amplify やってみたシリーズ tags - Try
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【個人的メモ】 EC2からSageMakerを扱う

EC2(Linux) controls SageMaker instances AWSのEC2インスタンスからSageMakerを操作して無駄遣い防止などをするためのメモ シェルスクリプト作るときの参考用 前提 AWS Cli(v2) がLinux上にインストールされていること aws configureでアクセスキーなどが設定済みであること 基本 $ aws sagemaker <サブコマンド> <パラメータ> サブコマンド一覧を表示(ヘルプ) $ aws sagemaker help インスタンスの状態を確認する(json) $ aws sagemaker list-notebook-instances 下記形式のjsonを得られる { "NotebookInstances": [ { "NotebookInstanceName": "<インスタンス名>", "NotebookInstanceArn": "arn:aws:sagemaker:<リージョン>:<XXXXXXXXXX>:notebook-instance/<インスタンス名?>", "NotebookInstanceStatus": "<状態(Pending等)>", "Url": "<インスタンス名>-<ランダム値?>.<リージョン>.sagemaker.aws", "InstanceType": "<インスタンスのタイプ(ml.t2.medium等)>", "CreationTime": "20XX-XX-XXT00:00:00.000000+09:00", "LastModifiedTime": "20XX-XX-XXT00:00:00.000000+09:00", "NotebookInstanceLifecycleConfigName": "<ライフサイクル設定名>" } ] } インスタンス起動 $ aws sagemaker start-notebook-instance --notebook-instance-name <インスタンス名> 終了コード:<0:正常><0以外:失敗> インスタンス停止 $ aws sagemaker stop-notebook-instance --notebook-instance-name <インスタンス名> 終了コード:<0:正常><0以外:失敗> 参考 sagemaker — AWS CLI 2.4.18 Command Reference
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む