Terraform으로 AWS EC2 생성하기

salgu·2023년 4월 1일
0

terraform

목록 보기
1/1
post-thumbnail

AWS 세팅


AWS IAM 사용자 생성

테라폼에서 AWS와 연동하기 위해서 사용할 IAM 사용자를 AdministratorAccess 정책을 연동하여 생성해줍니다.

AWS access key 발급

생성한 IAM 사용자에서 access key와 secret access key를 발급한 후 잘 저장해줍니다.

AWS configure

테라폼에서 사용할 tf 파일에 IAM key들이 노출이 되면 안되기 때문에 aws configure를 이용해 민감한 정보를 로컬에서 받아올 수 있게

$ aws configure

명령어로 aws key를 등록해줍니다.

aws-cli 설치 문서
https://docs.aws.amazon.com/ko_kr/cli/latest/userguide/getting-started-install.html



.tf 파일 작성


Terraform EC2 생성 (cicd.tf)

ec2.tf

provider "aws" {
  region     = "ap-northeast-2"
}

resource "aws_instance" "cicd" {
  ami           = "ami-03221589fd7c8f183"
  instance_type = "t2.micro"
  key_name = aws_key_pair.cicd_make_keypair.key_name
  vpc_security_group_ids = [aws_security_group.cicd_sg.id]
  associate_public_ip_address = true
  
  tags = {
    Name = "cicd"
  }
}

EC2를 생성할 수 있는 tf파일 입니다.

  • provider "aws" : aws provider를 사용하겠다는 의미
  • region : resource를 생성할 리전
  • resource "aws_instance" "cicd" : 생성할 resource의 종류, 인스턴스 이름
  • ami : 인스턴스에서 사용할 이미지 id
  • instance_type : 인스턴스의 유형
  • key_name : 인스턴스 ssh접속에 사용할 private key (.pem)
  • vpc_security_group_ids : 인스턴스에 적용할 보안그룹
  • associate_public_ip_address : public IP 할당

Terraform RSA 개인 키 생성 (private_key.tf)

resource "tls_private_key" "cicd_make_key" {
  algorithm = "RSA"
  rsa_bits  = 4096
}

resource "aws_key_pair" "cicd_make_keypair" {
  key_name   = "cicd_key"
  public_key = tls_private_key.cicd_make_key.public_key_openssh
}

resource "local_file" "cicd_downloads_key" {
  filename = "cicd_key.pem"
  content  = tls_private_key.cicd_make_key.private_key_pem
}

tls_private_key

tls_private_key 리소스를 사용하여 "cicd_make_key" 라는 이름의 RSA 알고리즘 및 2048 비트의 개인 키를 생성합니다.
이렇게 생성된 개인 키는 tls_private_key.cicd_make_key.private_key_pem 값으로 참조할 수 있습니다.

aws_key_pair

aws_key_pair 리소스를 사용하여 AWS EC2 Key Pair를 생성합니다.
tls_private_key 단계에서 생성된 개인 키를 사용하여 공개 키를 생성합니다.
이렇게 생성된 AWS EC2 Key Pair는 aws_key_pair.cicd_make_keypair.key_name 값으로 참조할 수 있습니다.

local_file

local_file 리소스를 사용하여 개인 키를 로컬 파일로 저장합니다.
aws_key_pair 단계에서 생성된 AWS EC2 Key Pair의 이름을 파일 이름으로 사용하고, 개인 키를 PEM 형식으로 인코딩하여 저장합니다.
이렇게 생성된 파일은 cicd_key.pem 파일 이름으로 저장됩니다.

Terraform EC2 보안그룹 생성 (security.tf)

resource "aws_security_group" "cicd_sg" {
  name_prefix = "cicd-sg"
  vpc_id = aws_vpc.cicd_vpc.id
}

resource "aws_security_group_rule" "cicd_sg_ingress_ssh" {
  type        = "ingress"
  from_port   = 22
  to_port     = 22
  protocol    = "tcp"
  cidr_blocks = ["{허용할 CIDR}"]
  security_group_id = aws_security_group.cicd_sg.id
}

resource "aws_security_group_rule" "cicd_sg_ingress_https" {
  type        = "ingress"
  from_port   = 443
  to_port     = 443
  protocol    = "tcp"
  cidr_blocks = ["{허용할 CIDR}"]
  security_group_id = aws_security_group.cicd_sg.id
}

resource "aws_security_group_rule" "cicd_sg_egress_all" {
  type             = "egress"
  from_port        = 0
  to_port          = 0
  protocol         = "-1"
  cidr_blocks      = ["{허용할 CIDR}"]
  security_group_id = aws_security_group.cicd_sg.id
}

인바운드 규칙을 포함하는 새 보안 그룹을 만들고 aws_security_group_rule 리소스를 사용하여 SSH 액세스를 허용하는 규칙을 추가합니다.

ec2.tf

vpc_security_group_ids = [aws_security_group.cicd_sg.id]

aws_instance 리소스의 vpc_security_group_ids 매개 변수를 사용하여 EC2 인스턴스가 위에서 만든 보안 그룹을 사용하도록 구성합니다.



Terraform 실행


설치

테라폼 설치 블로그 를 참고하여 각 실행환경에 맞게 테라폼을 설치해줍니다.

Terraform init

상태 저장을 위한 .tfstate 파일을 생성합니다.
여기에는 가장 마지막에 적용한 테라폼 내역이 저장됩니다.

Terraform Plan

정의한 코드가 어떤 인프라를 만들게 되는지 미리 예측 결과를 보여줍니다.
terraform apply 하기 전 실행하여 결과를 예측한 뒤 실행하면 오류의 확률을 줄여줍니다.

Terraform apply

실제로 인프라를 배포하기 위한 명령어입니다. apply를 완료하면, AWS 상에 실제로 해당 인프라가 생성되고 작업 결과가 backend의 .tfstate 파일에 저장됩니다.
해당 결과는 local의 .terraform 파일에도 저장됩니다



결과


$ terraform apply

명령어를 실행하여 작성했던 .tf 파일들을 읽어 ec2가 생성이 됩니다.


ec2 console에 접속하여 정상적으로 인스턴스가 생성이 됐는지 확인합니다.

$ ssh -i ./cicd_key.pem ec2-user@3.34.1.167

생성했던 pem키를 이용해 ssh로 접속하여 정상적으로 인스턴스가 생성되고 작동하는지 확인하면 마무리됩니다.



인스턴스 한개 더 생성해서 같은 Subnet으로 묶기


VPC, Subnet 작성 (subnet.tf)

resource "aws_vpc" "cicd_vpc" {
  cidr_block = "10.0.0.0/16"
  
  tags = {
    Name = "cicd-vpc"
  }
}

resource "aws_subnet" "cicd_subnet" {
  cidr_block = "10.0.1.0/24"
  vpc_id     = aws_vpc.cicd_vpc.id
  
  tags = {
    Name = "cicd-subnet"
  }
}

VPC와 Subnet을 작성해주면 해당 VPC와 Subnet이 생성됩니다.
그리고 해당 VPC를 모두 참조해야 하므로 변경해보겠습니다.

인스턴스, 보안그룹, 라우트 테이블 VPC, Subnet 참조

인스턴스 (cicd.tf)

provider "aws" {
  region     = "ap-northeast-2"
}

resource "aws_instance" "cicd" {
  ami           = "ami-03221589fd7c8f183"
  instance_type = "t3.micro"
  key_name = aws_key_pair.cicd_make_keypair.key_name  
  vpc_security_group_ids = [aws_security_group.cicd_sg.id]
  subnet_id = aws_subnet.cicd_subnet.id
  # availability_zone = "ap-northeast-2a"
  associate_public_ip_address = true

  tags = {
    Name = "cicd"
  }
}

Subnet으로 묶을 인스턴스에 subnet_id = aws_subnet.cicd_subnet.id 속성을 추가해줍니다.

인스턴스 생성 resource (application.tf)

resource "aws_instance" "application" {
  ami           = "ami-03221589fd7c8f183"
  instance_type = "t3.micro"
  key_name = aws_key_pair.cicd_make_keypair.key_name  
  vpc_security_group_ids = [aws_security_group.cicd_sg.id]
  subnet_id = aws_subnet.cicd_subnet.id
  # availability_zone = "ap-northeast-2a"

  tags = {
    Name = "application"
  }
}

Subnet으로 묶을 인스턴스에 subnet_id = aws_subnet.cicd_subnet.id 속성을 추가해서 새로운 인스턴스 resource를 작성해줍니다.

보안그룹에 VPC 연동

resource "aws_security_group" "cicd_sg" {
  name_prefix = "cicd-sg"
  vpc_id = aws_vpc.cicd_vpc.id
}

보안그룹에도 vpc_id = aws_vpc.cicd_vpc.id를 참조해줍니다.

인터넷 게이트웨이, Route table 생성 (route.tf)

resource "aws_internet_gateway" "cicd_igw" {
  vpc_id = aws_vpc.cicd_vpc.id
  
  tags = {
    Name = "cicd-igw"
  }
}

resource "aws_route_table" "cicd_rt" {
  vpc_id = aws_vpc.cicd_vpc.id
  
  route {
    cidr_block = "0.0.0.0/0"
    gateway_id = aws_internet_gateway.cicd_igw.id
  }
  
  tags = {
    Name = "cicd-rt"
  }
}

resource "aws_route_table_association" "cicd_rta" {
  subnet_id      = aws_subnet.cicd_subnet.id
  route_table_id = aws_route_table.cicd_rt.id
}

Subnet으로 따로 묶었기 때문에 ssh 접속 등 되지 않습니다.
vpc_id = aws_vpc.cicd_vpc.id VPC 또한 참조해줍니다.

aws_internet_gateway 리소스는 인터넷 게이트웨이를 생성하고
aws_route_table 리소스는 VPC의 라우팅 테이블을 업데이트합니다. 마지막으로 aws_route_table_association 리소스는 서브넷과 라우팅 테이블을 연결합니다.

같은 Subnet 통신 간 내부통신 보안그룹 열기 (sg.tf)

resource "aws_security_group_rule" "cicd_sg_ingress_internal" {
  type               = "ingress"
  from_port          = 0
  to_port            = 0
  protocol           = "-1"
  source_security_group_id = aws_security_group.cicd_sg.id
  security_group_id  = aws_security_group.cicd_sg.id
}

해당 보안그룹은 같은 보안 그룹에 속한 인스턴스끼리는 모든 포트에 대해 서로 통신이 가능하게 해줍니다.

  • protocol = "-1"은 모든 프로토콜을 의미함





github code : https://github.com/salgu1998/cicd

reference :

profile
https://github.com/leeeesanggyu, leeeesanggyu@gmail.com

0개의 댓글

관련 채용 정보