LoginSignup
3
5

More than 5 years have passed since last update.

Terraform備忘録

Posted at

雑メモ

HCL syntax

ref https://www.terraform.io/docs/configuration/syntax.html

リソース

resource "<リースの種類>" "<リソース名>" {}
  • リソースの種類は、プロバイダーがAWSの場合はaws_*という名前でTerraformで予め定義されています。VPCであればaws_vpc、EC2であればaws_instance
  • リソース名は任意の名前を設定可能

参照

<リソースの種類>.<リソース名>.<属性名>

Map

variable "images" {
    default = {
        us-east-1 = "ami-1ecae776"
        us-west-2 = "ami-e7527ed7"
        us-west-1 = "ami-d114f295"
        eu-west-1 = "ami-a10897d6"
        eu-central-1 = "ami-a8221fb5"
        ap-southeast-1 = "ami-68d8e93a"
        ap-southeast-2 = "ami-fd9cecc7"
        ap-northeast-1 = "ami-cbf90ecb"
        sa-east-1 = "ami-b52890a8"
    }
}

List

TODO

変数

Terraformでは、変数はvariableブロックで定義する

変数の定義
variable "<変数名>" {}

Output

terraformした時に結果が見れる

// output "<アウトプットする属性の説明>" { value = "<アウトプットする属性値>"}
output "public ip of cm-test" {
  value = "${aws_instance.cm-test.public_ip}"
}

Terraform Workspace

> terraform workspace list 
* default
  staging
> terraform workspace select staging 
Switched to workspace "staging".
> terraform workspace list
  default
* staging
> terraform workspace show 
staging

$ terraform console
> terraform.workspace
staging
>

Subnet

今回の構成

image.png
https://docs.aws.amazon.com/ja_jp/AmazonVPC/latest/UserGuide/vpc-nat-gateway.html

Subnet構成

  • public
    • public サブネットには、public ip アドレスを付与し、VPCの外からも見えるネットワークを作ります。 ELBを配置します。 また、nat-privateへの踏み台サーバーを建てる
  • nat-private
    • 外部ネットワークからアクセスは行えず、外のネットワークへ出る際に、nat を通るネットワーク おもに、自分で作ったアプリケーション(Railsアプリとか)を配置
  • private
    • 外部ネットワークからアクセスは行えず、外のネットワークに出る必要のないネットワーク Database等のdatastoreを配置

なお、subnetはそれぞれAZごとに作る。 東京リージョンでは aとcとAZがあるので、2つ作る

TFファイル

cidrsubnet

resource "aws_subnet" "public1a" {
  vpc_id = "${aws_vpc.vpc.id}"

  cidr_block        = "${cidrsubnet(aws_vpc.vpc.cidr_block, 8, 0)}"
  availability_zone = "ap-northeast-1a"

  tags {
    Name    = "${var.service}-${var.envname}-public1a"
  }
}

resource "aws_subnet" "public1c" {
  vpc_id = "${aws_vpc.vpc.id}"

  cidr_block        = "${cidrsubnet(aws_vpc.vpc.cidr_block, 8, 1)}"
  availability_zone = "ap-northeast-1c"

  tags {
    Name    = "${var.service}-${var.envname}-public1c"
  }
}

resource "aws_subnet" "nat-private1a" {
  vpc_id = "${aws_vpc.vpc.id}"

  cidr_block        = "${cidrsubnet(aws_vpc.vpc.cidr_block, 8, 4)}"
  availability_zone = "ap-northeast-1a"

  tags {
    Name    = "${var.service}-${var.envname}-nat-private1a"
  }
}

resource "aws_subnet" "nat-private1c" {
  vpc_id = "${aws_vpc.vpc.id}"

  cidr_block        = "${cidrsubnet(aws_vpc.vpc.cidr_block, 8, 5)}"
  availability_zone = "ap-northeast-1c"

  tags {
    Name    = "${var.service}-${var.envname}-nat-private1c"
  }
}

resource "aws_subnet" "private1a" {
  vpc_id = "${aws_vpc.vpc.id}"

  cidr_block        = "${cidrsubnet(aws_vpc.vpc.cidr_block, 8, 2)}"
  availability_zone = "ap-northeast-1a"

  tags {
    Name    = "${var.service}-${var.envname}-private1a"
  }
}

resource "aws_subnet" "private1c" {
  vpc_id = "${aws_vpc.vpc.id}"

  cidr_block        = "${cidrsubnet(aws_vpc.vpc.cidr_block, 8, 3)}"
  availability_zone = "ap-northeast-1c"

  tags {
    Name    = "${var.service}-${var.envname}-private1c"
  }
}

cidrsubnetの計算

> cidrsubnet("172.20.0.0/16", 3, 0)
172.20.0.0/19 //  00000000
> cidrsubnet("172.20.0.0/16", 3, 1)
172.20.32.0/19 // 00100000
> cidrsubnet("172.20.0.0/16", 3, 2)
172.20.64.0/19 // 01000000
> cidrsubnet("172.20.0.0/16", 3, 3)
172.20.96.0/19 // 01100000
...
> cidrsubnet("172.20.0.0/16", 3, 7) # 3つ目のブロックの3ビット分を7(111)で埋めるので、11100000(224)
172.20.224.0/19
> cidrsubnet("172.20.0.0/16", 3, 8) // 8は2進数で4桁(1000)なのでエラー
cidrsubnet: prefix extension of 3 does not accommodate a subnet numbered 8 in:

ref
https://note.cman.jp/network/subnetmask.cgi
https://hogehoge.tk/tool/number.html

IPv4プライベートアドレス範囲(RFC1918):

10.0.0.0〜10.255.255.255(24ビットブロック)
172.16.0.0〜172.31.255.255(20ビットブロック)
192.168.0.0〜192.168.255.255(16ビットブロック)

ref http://itdoc.hitachi.co.jp/manuals/3021/3021324220/NNMS0200.HTM

subnet のネットワーク

subnet内でのネットワークの流れを定義する必要があります。 どうやって外と通信するか。という感じ

public subnetでは、internet gateway を用意します。
これはVPCとしてのネットワークの出入り口でもあります。

nat-private subnetでは nat_gateway というものを用意します。
これは実態としてはEC2インスタンス(だとおもう)で、public ipアドレスを付与する必要があります。 以前は、AWSが用意したnat用のAMIを自身で起動して用意していましたが、nat_gatewayというマネージドなnatが利用できるようになりました。

resource "aws_internet_gateway" "gw" {
  vpc_id = "${aws_vpc.vpc.id}"

  tags {
    Name    = "${var.service}_${var.envname}_gateway"
  }
}

resource "aws_eip" "nat_gateway" {
  vpc = true
}

resource "aws_nat_gateway" "nat_gw" {
  allocation_id = "${aws_eip.nat_gateway.id}"
  subnet_id     = "${aws_subnet.public1a.id}"
  depends_on    = ["aws_internet_gateway.gw"]
}

ルートテーブル
実際の、subnetのルーティングを設定します。 0.0.0.0/0 、つまりすべてのネットワークをgatewayに流していく

resource "aws_route_table" "public" {
  vpc_id = "${aws_vpc.vpc.id}"

  route {
    cidr_block = "0.0.0.0/0"
    gateway_id = "${aws_internet_gateway.gw.id}"
  }

  tags {
    Name    = "${var.service}_${var.envname}_public"
  }
}

resource "aws_route_table" "nat-private" {
  vpc_id = "${aws_vpc.vpc.id}"

  route {
    cidr_block     = "0.0.0.0/0"
    nat_gateway_id = "${aws_nat_gateway.nat_gw.id}"
  }

  tags {
    Name    = "${var.service}_${var.envname}_nat-private"
  }
}

ルートテーブルを作っただけではダメで、それをどのsubnetで使うかを設定

resource "aws_route_table_association" "public1a" {
  route_table_id = "${aws_route_table.public.id}"
  subnet_id      = "${aws_subnet.public1a.id}"
}

resource "aws_route_table_association" "public1c" {
  route_table_id = "${aws_route_table.public.id}"
  subnet_id      = "${aws_subnet.public1c.id}"
}

resource "aws_route_table_association" "nat-private1a" {
  route_table_id = "${aws_route_table.nat-private.id}"
  subnet_id      = "${aws_subnet.nat-private1a.id}"
}

resource "aws_route_table_association" "nat-private1c" {
  route_table_id = "${aws_route_table.nat-private.id}"
  subnet_id      = "${aws_subnet.nat-private1c.id}"
}

セキュリティーグループ

aws_security_group.tf
resource "aws_security_group" "allow_all" {
    vpc_id = "${aws_vpc.vpc-1.id}"
    name = "allow_all" // AWS 上の実際のセキュリティグループ名称
    ingress { //  inbound 側のセキュリティ指定
        from_port = 80 // 開始ポート
        to_port = 80 // 終了ポート
        protocol = "tcp"
        cidr_blocks = ["0.0.0.0/0"] // 許可する CIDR
    }
    egress {//  outbound 側のセキュリティ指定
        from_port = 0
        to_port = 0 
        protocol = "-1" // 1にすると全トラフィック。
        cidr_blocks = ["0.0.0.0/0"]  // 許可するアドレスの範囲
    }
    description = "test"
}

Load balancer

Network Load Balancer(NLB) : L4 NATロードバランサ
Application Load Balancer(ALB) : L7リバースプロキシ
Classic Load Balancer(CLB) : L4/L7リバースプロキシ

リソース 用途
aws_lb LBの作成
aws_lb_target_group ターゲットグループの作成
aws_lb_target_group_attachment ターゲットグループとインスタンスまたはコンテナとひも付け
aws_lb_listener リスナーの作成(とALBとターゲットグループのひも付け)
aws_lb_listener_rule リスナーのルール作成
クライアント <-> リスナー <-> ターゲット
resource "aws_lb" "alb" {
  name                       = "${var.name}"
  security_groups            = ["${aws_security_group.alb.id}"]  // ALBに紐付けるセキュリティグループの配列
  subnets                    = ["${aws_subnet.frontend_subnet.*.id}"] // ALBに紐付けるサブネットIDの配列
  internal                   = false // true であればInternal ALBに
  enable_deletion_protection = false
  load_balancer_type         = "application"

  access_logs {
    bucket = "${aws_s3_bucket.alb_log.bucket}"
  }
}

resource "aws_lb_target_group" "alb" {
  count    = 2
  name     = "${var.name}-tg${count.index+1}"
  port     = 80
  protocol = "HTTP"
  vpc_id   = "${aws_vpc.vpc.id}"

  health_check { // ヘルスチェック
    interval            = 30
    path                = "/index.html"
    port                = 80
    protocol            = "HTTP"
    timeout             = 5
    unhealthy_threshold = 2
    matcher             = 200
  }
  // スティッキーセッションの設定もある
}

resource "aws_lb_listener" "alb" {
  load_balancer_arn = "${aws_alb.alb.arn}" // ALBのARN
  port              = "443" // ALBが待ち受けるポート番号
  protocol          = "HTTPS" // クライアントからALBへのアクセス時に利用されるプロトコル
  ssl_policy        = "ELBSecurityPolicy-2015-05" // クライアンとALB間での通信に利用されるSSLポリシー
  certificate_arn   = "${var.alb_config["certificate_arn"]}"  // (AWS上の)SSL証明書のARN

  default_action { // リスナーのデフォルトアクション
    target_group_arn = "${aws_alb_target_group.alb.0.arn}" // ターゲットグループのARN。 このターゲットグループにトラフィックが流れる
    type             = "forward" // トラフィックの流し方
  }
}

ARN構文

arn:partition:service:region:account-id:resource

ECS

image.png

用語について

用語 解説
Task Definitions コンテナの集合を定義。必ず同じインスタンスになる ≒ docker-compose
Task Task Definitionsが実体化されたもの、リソースの余裕のあるContainer Instanceで実行される
Container Taskの実態であるDocker Containers、Container Instance上で動く
Container Instance ContainerのホストとなるAmazon EC2、DockerとAgentが動いている
Agent Amazon ECSのエンドポイントと通信するエージェント
Cluster Container Instanceの集合体
Serivce Web APIのような長期的なワークロードに最適、Taskを必要数保つスケジューラー
Run Task バッチジョブのような短期的なワークロードに最適、Task Definitionsにしていしたタスクを実行する

ref https://www.slideshare.net/AmazonWebServicesJapan/20150727-jaws-container1-ecspublic

AWS Moduleのリソースについて

リソース 用途
aws_ecs_cluster LBの作成
aws_ecs_task_definition ターゲットグループの作成
template_file ターゲットグループとインスタンスまたはコンテナとひも付け

権限

IAMユーザーとIAMロールとIAMグループ

ポリシー

ポリシーは基本的に、「誰が」「どのAWSサービスの」「どのリソースに対して」「どんな操作を」「許可する(許可しない)」、といったことをJSON形式で記述します。
記述したポリシーをユーザー(IAMユーザー、IAMグループ、IAMロール)や、AWSリソースに関連づけることで、アクセス制御を実現しています。

references

3
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
5