note

Terraform

Terraform 官方網站,可以查到各種 Terraform 的使用方法: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/instance

Spot instance: 閒置的資源,可以用比較低的價格使用

使用terraform實作可以用外網連線的EC2網頁

接下來我們先使用 terraform 建立 VPC

vim main.tf
provider "aws" {
  region = "us-east-1" # 設定區域
}

resource "aws_vpc" "myvpc"{
    cidr_block="192.168.0.0/16" 
    tags = {
        Name = "myvpc" # 設定名稱
    }
}

terraform run

terraform init 
terraform apply

terraform delete

terraform destroy 

建立子網路,上面 VPC 已經被創建,所以 myvpc 已經不會再次被執行

provider "aws" {
  region = "us-east-1" # 設定區域
}

resource "aws_vpc" "myvpc"{ # myvpc 代表 ID
    cidr_block="192.168.0.0/16" 
    tags = {
        Name = "myvpc" # 設定名稱
    }
}

resource "aws_subnet" "myvpc-web" {
    vpc_id = "${aws_vpc.myvpc.id}" # VPC 的名稱
    cidr_block = "192.168.1.0/24"
    availability_zone = "us-east-1a"
    tags = {
        Name = "myvpc-web"
    }
}

建立 internet gateway 讓 VPC 可以連上網路,貼在上面程式碼的下方

resource "aws_internet_gateway" "igw" {
    vpc_id="${aws_vpc.myvpc.id}"
    tags = {
        Name = "myvpc-igw"
    }
}

建立 route table,讓路由器可以連線到 IGW

resource "aws_route_table" "myrt" {
    vpc_id="${aws_vpc.myvpc.id}"

    route {
        # defualt route # 新增內定路由
        cidr_block="0.0.0.0/0" # 連線到 igw
        gateway_id = "${aws_internet_gateway.igw.id}"
    }

    tags = {
        Name = "myvpc-rt"
    }
}

把剛剛創建的 route table,連線到 subnet myvpc-web

resource "aws_route_table_association" "myrt_assoc" {
    subnet_id = aws_subnet.myvpc-web.id
    route_table_id = aws_route_table.myrt.id
}

建立 VPC 的 SG,允許使用 HTTPS 和 HTTP

resource "aws_security_group" "sg_myvpc" {
    name = "sg_myvpc"
    description="security group for myvpc"
    vpc_id="${aws_vpc.myvpc.id}"

    ingress {
       description = "HTTPS traffic"
       from_port = 443
       to_port = 443
       protocol ="tcp"
       cidr_blocks = ["0.0.0.0/0"]   # 指任何地方都可以連線進來 
    }

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

    ingress {
       description = "SSH traffic"
       from_port = 22
       to_port = 22
       protocol ="tcp"
       cidr_blocks = ["0.0.0.0/0"]   
    }

    egress {   #  don't care,不管出去的資料
        from_port = 0
        to_port = 0
        protocol ="-1"
        cidr_blocks= ["0.0.0.0/0"]  
    }

    tags = {
        Name = "sg_myvpc"
    }
}

使用付費的 elastic IP,讓網址固定 (申請網路卡和 IP)

resource "aws_network_interface" "webserver-nic" {
    subnet_id = aws_subnet.myvpc-web.id
    private_ips=["192.168.1.100"]
    security_groups = ["${aws_security_group.sg_myvpc.id}"]  
}

resource "aws_eip" "web-eip" {
    vpc = true
    network_interface = aws_network_interface.webserver-nic.id
    associate_with_private_ip = "192.168.1.100" # 申請完的 IP 會和 192.168.1.100 綁定
    depends_on = [aws_internet_gateway.igw] # 運用 IGW 連線到外網
}

最後放入 EC2,我們使用 ubuntu 的 AMI

resource "aws_instance" "webserver" { 
  ami="ami-0c7217cdde317cfec" # 放入 AMI
  instance_type = "t2.micro"
  availability_zone = "us-east-1a"
  key_name = "testkey" # 要放在同一個資料夾裡面 (test.pem)

  network_interface {
    device_index = 0
    network_interface_id = aws_network_interface.webserver-nic.id
  }
  # 腳本內容為安裝 apache,然後建立一個簡單的網頁
  user_data = <<-EOF  
              #!/bin/bash
              sudo apt update -y
              sudo apt install apache2 -y
              sudo systemctl start apache2
              sudo bash -c 'echo your very first web server > /var/www/html/index.html'
              EOF   
  tags ={
    Name = "web-server"
  }
}

最後使用 ssh 連線看看

ssh -i "testkey.pem" ubuntu@34.194.125.17

完整程式碼

provider "aws" {
  region = "us-east-1" 
}

resource "aws_vpc" "myvpc"{
    cidr_block="192.168.0.0/16" 
    tags = {
        Name = "myvpc"
    }
}

resource "aws_subnet" "myvpc-web" {
    vpc_id = "${aws_vpc.myvpc.id}"
    cidr_block = "192.168.1.0/24"
    availability_zone = "us-east-1a"
    tags = {
        Name = "myvpc-web"
    }   
}

resource "aws_internet_gateway" "igw" {
    vpc_id="${aws_vpc.myvpc.id}"
    tags = {
        Name = "myvpc-igw"
    }
}

resource "aws_route_table" "myrt" {
    vpc_id="${aws_vpc.myvpc.id}"

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

    tags = {
        Name = "myvpc-rt"
    }
}

resource "aws_route_table_association" "myrt_assoc" {
    subnet_id = aws_subnet.myvpc-web.id
    route_table_id = aws_route_table.myrt.id
}

resource "aws_security_group" "sg_myvpc" {
    name = "sg_myvpc"
    description="security group for myvpc"
    vpc_id="${aws_vpc.myvpc.id}"

    ingress {
       description = "HTTPS traffic"
       from_port = 443
       to_port = 443
       protocol ="tcp"
       cidr_blocks = ["0.0.0.0/0"]
    }

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

    ingress {
       description = "SSH traffic"
       from_port = 22
       to_port = 22
       protocol ="tcp"
       cidr_blocks = ["0.0.0.0/0"]   
    }

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

    tags = {
        Name = "sg_myvpc"
    }
}

resource "aws_network_interface" "webserver-nic" {
    subnet_id = aws_subnet.myvpc-web.id
    private_ips=["192.168.1.100"]
    security_groups = ["${aws_security_group.sg_myvpc.id}"]  
}

resource "aws_eip" "web-eip" {
    vpc = true
    network_interface = aws_network_interface.webserver-nic.id
    associate_with_private_ip = "192.168.1.100"
    depends_on = [aws_internet_gateway.igw] 
}

resource "aws_instance" "webserver" { 
  ami="ami-0c7217cdde317cfec"
  instance_type = "t2.micro"
  availability_zone = "us-east-1a"
  key_name = "testkey"

  network_interface {
    device_index = 0
    network_interface_id = aws_network_interface.webserver-nic.id
  }
  user_data = <<-EOF
              #!/bin/bash
              sudo apt update -y
              sudo apt install apache2 -y
              sudo systemctl start apache2
              sudo bash -c 'echo your very first web server > /var/www/html/index.html'
              EOF   
  tags ={
    Name = "web-server"
  }
}

terraform delete

terraform destroy 

使用terraform實作ALB連線到兩台EC2

加分題: 使用 terraform 實作 ALB 連線到兩台 EC2 (需要自己配置 ALB)

參考超級完整網站: https://antonputra.com/amazon/create-alb-terraform/#secure-alb-with-tls-certificate

provider "aws" {
  region = "us-east-1" 
}

resource "aws_vpc" "myvpc"{
    cidr_block="192.168.0.0/16" 
    tags = {
        Name = "myvpc"
    }
}

resource "aws_subnet" "myvpc-web-a" {
    vpc_id = "${aws_vpc.myvpc.id}"
    cidr_block = "192.168.1.0/24"
    availability_zone = "us-east-1a"
    tags = {
        Name = "myvpc-web-a"
    }   
}
resource "aws_subnet" "myvpc-web-b" {
    vpc_id = "${aws_vpc.myvpc.id}"
    cidr_block = "192.168.2.0/24"
    availability_zone = "us-east-1b"
    tags = {
        Name = "myvpc-web-b"
    }   
}
resource "aws_internet_gateway" "igw" {
    vpc_id="${aws_vpc.myvpc.id}"
    tags = {
        Name = "myvpc-igw"
    }
}

resource "aws_route_table" "myrt" {
    vpc_id="${aws_vpc.myvpc.id}"

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

    tags = {
        Name = "myvpc-rt"
    }
}

resource "aws_route_table_association" "myrt_assoc-a" {
    subnet_id = aws_subnet.myvpc-web-a.id
    route_table_id = aws_route_table.myrt.id
}
resource "aws_route_table_association" "myrt_assoc-b" {
    subnet_id = aws_subnet.myvpc-web-b.id
    route_table_id = aws_route_table.myrt.id
}

resource "aws_security_group" "sg_myvpc" {
    name = "sg_myvpc"
    description="security group for myvpc"
    vpc_id="${aws_vpc.myvpc.id}"

    ingress {
       description = "HTTPS traffic"
       from_port = 443
       to_port = 443
       protocol ="tcp"
       cidr_blocks = ["0.0.0.0/0"]
    }

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

    ingress {
       description = "SSH traffic"
       from_port = 22
       to_port = 22
       protocol ="tcp"
       cidr_blocks = ["0.0.0.0/0"]   
    }

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

    tags = {
        Name = "sg_myvpc"
    }
}

resource "aws_instance" "web-server-a" { 
  ami="ami-0c7217cdde317cfec"
  instance_type = "t2.micro"
  availability_zone = "us-east-1a"
  key_name = "testkey"
  # 沒有 interface elastic IP 需要加上下列三個參數設定
  associate_public_ip_address = "true"
  subnet_id = aws_subnet.myvpc-web-a.id
  security_groups = ["${aws_security_group.sg_myvpc.id}"]
    
  user_data = <<-EOF
              #!/bin/bash
              sudo apt update -y
              sudo apt install apache2 -y
              sudo systemctl start apache2
              sudo bash -c 'echo web server a> /var/www/html/index.html'
              EOF   
  tags ={
    Name = "web-server-a"
  }
}

resource "aws_instance" "web-server-b" { 
  ami="ami-0c7217cdde317cfec"
  instance_type = "t2.micro"
  availability_zone = "us-east-1b"
  key_name = "testkey"
  # 沒有 interface elastic IP 需要加上下列三個參數設定
  associate_public_ip_address = "true"
  subnet_id = aws_subnet.myvpc-web-b.id 
  security_groups = ["${aws_security_group.sg_myvpc.id}"]
    
  user_data = <<-EOF
              #!/bin/bash
              sudo apt update -y
              sudo apt install apache2 -y
              sudo systemctl start apache2
              sudo bash -c 'echo web server b > /var/www/html/index.html'
              EOF   
  tags ={
    Name = "web-server-b"
  }
}

resource "aws_lb_target_group" "aws_lb_tg" {
  name     = "tf-example-lb-tg"
  port     = 80
  protocol = "HTTP"
  vpc_id   = aws_vpc.myvpc.id
}

# 把 EC2 連結 target group
resource "aws_lb_target_group_attachment" "aws_lb_tg_at_a" {  
  target_group_arn = aws_lb_target_group.aws_lb_tg.arn
  target_id        = aws_instance.web-server-a.id
  port             = 80
}
resource "aws_lb_target_group_attachment" "aws_lb_tg_at_b" {  
  target_group_arn = aws_lb_target_group.aws_lb_tg.arn
  target_id        = aws_instance.web-server-b.id
  port             = 80
}

resource "aws_lb" "my_app_eg1" {
  name               = "my-app-eg1"
  internal           = false
  load_balancer_type = "application"
  security_groups    = [aws_security_group.sg_myvpc.id]

  # access_logs {
  #   bucket  = "my-logs"
  #   prefix  = "my-app-lb"
  #   enabled = true
  # }

  subnets = [
    aws_subnet.myvpc-web-a.id,
    aws_subnet.myvpc-web-b.id
  ]
}

resource "aws_lb_listener" "my_app_eg1_listener" {
  load_balancer_arn = aws_lb.my_app_eg1.id
  port     = 80
  protocol = "HTTP"
  default_action {
    target_group_arn = aws_lb_target_group.aws_lb_tg.id
    type             = "forward"
  }
}

terraform run

terraform init 
terraform apply

terraform delete

terraform destroy 

最後執行結果