それなりに適当にやってます

なんとなくそれっぽいメモとか備忘録とか適当に。 2018年5月にブログ移転しました。 古い記事は未整理です。

AWS で Packer と Terraform を再勉強

GCPで試してたついでに、せっかくだからAWSでもまた1から作ってやってみた。

Packer

GCP向けに書いたのをベースにbuilders を修正して、yum install -y epel-release を追加した(その辺は省略)

$ export AWS_ACCESS_KEY_ID="ACCESS_KEY"
$ export AWS_SECRET_ACCESS_KEY="SECRET_ACCESS_KEY"
$ export AWS_DEFAULT_REGION="ap-northeast-1"
$ vi base.json                      #<-下記参照
$ packer inspect base.json          #<-何をするか表示
$ packer validate base.json         #<-バリデーションチェック
$ packer build base.json            #<-AMIの作成

base.json

{
  "builders": [
    {
      "type": "amazon-ebs",
      "source_ami": "ami-25bd2743",
      "instance_type": "t2.nano",
      "ssh_username": "centos",
      "region": "ap-northeast-1",
      "ami_name": "packer-example-{{timestamp}}",
      "ssh_timeout": "10m"
    }
  ]
  ...(略

GCPのときと同様に、Ansible で Apache をインストールして index.html が表示されるところまで確認した。

Terraform

GCPで試していた内容をベースに1ファイルでガシガシ作っただけ。 PyCharm に HashiCorp Terraform / HCL language support 入れたので楽だった。

$ export AWS_ACCESS_KEY_ID="ACCESS_KEY"
$ export AWS_SECRET_ACCESS_KEY="SECRET_ACCESS_KEY"
$ export AWS_DEFAULT_REGION="ap-northeast-1"
$ vi main.tf              #<-下記参照
$ terraform init          #<-イニシャライズ
$ terraform plan          #<-確認
$ terraform apply         #<-AWS環境の作成
$ terraform destroy       #<-AWS環境の削除

main.tf

/*
export AWS_ACCESS_KEY_ID="ACCESS_KEY"
export AWS_SECRET_ACCESS_KEY="SECRET_ACCESS_KEY"
export AWS_DEFAULT_REGION="ap-northeast-1"
terrafotm init
terraform plan
terraform apply
*/

provider "aws" {}

/* --------------------------------------------------------------------------------------------------------------------
    VARIABLE
-------------------------------------------------------------------------------------------------------------------- */
variable "vpc_name" {
  default = "terraform-vpc"
}

variable "vpc_cidrblock" {
  default = "10.0.0.0/16"
}

variable "availability_zones" {
  type = "list"

  default = ["ap-northeast-1a", "ap-northeast-1c", "ap-northeast-1d"]
}

variable "security_group_name" {
  default = "default-allow-ssh"
}

variable "ami_id" {
  default = "ami-XXXXXXXX"
  description = "Packer + Ansible で作成したイメージ"
}

variable "ssh_key" {
  default = "USERNAME"
  description = "キーペアに登録したユーザ名"
}

variable "instance_type" {
  default = "t2.nano"
}

variable "allow_ssh_list" {
  type = "list"
  
  default = ["127.0.0.1/32"]
  description = "SSH許可IPリスト"
}

variable "s3_bucket_name" {
  default = "terraform-bucket"
}

variable "alb_name" {
  default = "terraform-alb"
}

/* S3バケットなどグローバルに一意な名前用のランダム値 */
resource "random_id" "rand" {
  byte_length = 11
}

/* --------------------------------------------------------------------------------------------------------------------
    VPC, IGW, SUBNETWORK
-------------------------------------------------------------------------------------------------------------------- */
resource "aws_vpc" "main" {
  cidr_block = "${var.vpc_cidrblock}"

  tags {
    Name = "${var.vpc_name}"
  }
}

resource "aws_internet_gateway" "main" {
  vpc_id = "${aws_vpc.main.id}"

  tags {
    Name = "${var.vpc_name}-default-igw"
  }
}

resource "aws_subnet" "main" {
  count  = 3
  vpc_id = "${aws_vpc.main.id}"

  availability_zone = "${var.availability_zones[count.index]}"

  /* cidrblock を 8bit 単位で区切ったうち、count.index 順に該当するものを返す */
  cidr_block              = "${cidrsubnet(aws_vpc.main.cidr_block, 8, count.index)}"
  map_public_ip_on_launch = true

  tags {
    Name = "${var.vpc_name}-${count.index + 1}"
  }
}

/* --------------------------------------------------------------------------------------------------------------------
    EC2 INSTANCE
-------------------------------------------------------------------------------------------------------------------- */

resource "aws_security_group" "main" {
  name        = "${var.security_group_name}"
  vpc_id      = "${aws_vpc.main.id}"

  egress {
    from_port   = 0
    to_port     = 0
    protocol    = "-1"
    cidr_blocks = ["0.0.0.0/0"]
  }

  ingress {
    from_port   = 22
    to_port     = 22
    protocol    = "tcp"
    cidr_blocks = "${var.allow_ssh_list}"
  }

  ingress {
    from_port   = 80
    to_port     = 80
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  }
}

resource "aws_instance" "main" {
  count                  = 3
  ami                    = "${var.ami_id}"
  instance_type          = "${var.instance_type}"
  key_name               = "${var.ssh_key}"
  vpc_security_group_ids = ["${aws_security_group.main.id}"]
  subnet_id              = "${element(aws_subnet.main.*.id, count.index)}"

  tags {
    Name = "${format("${terraform.workspace}-web-server%02d", count.index + 1)}"
  }
}

resource "aws_eip" "web" {
  count    = "${aws_instance.main.count}"
  instance = "${element(aws_instance.main.*.id, count.index)}"
  vpc      = true
}

/* --------------------------------------------------------------------------------------------------------------------
    S3 Bucket
-------------------------------------------------------------------------------------------------------------------- */
resource "aws_s3_bucket" "main" {
  bucket        = "${var.s3_bucket_name}-${random_id.rand.dec}"
  acl           = "private"
  force_destroy = true

  tags {
    Name = "${var.s3_bucket_name}-${random_id.rand.dec}"
  }
}

resource "aws_s3_bucket_policy" "b" {
  bucket = "${aws_s3_bucket.main.id}"

  policy = <<POLICY
{
  "Id": "Policy1429136655940",
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "Stmt1429136633762",
      "Action": [
        "s3:PutObject"
      ],
      "Effect": "Allow",
      "Resource": "arn:aws:s3:::${aws_s3_bucket.main.bucket}/ALBLogs/*",
      "Principal": {
        "AWS": [
          "582318560864"
        ]
      }
    }
  ]
}
POLICY
}

/* --------------------------------------------------------------------------------------------------------------------
    ALB (New ELB)
-------------------------------------------------------------------------------------------------------------------- */
## ALB
resource "aws_lb" "main" {
  name                       = "${var.alb_name}"
  security_groups            = ["${aws_security_group.main.id}"]
  subnets                    = ["${aws_subnet.main.*.id}"]
  internal                   = false
  enable_deletion_protection = false

  access_logs {
    bucket  = "${aws_s3_bucket.main.bucket}"
    prefix  = "ALBLogs/${terraform.workspace}-${var.alb_name}"
    enabled = true
  }
}

## TARGET GROUP
resource "aws_lb_target_group" "main" {
  name     = "${var.alb_name}-tagetgroup"
  port     = 80
  protocol = "HTTP"
  vpc_id   = "${aws_vpc.main.id}"

  health_check {
    interval            = 30
    path                = "/"
    port                = 80
    protocol            = "HTTP"
    timeout             = 5
    unhealthy_threshold = 2
    matcher             = 200
  }
}

resource "aws_lb_target_group_attachment" "main" {
  count            = "${aws_instance.main.count}"
  target_group_arn = "${aws_lb_target_group.main.arn}"
  target_id        = "${element(aws_instance.main.*.id, count.index)}"
  port             = 80
}

## LISTENER
resource "aws_lb_listener" "main" {
  load_balancer_arn = "${aws_lb.main.arn}"
  port              = "80"
  protocol          = "HTTP"

  default_action {
    target_group_arn = "${aws_lb_target_group.main.arn}"
    type             = "forward"
  }
}

こんな感じで VPC > ゾーン毎のサブネット作成 > EC2インスタンスの作成・設定 > ALBの作成とかまで出来た。

以上