public_traffic_container_service pattern¶
概要¶
public_traffic_container_service pattern
モジュールでは、インターネットからのトラフィックを受ける想定のロードバランサーおよびコンテナサービス環境を構築します。また、サービスを公開するにあたってのSSL/TLS証明書やDNSレコードの設定も行います。
このpatternにより構築されるコンテナサービスでは、バックエンドのサーバーアプリケーションがコンテナとして動作します。このアプリケーションは、ロードバランサーを介してインターネットに公開され、利用者に対してサービスや機能を提供します。
想定する適用対象環境¶
public_traffic_container_service pattern
は、Runtime環境での使用を想定しています。
依存するpattern¶
public_traffic_container_service pattern
は、事前に以下のpatternが適用されていることを前提としています。
pattern名 | 利用する情報 |
---|---|
network pattern | パブリックサブネット、プライベートサブネット |
またコンテナサービスで使用するコンテナイメージおよび動作するコンテナが、次のようなリソース、情報を必要とする場合は依存するpatternが追加されます。
- Amazon ECRに格納されたDockerイメージを使用する
- コンテナ内からデータストアを使用する
- 環境変数(秘匿情報)を参照する
pattern名 | 利用する情報 |
---|---|
ci_pipeline pattern | Delivery環境に構築されたAmazon ECR上のDockerイメージ |
parameter_store pattern | AWS Systems Manager パラメータストアに格納された秘匿情報 |
database pattern | RDBMS |
redis pattern | Redis |
本patternが依存するリソースを他の構築手段で代替する場合は、依存するpatternと入出力リファレンスの内容を参考に、本patternが必要とするリソースを構築してください。
構築されるリソース¶
このpatternでは、以下のリソースが構築されます。
リソース名 | 説明 |
---|---|
Elastic Load Balancing(Application Load Balancer) | インターネットからのトラフィックを受けるロードバランサーを構築します |
AWS Fargate | アプリケーションコンテナを動作させるサービスを構築します |
AWS Certificate Manager | SSL/TLS証明書を作成します |
Amazon Route 53 | DNSレコードを作成します |
Amazon S3 | ALBのアクセスログ格納先 |
Amazon CloudWatch Logs | コンテナログの格納先 |
public_traffic_container_service pattern
では、ドメインの取得は行いません。事前にドメインの取得が必要です。
モジュールの理解に向けて¶
一般にサーバーアプリケーションをインターネットに公開する際には、以下のような環境を構築する必要があります。
- 負荷分散や可用性を考慮した、ロードバランサーや複数インスタンスで動作するサーバー環境
- インターネット公開に必要な、DNSレコードやSSL/TLS証明書の設定
public_traffic_container_service pattern
では、これらを実現するリソースを構築します。
Eponaでは、アプリケーションがコンテナ化されていることを前提としています。
public_traffic_container_service pattern
を適用することにより、以下の環境が得られます。
- コンテナの稼働数を柔軟に増減(スケールイン・アウト)できる、AWS Fargateクラスター
- コンテナを稼働させるインスタンスは、利用者は管理不要(AWS管理となる)
- インターネットからのトラフィックを受け付け、AWS Fargateクラスターへ転送するApplication Load Balancer
Application Load Balancerは、AWS CodeDeployと連携することを想定しています。
具体的には、Blue/Greenデプロイが行われることを想定し、ターゲットグループが2つ作成されます。
詳しくは、cd_pipeline_backend pattern
も参照してください。
また、今日のインターネットに公開されるWebサービス、Webサイトには固有のドメイン名でアクセスできることは当然として、HTTPSでのアクセスが求められるようになっている状況です。
このため、インターネット公開を前提として以下の環境を構成します。
- Amazon Route 53を使用した、サービス公開用のDNSレコードの取得
- サービス公開用のドメイン名に合わせた、AWS Certificate ManagerによるSSL/TLS証明書の取得
ここで作成するDNSレコードおよびSSL/TLS証明書は、同時に作成されるApplication Load Balancerへ紐付けられます。
ドメイン取得について¶
public_traffic_container_service pattern
では、ドメインの登録自体は範囲外となっています。
事前に、AWSのマネジメントコンソールで必要なドメインを取得してください。
ドメイン取得がpublic_traffic_container_service pattern
の範囲外になっているのは、Terraformが対応していないことがひとつの理由です。加えて、ドメイン取得に関してはメール確認といった人手による作業が必要になるため、完全な自動化はできません。このため、Eponaの範囲外でドメインを取得する前提としています。
public_traffic_container_service pattern
は、事前のドメイン取得およびドメイン取得に伴うホストゾーンの作成が完了した後に適用されることを想定しています。
ホストゾーンの作成は、Amazon Route 53でドメインを取得した際に、自動的に作成されます。
public_traffic_container_service pattern
では、作成済みのホストゾーンに対して、DNSレコードを作成します。
ログの保存について¶
AWS Fargateのようなコンテナを管理するプラットフォーム上で動作するアプリケーションは、ログを標準出力として書き出すことで記録します。
ただ、AWS Fargateはコンテナインスタンスを実行している仮想マシンへは直接アクセスできないため、デフォルトではコンテナのログを確認できません。
このため、実際の利用にはログをクラスター外に保存することが必須となるでしょう。
public_traffic_container_service pattern
では、ログはAmazon CloudWatch Logsへの保存を想定しています。
ロググループはcontainer_log_group_names
に、ロググループ名を指定して作成します。タスク内のコンテナ数分、ロググループを作成しましょう。
container_log_group_names = ["ロググループ名1", "ロググループ名2", "ロググループ名3", ...]
ここで指定したロググループ名は、タスクのlogConfiguration
に設定してコンテナのログを保存していきます。
Amazon CloudWatch Logsへのログ出力は、AWS FireLensを利用して行うことをおすすめします。詳しくは、以下のドキュメントを参照してください。
Amazon ECS上のコンテナログを、AWS FireLensを使ってAmazon CloudWatch Logsに送信する
さらにDatadogが利用可能な場合は、ログを集約できます。詳しくはこちらを参照してください。
タスク定義で使用するコンテナについて¶
本patternで設定するタスク定義のコンテナには、実際のアプリケーションのものではなく、ダミーのものを設定するようにしてください。
本patternで構築されるFargate環境の更新は、AWS CodeDeployから行う前提となっています。 つまり、本patternに実際のアプリケーションのタスク定義を書いた場合、AWS CodeDeploy用のタスク定義と二重管理になってしまいます。 また、本patternは環境を構築するための最初の1回のみしか適用しないため、タスク定義の管理にコストをかけることは好ましくありません。
したがって、本patternでデプロイする初回のコンテナは、ダミーのコンテナを使用することを推奨します。
具体的なダミーのコンテナとしては、HashiCorp社が提供しているhttp-echoなどがあります。
次節のサンプルコードでは、http-echo
をコンテナイメージに設定した例を記載しています。
なお、本pattern適用時にFargateへデプロイされるコンテナイメージこそダミーですが、コンテナ定義以外のリソースはすべて本来利用すべきものを構築します。 したがって、DNSレコードやクラスター名、ロググループの定義等は実際の利用で必要なものを作成してコンテナのみを差し替えます。
たとえば、ロググループを例にして説明します。
cd_pipeline_backend pattern
によりデプロイするコンテナが以下の3つだとします。
- アプリケーションコンテナ
- Fluent Bitコンテナ
- Datadog Agentコンテナ
この場合、public_traffic_container_service pattern
適用時にデプロイするコンテナと作成するロググループは、次のようになります。
- デプロイするコンテナ
http-echo
のみ
- 作成するロググループ
- アプリケーションコンテナ用ロググループ
- Fluent Bitコンテナ用ロググループ
- Datadog Agentコンテナ用ロググループ
ロードバランサーのバックエンドのアクセス制御について¶
本パターンではALBのリスナーにルールを追加することで、特定のトラフィックのみバックエンドのコンテナサービスへ転送する等の柔軟なルーティングを実現できます。
ルーティングに関する設定をしない場合は、ALBはすべてのトラフィックをバックエンドのコンテナサービスへと転送します。
詳しくは
ALBのリスナールール
を参照してください。
public_traffic_container_service pattern
では以下のアクションタイプをサポートしています。
- 転送(forward)
- 固定レスポンス(fixed-response)
- リダイレクト(redirect)
リスナールール毎に、リクエストURLのパスパターンに基づいた条件を設定することでアクションを実行するかどうかを制御します。 ルールを複数設定した場合は、ルール毎に優先度を付けることでルールを評価する順番を制御できます。
転送(forward)アクション¶
トラフィックをバックエンドのコンテナサービスへ転送します。
詳しくは
転送アクション
を参照してください。
転送先のターゲットグループは、デフォルトアクションの転送先をもとにEponaが自動的に設定します。
このため、本パターンでは、ALBリスナーのデフォルトアクションはECSへの転送アクションで固定としており、使用できません。
固定レスポンス(fixed-response)アクション¶
HTTPステータスコードとオプションのメッセージを含む固定のHTTPレスポンスを返却します。 ALBがサポートしているレスポンスコードとコンテントタイプは以下になります。
- HTTPステータスコード
- 2XX
- 4XX
- 5XX
- コンテントタイプ
text/plain
text/css
text/html
application/javascript
application/json
詳しくは 固定レスポンスアクション を参照してください。
リダイレクト(redirect)アクション¶
インターネットからのトラフィックを別のURLにリダイレクトします。
HTTPステータスコードとして一時的 (HTTP 302) または恒久的 (HTTP 301)が設定できます。
リダイレクト先として以下の項目が設定できます。設定をしなかった項目は元の値が保持されます。
- host
- port
- path
- protocol
- query
詳しくは リダイレクトアクション を参照してください。
転送アクションのデフォルト設定について¶
転送アクションに関する設定をしない場合、すべてのトラフィックをバックエンドに転送するリスナールールをEponaが内部的に作成します。
このリスナールールは最優先で適用されます。
そのため、転送アクションを設定しない状態で、「/*」に対する固定レスポンスやリダイレクトアクションだけを設定した場合、
転送アクションが優先されてしまい、意図した挙動にならない場合があります。
固定レスポンスやリダイレクトのアクションだけ設定する場合でも、適切な優先度を設定した転送アクションをあわせて追加するようにしてください。
サンプルコード¶
public_traffic_container_service pattern
を使用したサンプルコードを、以下に記載します。
module "public_traffic_container_service" {
source = "git::https://gitlab.com/eponas/epona.git//modules/aws/patterns/public_traffic_container_service?ref=v0.2.6"
name = "[リソースに共通的に付与する名前]"
vpc_id = data.terraform_remote_state.production_network.outputs.network.vpc_id
public_subnets = data.terraform_remote_state.production_network.outputs.network.public_subnets
public_traffic_protocol = "HTTPS"
public_traffic_port = 443
public_traffic_inbound_cidr_blocks = ["0.0.0.0/0"]
# リダイレクトのルールの追加例
# `/redirect/*` のパスにアクセスしたときに`host-to-redirect`にリダイレクトします
# ホスト以外のURLは元のURLを引き継ぎます
alb_redirect_listener_rules = [
{
priority = "10"
host = "host-to-redirect"
status_code = "HTTP_301"
path_pattern = "/redirect/*"
}
]
# アクセス制御の例
# `/api/*`のパスだけバックエンドのECSに転送し、それ以外のパスへのアクセスは403エラーを返却します
alb_forward_listener_rules = [
{
priority = "90"
path_pattern = "/api/*"
}
]
alb_fixed_response_listener_rules = [
{
priority = "100"
content_type = "text/plain"
message_body = "403 Forbidden"
status_code = "403"
path_pattern = "/*"
}
]
dns = {
zone_name = "example.com"
record_name = "chat-example-backend.example.com"
}
container_subnets = data.terraform_remote_state.production_network.outputs.network.private_subnets
container_protocol = "HTTP"
container_port = 8080
container_health_check_path = "/"
container_cluster_name = "chat-example"
container_traffic_inbound_cidr_blocks = ["AWS Fargateを配置するVPCのCIDRブロック"]
container_service_desired_count = 3
container_service_platform_version = "1.4.0"
container_task_cpu = 512
container_task_memory = "1024"
default_ecs_task_iam_role_name = "ChatExampleContainerServiceTaskRole"
default_ecs_task_iam_policy_name = "ChatExampleContainerServiceTaskRolePolicy"
default_ecs_task_execution_iam_policy_name = "ChatExampleContainerServiceTaskExecution"
default_ecs_task_execution_iam_role_name = "ChatExampleContainerServiceTaskExecutionRole"
container_log_group_names = ["fargate-log-group/chat-example"]
container_definitions = <<-JSON
[
{
"name": "[タスク名]",
"image": "hashicorp/http-echo:0.2.3",
"essential": true,
"portMappings": [
{
"protocol": "tcp",
"containerPort": 8080
}
],
"logConfiguration": {
# ログ設定
},
"command": [
"-listen",
":8080",
"-text",
"echo"
]
}
]
JSON
tags = {
# 任意のタグ
Environment = "runtime"
RuntimeEnvironment = "production"
ManagedBy = "epona"
}
}
関連するpattern¶
public_traffic_container_service pattern
に関連するpatternを、以下に記載します。
pattern名 | 説明 |
---|---|
ci_pipeline pattern |
アプリケーションをコンテナイメージとしてビルドし、Amazon ECRへPushできるようになります |
cd_pipeline_backend_trigger pattern |
Amazon ECRへのコンテナイメージPushをトリガーに、デプロイメントパイプラインを起動できるようになります |
cd_pipeline_backend pattern |
デプロイメントパイプラインを構築して、AWS FaragateクラスターへのBlue/Greenデプロイが可能になります |
ログの集約¶
public_traffic_container_service pattern
では、ALBのログをAmazon S3に出力します。
また、コンテナのログはAmazon CloudWatch Logsに出力します。
Amazon CloudWatch Logsへのログ出力は、AWS FireLensを利用して行うことをおすすめします。
Amazon ECS上のコンテナログを、AWS FireLensを使ってAmazon CloudWatch Logsに送信する
また、Datadogが使用できる場合はdatadog_log_trigger patternを使ったログ集約を行いましょう。
システムメトリクスの収集¶
public_traffic_container_service pattern
では、コンテナのシステムメトリクス(CPU使用率やメモリ使用量など)を収集する仕組みは提供されません。
下記ガイドで、コンテナのメトリクスをDatadogへ送信する方法を解説しているので、そちらを参照してください。
入出力リファレンス¶
Requirements¶
Name | Version |
---|---|
terraform | ~> 0.14.10 |
aws | >= 3.37.0, < 4.0.0 |
Inputs¶
Name | Description | Type | Default | Required |
---|---|---|---|---|
container_cluster_name | コンテナサービスのクラスター名 | string |
n/a | yes |
container_definitions | コンテナサービスのタスクで実行する、コンテナ定義のリスト | string |
n/a | yes |
container_health_check_path | ロードバランサーの、コンテナに対するヘルスチェックのパス | string |
n/a | yes |
container_port | ロードバランサーがコンテナに転送する際のポート | number |
n/a | yes |
container_protocol | ロードバランサーがコンテナに転送する際のプロトコル | string |
n/a | yes |
container_service_desired_count | コンテナサービス内の、タスクのインスタンス数 | number |
n/a | yes |
container_service_platform_version | コンテナサービスを実行するプラットフォームのバージョン | string |
n/a | yes |
container_subnets | コンテナサービスを配置する、サブネットIDのリスト | list(string) |
n/a | yes |
container_task_cpu | コンテナサービス内で実行されるタスクに割り当てるCPU | number |
n/a | yes |
container_task_memory | コンテナサービス内で実行されるタスクに割り当てるメモリ | string |
n/a | yes |
container_traffic_inbound_cidr_blocks | コンテナサービスが受け付けるトラフィックの、CIDRブロックのリスト | list(string) |
n/a | yes |
dns | ロードバランサーのDNSに関する設定(zone_name, record_name)。 zone_name = record_nameを登録するホストゾーン名 record_name = Amazon Route 53に登録するレコードセットの名前 |
map(any) |
n/a | yes |
name | コンテナサービス、ロードバランサーに関する名前 | string |
n/a | yes |
public_subnets | ロードバランサーに割り当てる、パブリックサブネットのIDのリスト | list(string) |
n/a | yes |
public_traffic_inbound_cidr_blocks | ロードバランサーが受け付けを許可するトラフィックのCIDRブロックのリスト | list(string) |
n/a | yes |
public_traffic_port | ロードバランサーが受け付けるトラフィックのポート | number |
n/a | yes |
public_traffic_protocol | ロードバランサーが受け付けるトラフィックのプロトコル | string |
n/a | yes |
vpc_id | VPC ID | string |
n/a | yes |
alb_fixed_response_listener_rules | ロードバランサーのリスナーに設定する固定レスポンスルールのリスト レスポンスコードとオプションのメッセージを返すことができる [ { priority = ルールの優先順位。値が小さいルールから順に評価される。(例: "10") # Required content_type = コンテントタイプ (例: "text/plain") # Required content_typeに設定できる値についてはcontent_typeを参照してください message_body = メッセージボディ (例: "403 Forbidden") # Required status_code = HTTPレスポンスコード (例: "403") # Required 2XX,4XX,5XXのいずれかを設定してください path_pattern = ルールのアクションが実行される条件。カンマ区切りで複数指定が可能。 (単一の場合の例: "/*" 複数の場合の例: "/foo/*,/bar/*") # Required } ] |
list(map(string)) |
[] |
no |
alb_forward_listener_rules | ロードバランサーのリスナーに設定するフォワードアクションルールのリスト [ { priority = ルールの優先順位。値が小さいルールから順に評価される。 (例: "10") # Required path_pattern = ルールのアクションが実行される条件。カンマ区切りで複数指定が可能。 (単一の場合の例: "/*" 複数の場合の例: "/foo/*,/bar/*") # Required } ] |
list(map(string)) |
[] |
no |
alb_redirect_listener_rules | ロードバランサーのリスナーに設定するリダイレクトルールのリストhost 、path 、port 、protocol 、query に関しては #{host} のように記述することで、元のURLの値を再利用できます詳細についてはリダイレクトアクションを参照してください [ { priority = ルールの優先順位 (例: "10") # Required host = リダイレクト先のホスト (例: "example.com") # Optional 省略した場合 "#{host}" が設定されますpath = リダイレクト先のURLパス (例: "/bar") # Optional 省略した場合 "/#{path}" が設定されますport = リダイレクト先のポート番号 (例: "8080") # Optional 省略した場合 "#{port}" が設定されますprotocol = プロトコル HTTPもしくはHTTPS (例: "HTTPS") # Optional 省略した場合 "#{protocol}" が設定されますquery = クエリパラメータ (例: "key=aaa") # Optional 省略した場合 "#{query}" が設定されますstatus_code = HTTPリダイレクトコード (例: "HTTP_301") # Required "HTTP_301"か"HTTP_302"のいずれかを設定してください path_pattern = ルールのアクションが実行される条件。カンマ区切りで複数指定が可能。 (単一の場合の例: "/*" 複数の場合の例: "/foo/*,/bar/*") # Required } ] |
list(map(string)) |
[] |
no |
container_log_group_kms_key_id | CloudWatch Logsを暗号化するためのKMS CMKのARN | string |
null |
no |
container_log_group_names | コンテナのログ出力先と成るCloudWatch Logsのグループ名のリスト | list(string) |
[] |
no |
container_log_group_retention_in_days | CloudWatch Logsに保存した、コンテナログの保持日数 | number |
null |
no |
container_task_execution_role_arn | コンテナサービスのタスクに割り当てるタスク実行IAMロールのARN。create_default_ecs_task_execution_roleをfalseにする場合に指定すること | string |
null |
no |
container_task_role_arn | コンテナサービスのタスクが、他のAWSサービスを呼び出せるように割り当てるIAMロールのARN | string |
null |
no |
container_traffic_inbound_protocol | コンテナサービスが受け付けるトラフィックのプロトコル | string |
"tcp" |
no |
create_default_ecs_task_execution_role | デフォルトのタスク実行ロールを作成する場合、trueを指定する | bool |
true |
no |
create_default_ecs_task_role | デフォルトのタスク実行ロールを作成する場合、trueを指定する | bool |
true |
no |
create_public_traffic_certificate | ロードバランサーで利用するSSL/TLS証明書を作成する場合、true | bool |
true |
no |
default_ecs_task_execution_iam_policy_name | デフォルトのタスク実行ロールを作成する場合のIAMポリシー名 | string |
"DefaultContainerServiceTaskExecutionRolePolicy" |
no |
default_ecs_task_execution_iam_role_name | デフォルトのタスク実行ロールを作成する場合のIAMロール名 | string |
"DefaultContainerServiceTaskExecutionRole" |
no |
default_ecs_task_iam_policy_name | デフォルトのタスクロールを作成する場合のIAMポリシー名 | string |
"DefaultContainerServiceTaskRolePolicy" |
no |
default_ecs_task_iam_role_name | デフォルトのタスクロールを作成する場合のIAMロール名 | string |
"DefaultContainerServiceTaskRole" |
no |
public_traffic_access_logs_bucket | ロードバランサーのアクセスログを保存するS3バケット名。public_traffic_access_logs_enabledがtrueで、この変数を指定しない場合、nameから自動導出する | string |
null |
no |
public_traffic_access_logs_create_bucket | bucketに指定したS3バケットをこのモジュールで作成する場合、trueを指定する。デフォルトでtrueが指定されたものとして振る舞う | bool |
true |
no |
public_traffic_access_logs_enabled | ロードバランサーのアクセスログを有効にする場合、trueを指定する。デフォルトでtrueが指定されたものとして振る舞う | bool |
true |
no |
public_traffic_access_logs_force_destroy | destroy時、データがあったとしても強制的にアクセスログ用S3バケットを削除する | bool |
false |
no |
public_traffic_access_logs_prefix | アクセスログをS3バケットに保存する時のprefix。指定しない場合は、ログはS3のルートに保存される | string |
null |
no |
public_traffic_certificate_arn | ロードバランサーに与えるSSL/TLS証明書のARN。このpattern外部で証明書を作成する場合に使用する | string |
null |
no |
public_traffic_inbound_protocol | ロードバランサーが受け付けるトラフィックのプロトコル。セキュリティグループの指定に利用 | string |
"tcp" |
no |
public_traffic_ssl_policy | ロードバランサーのデフォルトのセキュリティポリシー | string |
"ELBSecurityPolicy-TLS-1-2-Ext-2018-06" |
no |
tags | このモジュールで作成するリソースに、共通的に付与するタグ | map(string) |
{} |
no |
Outputs¶
Name | Description |
---|---|
cloudwatch_container_log_names | コンテナのログ出力先となる、CloudWatch Logsのロググループ名のリスト |
ecs_cluster_name | ECSクラスター名 |
ecs_service_name | ECSサービス名 |
load_balancer_access_logs_bucket | ロードバランサーのアクセスログ出力用のS3バケット名 |
load_balancer_access_logs_bucket_id | ロードバランサーのアクセスログ出力用のS3バケットのID |
load_balancer_arn | ロードバランサーのARN |
load_balancer_prod_listener_arn | 本番環境用トラフィックを受け持つ、ロードバランサーのListenerのARN |
load_balancer_target_group_names | LoadBalancerのターゲットグループ名のリスト |
※ このドキュメントはクリエイティブコモンズ(Creative Commons) 4.0 の「表示—継承」に準拠しています。
※ このドキュメントに記載されている会社名、製品名は、各社の登録商標または商標です。
© 2021 TIS Inc.