본문 바로가기

DevOps/Terraform

[T102 2주차] (5) 테라폼 VPC

cloudNet@ 팀의 가시다 님이 진행하는 테라폼 102 스터디 2주차 정리입니다.

2주차 내용: 

테라폼 VPC/ASG/ELB

  • VPC

1. VPC

VPCVirtual Private Cloud의 약자로 AWS 클라우드 내 논리적으로 독립된 섹션을 제공하여, 사용자가 정의한 가상 네트워크상에서 다양한 AWS 리소스를 실행할 수 있게 지원합니다.

 

* 참고*

VPC 이전의 AWS 환경은 어땟을까요?

EC2 Classic Network 라는 이름으로 존재했답니다.

1. Public Cloud Service : 인터넷을 통해서만 서비스 
2. 다른 고객과 공유하는 단일 일반 네트워크에서 인스턴스를 실행

  • 독립된 가상의 클라우드 네트워크
  • 하나의 계정에 여러개의 VPC 생성 가능
  • 단일 리전에 여러개 VPC 생성 가능하나 하나의 리전 안에서만 존재할 수 있음

 

  • vpc 배포
cat <<EOT > vpc.tf
provider "aws" {
  region  = "ap-northeast-2"
}

resource "aws_vpc" "myvpc" {
  cidr_block       = "10.10.0.0/16"

  tags = {
    Name = "t101-study"
  }
}
EOT
# 배포
terraform init
terraform plan && terraform apply -auto-approve
terraform state list
aws_vpc.myvpc

# VPC 확인
export AWS_PAGER=""
aws ec2 describe-vpcs | jq
aws ec2 describe-vpcs --output yaml


- CidrBlock: 10.10.0.0/16
  CidrBlockAssociationSet:
  - AssociationId: vpc-cidr-assoc-02c8a0b01330d52d6
    CidrBlock: 10.10.0.0/16
    CidrBlockState:
      State: associated
  DhcpOptionsId: dopt-0c9de467
  InstanceTenancy: default
  IsDefault: false
  OwnerId: '466593096201'
  State: available
  Tags:
  - Key: Name
    Value: t101-study
  VpcId: vpc-04dc814e3796551e6
  • 생성된 VPC의 DNS 옵션을 수정해볼까? 

DNS 확인 : default가 활성화

cat <<EOT > vpc.tf
provider "aws" {
  region  = "ap-northeast-2"
}

resource "aws_vpc" "myvpc" {
  cidr_block       = "10.10.0.0/16"
  enable_dns_support   = true
  enable_dns_hostnames = true

  tags = {
    Name = "t101-study"
  }
}
EOT
  • 예측되는 결과는, dns 호스트이름 : 활성화됨


2. 서브넷

서브넷(Subnet)의 일반적인 개념은 네트워크 영역을 부분적으로 나눈 망으로 정의할 수 있습니다.

AWS의 VPC에서도 서브넷을 통해 네트워크를 분리하여 나눌 수 있습니다.

VPC 내에 서브넷을 통해 네트워크망을 분리하고 있는 모습입니다.

추가로 알아두셔야 할 것은 서브넷의 IP 대역은 VPC의 IP 대역에 속해 있어야 하며, 서브넷1개의 가용 영역(AZ)에 종속되어야 합니다.

 

  • 서브넷 2개 생성
cat <<EOT > vpc.tf
provider "aws" {
  region  = "ap-northeast-2"
}

resource "aws_vpc" "myvpc" {
  cidr_block       = "10.10.0.0/16"
  enable_dns_support   = true
  enable_dns_hostnames = true

  tags = {
    Name = "t101-study"
  }
}

resource "aws_subnet" "mysubnet1" {
  vpc_id     = aws_vpc.myvpc.id
  cidr_block = "10.10.1.0/24"

  availability_zone = "ap-northeast-2a"

  tags = {
    Name = "t101-subnet1"
  }
}

resource "aws_subnet" "mysubnet2" {
  vpc_id     = aws_vpc.myvpc.id
  cidr_block = "10.10.2.0/24"

  availability_zone = "ap-northeast-2c"

  tags = {
    Name = "t101-subnet2"
  }
}

output "aws_vpc_id" {
  value = aws_vpc.myvpc.id
}
EOT
  • 예측 결과 : 해당 vpc 안에 서브넷 2개를 생성해야 함


3. IGW 

 

  • 인터넷 게이트웨이는 VPC와 인터넷 간의 논리적인 연결입니다. 간략하게 VPC에서 인터넷 구간으로 나가는 관문
  • 인터넷 게이트웨이는 VPC 당 1개만 생성할 수 있습니다.
  • 인터넷 게이트웨이를 통해 외부 인터넷 구간으로 통신할 수 있는 대상은 퍼블릭 IP를 사용하는 퍼블릭 서브넷 내의 자원입니다.
  • 이러한 퍼블릭 서브넷은 자신의 라우팅 테이블에 외부 인터넷 구간으로 나가는 타깃을 인터넷 게이트웨이로 지정해 주어야 합니다.
cat <<EOT > vpc.tf
provider "aws" {
  region  = "ap-northeast-2"
}

resource "aws_vpc" "myvpc" {
  cidr_block       = "10.10.0.0/16"
  enable_dns_support   = true
  enable_dns_hostnames = true

  tags = {
    Name = "t101-study"
  }
}

resource "aws_subnet" "mysubnet1" {
  vpc_id     = aws_vpc.myvpc.id
  cidr_block = "10.10.1.0/24"

  availability_zone = "ap-northeast-2a"

  tags = {
    Name = "t101-subnet1"
  }
}

resource "aws_subnet" "mysubnet2" {
  vpc_id     = aws_vpc.myvpc.id
  cidr_block = "10.10.2.0/24"

  availability_zone = "ap-northeast-2c"

  tags = {
    Name = "t101-subnet2"
  }
}


resource "aws_internet_gateway" "myigw" {
  vpc_id = aws_vpc.myvpc.id

  tags = {
    Name = "t101-igw"
  }
}

output "aws_vpc_id" {
  value = aws_vpc.myvpc.id
}
EOT
  • terraform apply 전

  • terraform apply 후


4. 라우팅 테이블

  • NAT 게이트웨이도 인터넷 게이트웨이처럼 외부 인터넷 구간과 연결하는 관문 역할을 하고 있습니다.
  • NAT는 네트워크 주소 즉, IP 주소를 변환해 주는 기술입니다.
  • 인터넷 구간은 공공 네트워크 구간으로 퍼블릭 IP를 통해 통신이 이루어집니다.
  • 프라이빗 IP는 인터넷 구간으로 넘어올 수가 없는데, 이때 NAT 게이트웨이가 프라이빗 IP를 퍼블릭 IP로 변환하여 통신을 도울 수 있습니다.
  • 인터넷 게이트웨이는 퍼블릭 서브넷의 외부 인터넷 구간을 연결하는 반면에 NAT 게이트웨이는 프라이빗 서브넷 인스턴스의 프라이빗 IP를 퍼블릭 IP로 변환하여 외부 인터넷 구간으로 연결할 수 있습니다.
  • NAT 게이트웨이는 한쪽 방향으로만 동작합니다.
cat <<EOT > vpc.tf
provider "aws" {
  region  = "ap-northeast-2"
}

resource "aws_vpc" "myvpc" {
  cidr_block       = "10.10.0.0/16"
  enable_dns_support   = true
  enable_dns_hostnames = true

  tags = {
    Name = "t101-study"
  }
}

resource "aws_subnet" "mysubnet1" {
  vpc_id     = aws_vpc.myvpc.id
  cidr_block = "10.10.1.0/24"

  availability_zone = "ap-northeast-2a"

  tags = {
    Name = "t101-subnet1"
  }
}

resource "aws_subnet" "mysubnet2" {
  vpc_id     = aws_vpc.myvpc.id
  cidr_block = "10.10.2.0/24"

  availability_zone = "ap-northeast-2c"

  tags = {
    Name = "t101-subnet2"
  }
}


resource "aws_internet_gateway" "myigw" {
  vpc_id = aws_vpc.myvpc.id

  tags = {
    Name = "t101-igw"
  }
}

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

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

resource "aws_route_table_association" "myrtassociation1" {
  subnet_id      = aws_subnet.mysubnet1.id
  route_table_id = aws_route_table.myrt.id
}

resource "aws_route_table_association" "myrtassociation2" {
  subnet_id      = aws_subnet.mysubnet2.id
  route_table_id = aws_route_table.myrt.id
}

resource "aws_route" "mydefaultroute" {
  route_table_id         = aws_route_table.myrt.id
  destination_cidr_block = "0.0.0.0/0"
  gateway_id             = aws_internet_gateway.myigw.id
}

output "aws_vpc_id" {
  value = aws_vpc.myvpc.id
}
EOT
  • 리소스 Map
  • subnet 1, subnet 2 명시적 연결

  • aws ec2 describe-route-tables 명령어 
# 라우팅 테이블 확인
#aws ec2 describe-route-tables --filters 'Name=tag:Name,Values=t101-rt' --query 'RouteTables[].Associations[].SubnetId'
aws ec2 describe-route-tables --filters 'Name=tag:Name,Values=t101-rt' --output table
  • 라우팅 테이블 확인


5. 최종 종합

  • 다음 리소스 맵에 ec2와 보안그룹을 배포해봅니다.
cat <<EOT > sg.tf
resource "aws_security_group" "mysg" {
  vpc_id      = aws_vpc.myvpc.id
  name        = "T101 SG"
  description = "T101 Study SG"
}

resource "aws_security_group_rule" "mysginbound" {
  type              = "ingress"
  from_port         = 0
  to_port           = 80
  protocol          = "tcp"
  cidr_blocks       = ["0.0.0.0/0"]
  security_group_id = aws_security_group.mysg.id
}

resource "aws_security_group_rule" "mysgoutbound" {
  type              = "egress"
  from_port         = 0
  to_port           = 0
  protocol          = "-1"
  cidr_blocks       = ["0.0.0.0/0"]
  security_group_id = aws_security_group.mysg.id
}
EOT
cat <<EOT > ec2.tf
data "aws_ami" "my_amazonlinux2" {
  most_recent = true
  filter {
    name   = "owner-alias"
    values = ["amazon"]
  }

  filter {
    name   = "name"
    values = ["amzn2-ami-hvm-*-x86_64-ebs"]
  }

  owners = ["amazon"]
}

resource "aws_instance" "myec2" {

  depends_on = [
    aws_internet_gateway.myigw
  ]

  ami                         = data.aws_ami.my_amazonlinux2.id
  associate_public_ip_address = true
  instance_type               = "t2.micro"
  vpc_security_group_ids      = ["\${aws_security_group.mysg.id}"]
  subnet_id                   = aws_subnet.mysubnet1.id

  user_data = <<-EOF
              #!/bin/bash
              wget https://busybox.net/downloads/binaries/1.31.0-defconfig-multiarch-musl/busybox-x86_64
              mv busybox-x86_64 busybox
              chmod +x busybox
              RZAZ=\$(curl http://169.254.169.254/latest/meta-data/placement/availability-zone-id)
              IID=\$(curl 169.254.169.254/latest/meta-data/instance-id)
              LIP=\$(curl 169.254.169.254/latest/meta-data/local-ipv4)
              echo "<h1>RegionAz(\$RZAZ) : Instance ID(\$IID) : Private IP(\$LIP) : Web Server</h1>" > index.html
              nohup ./busybox httpd -f -p 80 &
              EOF

  user_data_replace_on_change = true

  tags = {
    Name = "HallsHolicker-jjang"
  }
}

output "myec2_public_ip" {
  value       = aws_instance.myec2.public_ip
  description = "The public IP of the Instance"
}
EOT
  • apply후 확인 
terraform plan && terraform apply -auto-approve
Outputs:
myec2_public_ip = "3.34.133.12"

terraform state list
data.aws_ami.my_amazonlinux2
aws_instance.myec2
...

# 출력된 EC2 퍼블릭IP로 cul 접속 확인
terraform output -raw myec2_public_ip
3.34.133.12

MYIP=$(terraform output -raw myec2_public_ip)
while true; do curl --connect-timeout 1  http://$MYIP/ ; echo "------------------------------"; date; sleep 1; done
  • curl 확인


여기까지 vpc와 Subnet, IGW , Routing Table을 테라폼으로 만들어보고 

ec2 와 sg 를 만들어서 통신 테스트를 진행 하였다! 

다음은 2주차에 배운 반복문을 공부해보도록 하자.