2021年3月10日水曜日

Terraform(ECS & Firehose)

Terraformを使って、ECSが稼働する一式を作成してみる。

以下がTerraformで作成したECSのアーキテクチャになる。
①VPC
②ALB(Load Blanser)
③ECS(Fargate)/ログ出力用のサイドカーコンテナ(Firelens)
④Firehouse(ログのストリーム)
⑤S3(ログ保存)
⑥Route53(サービスディスカバリー用)
  ->バックエンド側とフロント側のコンテナの接点として利用
⑦CloudWatch(コンテナのログ出力先の用途)
⑧Terraform(Ver:0.15)


 















次にTerraformの記載内容について説明します。

①ECSのタスク定義ファイル類
②CloudWatch
③ECS
④ELB(application Load blanser)
⑤firehose
⑥network
⑦出力用
⑧プロバイダー用(リージョン指定など)
⑨変数用











module関連のファイルやディレクトリが記載されているが
今回は正式に利用しないので、説明は割愛する。



②CloudWatch

######################
# Cloudwatch
######################
// front(nginx用) //
resource "aws_cloudwatch_log_group" "main" {
name = "/ecs/foo" # ロググループの作成 
retention_in_days = 30 # ログの保有期間(日数)
}

// backend(APP用) //
resource "aws_cloudwatch_log_group" "main_back" {
name = "/ecs/foo_back" # ロググループの作成 
retention_in_days = 30 # ログの保有期間(日数)
}


// Firelens用 //
resource "aws_cloudwatch_log_group" "firelens" {
name = "/ecs/firelens-example" # ロググループの作成 
retention_in_days = 30 # ログの保有期間(日数)
}


③ECS

##########################
# ecs cluster
##########################
// クラスター作成 (for Fargate) //
resource "aws_ecs_cluster" "foo" {
name = var.name-01 # クラスター名
// 詳細設定 //
setting {
name = "containerInsights" # CloudWatch Container Insights
value = "enabled" # 有効にする(enabled)
}
}


##########################
# Task Definition (Front)
##########################
// タスク定義(nginx用) //
resource "aws_ecs_task_definition" "foo" {
family = "mongo" # タスク定義名(mongo)
container_definitions = file("./task-definitions/fargate-task_front.json") # タスク定義指定
requires_compatibilities = ["FARGATE"] # 互換性が必要(FARGATE)
network_mode = "awsvpc" # ネットワークモード
// タスクサイズ //
cpu = "256" # タスクメモリ:1CPUの25%使用
memory = "512" # タスクCPU(単位) :512MB
execution_role_arn = "arn:aws:iam:::role/ecsTaskExecutionRole" # タスクロール
}


#########################
# Service (Front)
#########################
// サービス(nginx用) //
resource "aws_ecs_service" "mongo" {
name = var.name-01 # サービス名
cluster = aws_ecs_cluster.foo.arn # クラスター(foo)を指定
task_definition = aws_ecs_task_definition.foo.arn # タスク定義(foo)を指定
desired_count = 1 # タスクの台数
launch_type = "FARGATE" # 機動タイプ(FARGATE)
platform_version = "1.4.0" # プラットフォームバージョン
health_check_grace_period_seconds = 60 # ヘルスチェックの猶予期間
depends_on = [aws_lb_listener.main] # 依存関係:リスナーを指定

network_configuration {
assign_public_ip = true # ENIにパブリックIPアドレスを割り当てる(true:有効)

security_groups = [aws_security_group.web_service.id]
subnets = [aws_subnet.public1.id, aws_subnet.public2.id] # サブネットを指定
}

load_balancer {
target_group_arn = aws_lb_target_group.foo.arn # ターゲットグループ(foo)連携
container_name = var.name-01 # タスク定義ですでに指定されているコンテナー名の値
container_port = 80 # ポート番号
}

lifecycle {
ignore_changes = [task_definition] # ライフサイクル(タスク定義)
}
}

##########################
# Task Definition (back)
##########################
// タスク定義(APP用) //
resource "aws_ecs_task_definition" "foo_back" {
family = "mongo_back" # タスク定義名(mongo)
container_definitions = file("./task-definitions/fargate-task_back.json") # タスク定義指定
requires_compatibilities = ["FARGATE"] # 互換性が必要(FARGATE)
network_mode = "awsvpc" # ネットワークモード
// タスクサイズ //
cpu = "256" # タスクメモリ :1スレッドの25%
memory = "512" # タスクCPU(単位) :512MB
execution_role_arn = "arn:aws:iam:::role/ecsTaskExecutionRole" # タスクロール
}


##########################
# Service (Back)
##########################
// サービス(APP用) //
resource "aws_ecs_service" "mongo_back" {
name = var.name-03 # サービス名
cluster = aws_ecs_cluster.foo.arn # クラスター(foo)を指定
task_definition = aws_ecs_task_definition.foo_back.arn # タスク定義(foo_back)を指定
desired_count = 1 # タスクの台数
launch_type = "FARGATE" # 機動タイプ(FARGATE)
platform_version = "1.4.0" # プラットフォームバージョン
//depends_on = [aws_lb_listener.main] # 依存関係:リスナーを指定

service_registries {
registry_arn = aws_service_discovery_service.service_a.arn
}

network_configuration {
assign_public_ip = true # ENIにパブリックIPアドレスを割り当てる(true:有効)
security_groups = [aws_security_group.web_service.id]
subnets = [aws_subnet.public1.id, aws_subnet.public2.id] # サブネットを指定
}

lifecycle {
ignore_changes = [task_definition] # ライフサイクル(タスク定義)
}
}


##########################
# Service Discovery (back)
##########################
// サービスディスカバリー(APP用)
resource "aws_service_discovery_private_dns_namespace" "internal" {
name = "spring.local"
vpc = aws_vpc.main.id
description = "Service Discovery(for Backend)"
}

resource "aws_service_discovery_service" "service_a" {
name = "front"

dns_config {
namespace_id = aws_service_discovery_private_dns_namespace.internal.id

dns_records {
ttl = 10
type = "A"
}

routing_policy = "MULTIVALUE"
}

health_check_custom_config {
failure_threshold = 1
}
}


④Firehouse

#######################
# S3 for firehouse
#######################
resource "aws_s3_bucket" "bucket" {
bucket = "foo-backet"
acl = "private"
}

#######################
# IAM Role
#######################
resource "aws_iam_role" "firehose_role" {
name = "firehose_test_role"

assume_role_policy = <<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Action": "sts:AssumeRole",
"Principal": {
"Service": "firehose.amazonaws.com"
},
"Effect": "Allow",
"Sid": ""
}
]
}
EOF
}

#######################
# kinesis firehouse
#######################
resource "aws_kinesis_firehose_delivery_stream" "foo_stream" {
name = "foo-stream"
destination = "s3"

s3_configuration {
role_arn = aws_iam_role.firehose_role.arn
bucket_arn = aws_s3_bucket.bucket.arn
}
}


⑥ network

####################
# VPC
####################
resource "aws_vpc" "main" {
cidr_block = var.cidr-block-vpc # CIDRブロック(VPC用)
enable_dns_hostnames = true # VPCでDNSホスト名を有効/無効にする(有効)
enable_dns_support = true # VPCでDNSサポートを有効/無効にする(有効)
instance_tenancy = "default" # VPCで起動されたインスタンスのテナンシーオプション

tags = {
Name = var.name-02 # タグ名
}
}


#####################
# Internet Gateway
#####################
// VPCインターネットゲートウェイ //
resource "aws_internet_gateway" "main" {
vpc_id = aws_vpc.main.id # VPC(main)を指定
}


####################
# subnet
####################
// サブネット1 //
resource "aws_subnet" "public1" {
vpc_id = aws_vpc.main.id # VPC(main)を指定
cidr_block = var.cidr-block-1 # CIDRブロック
availability_zone = var.az1 # azを指定
map_public_ip_on_launch = true # trueを指定して、サブネットに起動されたインスタンスにパブリックIPアドレスを割り当てる必要があることを示します
}
// サブネット2 //
resource "aws_subnet" "public2" {
vpc_id = aws_vpc.main.id # VPC(main)を指定
cidr_block = var.cidr-block-2 # CIDRブロック
availability_zone = var.az2 # azを指定
map_public_ip_on_launch = true # trueを指定して、サブネットに起動されたインスタンスにパブリックIPアドレスを割り当てる必要があることを示します
}


######################
# Route table
######################
// VPCのルーティングテーブル //
resource "aws_route_table" "public" {
vpc_id = aws_vpc.main.id # VPC(main)を指定
tags = {
Name = var.name-02 # タグ名
}
}
// VPCルーティングテーブルにルーティングテーブルエントリ(ルート)を作成するために利用 //
resource "aws_route" "foo" {
route_table_id = aws_route_table.public.id # ルートテーブル(public)を指定
gateway_id = aws_internet_gateway.main.id # インターネットゲートウェイ(main)を指定
destination_cidr_block = var.cidr-block-zero # CIDRブロック(0.0.0.0/0)
}


######################
# Association
######################
resource "aws_main_route_table_association" "foo" {
vpc_id = aws_vpc.main.id # 紐づけたいVPCのIDを指定
route_table_id = aws_route_table.public.id # 紐付けたいルートテーブルのIDを指定
}

resource "aws_route_table_association" "public1" {
subnet_id = aws_subnet.public1.id # 紐づけたいサブネットのIDを指定
route_table_id = aws_route_table.public.id # 紐付けたいルートテーブルのIDを指定
}

resource "aws_route_table_association" "public2" {
subnet_id = aws_subnet.public2.id # 紐づけたいサブネットのIDを指定
route_table_id = aws_route_table.public.id # 紐付けたいルートテーブルのIDを指定
}

######################
# security group
######################
resource "aws_security_group" "web_service" { # セキュリティグループ名
vpc_id = aws_vpc.main.id # VPC指定
dynamic "ingress" { # インバウンド
for_each = var.web_service_ports # for_each

content {
from_port = ingress.value # 変数から指定したポート番号を順番に取得
to_port = ingress.value # 変数から指定したポート番号を順番に取得
protocol = "tcp" # プロトコル(TCP)
cidr_blocks = ["0.0.0.0/0"] # CIDR(0.0.0.0/0)
}
}
egress { # アウトバウンド
from_port = 0
to_port = 0
protocol = "-1" # 全て
cidr_blocks = ["0.0.0.0/0"] # CIDR(0.0.0.0/0)
}
}


⑨変数用

// 変数の一覧 //

#######################
# name
#######################
variable "name-01" { # nameの変数名
default = "foo"
}

variable "name-02" { # nameの変数名
default = "for terraform"
}

variable "name-03" { # nameの変数名
default = "foo_back"
}

#######################
# network
#######################
variable "cidr-block-vpc" { # CIDRブロックの変数名
default = "10.0.0.0/16" # CIDRブロックを指定
description = "VPC Subnet" # 備考
}

variable "cidr-block-1" { # CIDRブロックの変数
default = "10.0.16.0/20" # CIDRブロックを指定
description = "Availability_zone Subnet1" # 備考
}

variable "cidr-block-2" { # CIDRブロックの変数名
default = "10.0.32.0/20" # CIDRブロックを指定
description = "Availability_zone Subnet2" # 備考
}

variable "cidr-block-zero" { # CIDRブロックの変数名
default = "0.0.0.0/0" # CIDRブロックを指定
description = "cidr_block-zero" # 備考
}

#######################
# availability_zone
#######################
variable "az1" { # azの変数名
default = "ap-northeast-1c" # azを指定
}

variable "az2" { # azの変数名
default = "ap-northeast-1d" # azを指定
}


#######################
# Protocol
#######################
variable "protocol-01" { # プロトコルの変数名
default = "HTTP" # プロトコルを指定
}


######################
# security group
#######################
variable "web_service_ports" { # for_each用の変数
type = list(number) # 数字
description = "list of web service ports" # 備考
default = [
"80", # ポート番号(http:簡易テスト用)
"443", # ポート番号(https用)
"8080", # ポート番号(spring boot用)
]
}






0 件のコメント:

コメントを投稿

php log(ECS ログ出力)

# PHPエラーログの設定 ENV PHP_INI_DIR /usr/local/etc/php RUN { \ echo 'log_errors = On' ; \ echo 'error_log = /proc/self/...