💭
AWS学びなおし(+TF)_SNS
AWS SNS (Simple Notification Service) は、シンプルで柔軟なフルマネージド型のPub/Sub(パブリッシュ/サブスクライブ)メッセージングサービスです。アプリケーション、マイクロサービス、およびデバイス間でメッセージを非同期に送受信することを可能にします。
SNSの主な役割と仕組み:
- メッセージブローカー: SNSはメッセージブローカーとして機能し、メッセージの発行者(パブリッシャー)と受信者(サブスクライバー)の間を取り持ちます。
- トピック: メッセージは「トピック」と呼ばれる論理的なアクセスポイントに発行されます。トピックはメッセージのカテゴリや種類を表します。
- サブスクリプション: メッセージを受信したいアプリケーションやエンドポイントは、特定のトピックに対して「サブスクリプション」を作成します。
- パブリッシュ: パブリッシャーは、メッセージを特定のトピックに送信(パブリッシュ)します。
- 配信: SNSは、トピックにサブスクライブしているすべてのサブスクライバーに対してメッセージをプッシュ型で配信します。
SNSの主な特徴:
- Pub/Subモデル: 1つのメッセージを複数の受信者に同時に配信できます。これにより、疎結合なシステム構築が容易になります。
- プッシュ型配信: メッセージが発行されると、SNSがサブスクライバーに自動的にメッセージを送信します。ポーリング処理が不要になり、リアルタイム性が向上します。
-
多様なサブスクリプションプロトコル: 以下のプロトコルをサポートしており、様々なシステムとの連携が可能です。
- HTTP/HTTPS: Webアプリケーションのエンドポイント
- Email/Email-JSON: Eメールアドレス
- SQS (Simple Queue Service): キューイングサービス
- Lambda: サーバーレス関数
- Application: モバイルプッシュ通知 (APNS, FCM)
- SMS: テキストメッセージ
- 高スループットと低レイテンシー: 大量のメッセージを高速かつ低遅延で処理できます。
- 高い信頼性と可用性: AWSのインフラ上で動作するため、可用性と耐久性が高く、メッセージの損失リスクを低減できます。
- フルマネージドサービス: サーバーの管理やスケーリングをAWSに任せることができ、運用負荷を軽減できます。
- メッセージフィルタリング: サブスクライバーは、メッセージ属性に基づいてメッセージをフィルタリングできます。不要なメッセージを受信しないようにすることで、効率的な処理を実現できます。
- メッセージ永続化 (SQS連携): SQSと連携することで、メッセージの永続化が可能になります。配信に失敗した場合でも、メッセージをSQSキューに保存し、再処理できます。
- メッセージ暗号化: 保管時および転送中のメッセージを暗号化することで、セキュリティを強化できます。
- アクセス制御: IAM (Identity and Access Management) を使用して、トピックへのアクセス権限を詳細に制御できます。
SNSの主なユースケース:
- イベント通知: EC2インスタンスの状態変更、S3バケットへのファイルアップロードなど、AWSリソースのイベント通知
- アラート通知: CloudWatchアラームの発報、システムエラーの通知
- アプリケーション間連携: マイクロサービス間の非同期通信、ワークフローのトリガー
- モバイルプッシュ通知: モバイルアプリケーションへのプッシュ通知
- マーケティングメッセージ: EメールやSMSによるマーケティングメッセージ配信
- IoTデータの収集と配信: IoTデバイスからのデータを収集し、複数のバックエンドシステムに配信
SNSのメリット:
- 疎結合なシステム構築: パブリッシャーとサブスクライバーが直接的に依存しないため、柔軟で拡張性の高いシステムを構築できます。
- リアルタイム処理: プッシュ型配信により、イベント発生時に即座に処理を開始できます。
- 高いスケーラビリティと信頼性: 大規模なシステムや高負荷な環境にも対応できます。
- 運用コストの削減: フルマネージドサービスのため、運用負荷を大幅に削減できます。
- 多様なシステムとの連携: 様々なプロトコルをサポートしており、既存システムとの連携が容易です。
SNSのデメリット:
- メッセージの順序保証 (標準トピック): 標準トピックでは、メッセージの順序が保証されません。順序保証が必要な場合は、FIFOトピックを使用する必要があります。
- メッセージの重複配信 (標準トピック): 標準トピックでは、まれにメッセージが重複して配信される可能性があります。べき等な処理を実装する必要があります。
- 設定の複雑さ: 高度な機能 (メッセージフィルタリング、配信ポリシー、暗号化など) を利用する場合、設定が複雑になる場合があります。
- コスト: メッセージの送信量やサブスクリプション数に応じてコストが発生します。
【実務レベルの内容と重要事項】
実務におけるSNSの重要事項:
-
セキュリティ:
- IAMポリシー: トピックへのアクセス制御をIAMポリシーで適切に設定することが重要です。パブリッシャーとサブスクライバーに必要な最小限の権限のみを付与します。
- 暗号化: 機密性の高いメッセージを扱う場合は、保管時暗号化 (SSE-KMS) と転送中の暗号化 (HTTPS) を有効にすることを推奨します。
- アクセスキーの管理: パブリッシャーのアクセスキーは安全に管理し、漏洩しないように注意が必要です。IAMロールの使用を推奨します。
-
信頼性:
- 配信ポリシー: 配信ポリシーを適切に設定することで、配信の信頼性を高めることができます。リトライ回数、バックオフ時間、デッドレターキュー (DLQ) などを設定します。
- DLQ (デッドレターキュー): 配信に失敗したメッセージをDLQに保存することで、メッセージの損失を防ぎ、後から再処理できます。SQSをDLQとして設定することが一般的です。
- メッセージの冪等性: メッセージの重複配信に備えて、サブスクライバー側でメッセージ処理の冪等性を確保することが重要です。
- FIFOトピック: メッセージの順序保証が重要な場合は、FIFOトピックを使用します。ただし、標準トピックと比較してスループットが低くなる点に注意が必要です。
-
スケーラビリティ:
- 自動スケーリング: SNSは自動的にスケールするため、特に考慮する必要はありません。ただし、サブスクライバー側の処理能力がボトルネックにならないように注意が必要です。
- メッセージバッチ処理: サブスクライバー側でメッセージをバッチ処理することで、効率的な処理が可能です。特にLambda関数をサブスクライバーとする場合に有効です。
-
モニタリング:
- CloudWatchメトリクス: SNSのメトリクス (PublishSuccess、DeliverySuccessRateなど) をCloudWatchで監視し、異常を早期に検知できるようにします。
- CloudWatch Logs: 必要に応じて、SNSのログをCloudWatch Logsに出力し、詳細な分析やトラブルシューティングに役立てます。
- アラート設定: CloudWatchアラームを設定し、異常が発生した場合に通知を受け取れるようにします。
-
コスト最適化:
- メッセージサイズ: メッセージサイズを小さくすることで、コストを削減できます。
- 配信プロトコル: 配信プロトコルによってコストが異なる場合があります。最適なプロトコルを選択します。
- リージョンの選択: SNSのリージョンとサブスクライバーのリージョンを同一にすることで、データ転送料金を削減できる場合があります。
- 不要なトピックとサブスクリプションの削除: 使用しなくなったトピックやサブスクリプションは定期的に削除し、無駄なコストを削減します。
実務で考慮すべき事項:
- メッセージ設計: メッセージの内容、形式、サイズなどを適切に設計することが重要です。
- エラーハンドリング: 配信エラー、処理エラーが発生した場合の処理方法を事前に検討しておく必要があります。
- バージョン管理: メッセージスキーマやトピックの設定変更など、変更管理を適切に行う必要があります。
- ドキュメント化: SNSの構成、設定、利用方法などをドキュメント化し、チーム内で共有することが重要です。
【実務でどの程度使用されるのか】
SNSは実務で非常に広く使用されているサービスです。AWS環境におけるイベント通知やアプリケーション連携の基盤として、多くのシステムで活用されています。
実務での使用頻度が高い理由:
- 汎用性の高さ: 様々なユースケースに対応できる汎用性の高いサービスです。
- 容易な導入と利用: 設定が比較的容易で、すぐに利用を開始できます。
- AWSサービスとの親和性: 他のAWSサービス (EC2, S3, Lambda, SQS, CloudWatchなど) との連携が容易です。
- 高い信頼性とスケーラビリティ: 実運用に耐えうる高い信頼性とスケーラビリティを備えています。
- フルマネージド: 運用負荷が低く、開発者はアプリケーションロジックに集中できます。
具体的な使用例:
- ECサイト: 注文受付、在庫変動、配送状況などのイベント通知、顧客へのメール/SMS通知
- SaaSアプリケーション: ユーザー登録、課金処理、システムアラートなどの通知、アプリケーション内メッセージング
- IoTシステム: デバイスからのデータ収集、異常検知アラート、デバイス制御コマンドの送信
- マイクロサービスアーキテクチャ: サービス間の非同期通信、イベント駆動型アーキテクチャの実現
- データ分析基盤: データパイプラインのトリガー、データ処理ジョブの通知
SNSの利用規模:
- 小規模なWebアプリケーションから、大規模なエンタープライズシステムまで、幅広い規模のシステムで利用されています。
- 月間数百万、数千万件以上のメッセージを処理するシステムも珍しくありません。
**結論として、SNSは現代のクラウドネイティブなシステム構築において、不可欠なサービスと言えます。**設計・開発段階からSNSの利用を検討することで、より柔軟でスケーラブル、かつ信頼性の高いシステムを構築することが可能になります。
【terraformのコードで記述する場合の基本的内容と実務レベルの内容】
Terraformコード (基本):
resource "aws_sns_topic" "example" {
name = "my-topic"
}
解説:
-
resource "aws_sns_topic" "example"
:aws_sns_topic
リソースを使用してSNSトピックを作成することを宣言しています。"example"
はリソースのローカル名です。 -
name = "my-topic"
: 作成するSNSトピックの名前を指定します。AWSアカウント内で一意である必要があります。
Terraformコード (実務レベル):
resource "aws_sns_topic" "example" {
name = "my-app-events"
delivery_policy = jsonencode({
http = {
defaultHealthyRetryPolicy = {
minDelayTarget = 5
maxDelayTarget = 20
numRetries = 3
numMaxDelayRetries = 50
backoffFunction = "exponential"
}
disableSubscriptionOverrides = false
healthyRetryPolicy = {
minDelayTarget = 10
maxDelayTarget = 60
numRetries = 10
numMaxDelayRetries = 100
backoffFunction = "linear"
}
throttlePolicy = {
maxReceivesPerSecond = 100
}
}
})
display_name = "MyApp Events Topic"
kms_master_key_id = "alias/aws/sns" # KMS key ID or alias for encryption
policy = data.aws_iam_policy_document.sns_topic_policy.json # IAM policy document
tags = {
Environment = "Production"
Application = "MyApp"
}
}
data "aws_iam_policy_document" "sns_topic_policy" {
statement {
sid = "AllowPublishToTopic"
principals {
type = "AWS"
identifiers = ["arn:aws:iam::123456789012:role/my-publisher-role"] # パブリッシャーのIAMロールARN
}
actions = [
"SNS:Publish"
]
resources = [
"arn:aws:sns:ap-northeast-1:123456789012:my-app-events" # 作成するSNSトピックのARN (リージョンとアカウントIDは適宜変更)
]
}
}
実務レベルのコード解説:
-
delivery_policy
: 配信ポリシーを設定します。リトライポリシー、バックオフ関数、スロットリングポリシーなどを細かく制御できます。上記例では、HTTPサブスクリプションに対する配信ポリシーを設定しています。-
defaultHealthyRetryPolicy
: デフォルトのリトライポリシー -
healthyRetryPolicy
: 成功とみなされる配信試行に対するリトライポリシー -
throttlePolicy
: スロットリングポリシー
-
-
display_name
: SNSコンソールに表示されるトピックの表示名を設定します。 -
kms_master_key_id
: 保管時暗号化 (SSE-KMS) を有効にするためのKMSキーIDまたはエイリアスを指定します。alias/aws/sns
はAWS管理のSNS暗号化キーを使用する場合の例です。独自のKMSキーを使用することも可能です。 -
policy
: IAMポリシーを設定します。トピックへのアクセス権限を詳細に制御できます。-
data "aws_iam_policy_document" "sns_topic_policy"
: IAMポリシーをJSON形式で記述するためにaws_iam_policy_document
データソースを使用しています。 -
statement
: ポリシーのステートメントを定義します。 -
principals
: アクションを許可するプリンシパル (IAMユーザー、IAMロール、AWSアカウントなど) を指定します。上記例では、特定のIAMロール (arn:aws:iam::123456789012:role/my-publisher-role
) にPublishアクションを許可しています。 -
actions
: 許可するアクションを指定します。SNS:Publish
はSNSトピックへのメッセージ発行を許可するアクションです。 -
resources
: アクションを適用するリソース (SNSトピック) のARNを指定します。
-
-
tags
: リソースにタグを付与します。リソース管理、コスト分析、検索などに役立ちます。
Terraformコード (サブスクリプション設定):
resource "aws_sns_topic_subscription" "http_subscription" {
topic_arn = aws_sns_topic.example.arn
protocol = "https"
endpoint = "https://example.com/webhook" # サブスクライバーのエンドポイントURL
filter_policy = jsonencode({
"event_type" = ["order_created", "payment_success"] # メッセージフィルタリングの例
})
delivery_policy = jsonencode({ # サブスクリプションごとの配信ポリシー設定も可能
http = {
defaultHealthyRetryPolicy = {
minDelayTarget = 10
maxDelayTarget = 60
numRetries = 5
}
}
})
raw_message_delivery = true # 生メッセージ配信を有効にする (HTTP/HTTPSの場合)
attributes = { # 属性設定 (例: サブスクリプションの名前)
SubscriptionType = "webhook"
}
}
サブスクリプション設定コード解説:
-
resource "aws_sns_topic_subscription" "http_subscription"
:aws_sns_topic_subscription
リソースを使用してSNSトピックへのサブスクリプションを作成することを宣言しています。 -
topic_arn
: サブスクライブするSNSトピックのARNを指定します。aws_sns_topic.example.arn
は、先ほど作成したaws_sns_topic
リソースのARNを参照しています。 -
protocol
: サブスクリプションプロトコルを指定します。上記例ではhttps
を指定しています。 -
endpoint
: サブスクライバーのエンドポイントURLを指定します。HTTP/HTTPSプロトコルの場合に必須です。 -
filter_policy
: メッセージフィルタリングポリシーを設定します。サブスクライバーは、指定した属性に一致するメッセージのみを受信できます。上記例では、event_type
属性がorder_created
またはpayment_success
であるメッセージのみを受信するように設定しています。 -
delivery_policy
: サブスクリプションごとの配信ポリシーを設定できます。トピック全体の配信ポリシーをオーバーライドする場合などに使用します。 -
raw_message_delivery
: HTTP/HTTPSプロトコルの場合、生メッセージ配信を有効にするかどうかを指定します。true
に設定すると、SNSメッセージのメタデータ (タイプ、メッセージIDなど) が含まれない、生のメッセージボディのみがエンドポイントに送信されます。 -
attributes
: サブスクリプションの属性を設定できます。SubscriptionType
はユーザー定義の属性の例です。
実務におけるTerraformコードのポイント:
- モジュール化: SNSトピックとサブスクリプションの設定をTerraformモジュールとして作成し、再利用性を高めることを推奨します。
- 変数 (Variables) の活用: トピック名、エンドポイントURL、KMSキーIDなどの設定値をTerraform変数として定義し、柔軟性を高めます。
-
状態管理: Terraformの状態ファイル (
terraform.tfstate
) を適切に管理し、複数人での共同作業や変更履歴の追跡を容易にします。 - IaC (Infrastructure as Code) のベストプラクティス: Terraformのコードは、バージョン管理システム (Gitなど) で管理し、変更レビュープロセスを導入するなど、IaCのベストプラクティスに従って管理します。
上記はあくまで基本的な例です。実務では、要件に応じてさらに詳細な設定や、他のAWSリソース (SQS, Lambdaなど) との連携が必要になる場合があります。Terraformの公式ドキュメントやAWSのドキュメントを参考に、最適な構成を検討してください。
Discussion