雑メモ
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
今回の構成
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
用語について
用語 | 解説 |
---|---|
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
- https://astap.hatenablog.jp/entry/2017/06/13/124708
- https://int128.hatenablog.com/entry/2018/06/28/180504
- https://dev.classmethod.jp/cloud/terraform-getting-started-with-aws/
- https://qiita.com/zembutsu/items/5de875ed99ac8a56a998
- https://dev.classmethod.jp/cloud/aws/describe-elb-types/
- https://dev.classmethod.jp/cloud/aws/ecs-alb-routing/
- https://christina04.hatenablog.com/entry/2018/02/09/095743
- https://dev.classmethod.jp/cloud/aws/terraform-alb/
- https://www.slideshare.net/AmazonWebServicesJapan/20150727-jaws-container1-ecspublic
- https://dev.classmethod.jp/cloud/aws-iam-policy/