Terraform - 웹 서버 구축(EC2, Nginx)

Bobby·2023년 4월 10일
0

DEV OPS

목록 보기
5/5
post-custom-banner

** AWS를 사용하였음.

Infrastructure as Code(IaC)

클라우드 환경에서 서비스가 점점 커짐에 따라 관리해야 하는 서버가 늘어난다.
설정 변경이 될 때마다 aws 콘솔에 들어가서 하나씩 수정한다..
관리해야 하는 서버가 수십대라면? 리전이나 계정을 옮긴다면..?

이제 인프라도 코드로 관리하자!

  • 시스템 변경 및 구성에 대해 일관되게 반복되는 과정을 코드를 통해 자동화하면 빠르게 변경/구성할 수 있다.
  • 수동으로 구성했을 때 누락하거나 잘못 설정하는 등의 실수를 없앨 수 있다.

흔하게 사용되는 Terraform 에 대해서 알아보자.


Terraform

  • 테라폼(Terraform)은 HashiCorp가 개발한 오픈 소스 코드형 인프라스트럭처이다.
  • 사용자는 HCL(HashiCorp Configuration Language)이라는 선언형 구성 언어나 선택적으로 JSON을 사용하여 데이터 센터 인프라스트럭처를 정의하고 제공한다.

Terraform 설치

# 테라폼 버전 관리 도구
brew install tfenv

# 버전 확인
tfenv --version

# 테라폼 설치 - version을 명시하지 않으면 최신 버전 설치
tfenv install {version}

# 여러 버전을 사용 중일때 사용 버전 지정
tfenv use {version}
  • 테라폼은 .tf 로 끝나는 확장자를 가진 파일로 구성된다.
  • 테라폼을 실행하는 내부에 있는 .tf 파일들을 실행한다.

Terraform 주요 명령어

# 초기화
terraform init
# 실행 계획
terraform plan
# 적용
terraform apply
# 삭제
terraform destroy

예제

간단하게 EC2에 nginx를 띄워보자.

  • 가독성 및 공통 사용을 위해서 파일을 나눠서 작성했다.

사용 준비

terraform 을 사용하기 위해 IAM 계정을 하나 생성한다.

  • 어드민 권한을 주자.

  • access key 생성


  • secret key는 다시 볼 수 없으니 잘 저장해 두자.

aws cli 설치

brew install awscli

aws 설정

aws configure
  • 위에서 생성한 access key, secret key 를 입력하자.
  • ~/.aws 디렉토리 아래에 config, credentials 아래에 파일이 저장되고 aws cli를 사용할 때 해당 권한, 설정을 가지고 사용한다.

1. provider.tf

  • 어느 클라우드 서비스를 사용할 지 지정하는 부분이다.

provider.tf

  • 리전과 가용영역을 지정.
provider "aws" {
  region = "ap-northeast-3"
}

# 사용 가능한 가용영역 
data "aws_availability_zones" "available" {
  state = "available"
}

2. network.tf

  • VPC, subnet 등 네트워크 설정

  • resource 뒤에는 aws의 서비스 명을 적고 그 다음에는 코드에서 사용할 해당 리소스의 이름을 적는다.


resource "aws_vpc" "vpc" {
  cidr_block           = "10.0.0.0/16"

  enable_dns_hostnames = true
  enable_dns_support   = true

  tags = {
    "Name" = "vpc"
  }
}

resource "aws_subnet" "subnet" {
  vpc_id            = aws_vpc.vpc.id
  cidr_block        = "10.0.1.0/24"

  tags = {
    "Name" = "subnet"
  }
}

resource "aws_internet_gateway" "igw" {
  vpc_id = aws_vpc.vpc.id

  tags = {
    Name = "igw"
  }
}

resource "aws_route_table" "rt" {
  vpc_id = aws_vpc.vpc.id

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

  tags = {
    Name = "rt"
  }
}

resource "aws_route_table_association" "rta" {
  subnet_id      = aws_subnet.subnet.id
  route_table_id = aws_route_table.rt.id
}

3. sg.tf

  • 시큐리티 그룹 생성
  • ingress : 인바운드 트래픽 설정
    • http 접근을 위해 80 포트와 ssh 접근을 위한 22 포트를 열었다.
  • egress : 아웃바운드 트래픽 설정
resource "aws_security_group" "sg" {
        name = "sg"
        vpc_id      = aws_vpc.vpc.id

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

        ingress {
                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" = "test-sg"
 	}	
}

4. privatekey.tf

  • ssh 접근을 위해 pem 키를 생성하고 등록한다.
resource "tls_private_key" "pk" {
  algorithm = "RSA"
  rsa_bits  = 4096
}

resource "aws_key_pair" "kp" {
  key_name   = "terraform"
  public_key = tls_private_key.pk.public_key_openssh
}

resource "local_file" "ssh_key" {
  filename = "${aws_key_pair.kp.key_name}.pem"
  content = tls_private_key.pk.private_key_pem
}

5. web.tf

  • 웹서버 구동을 위한 EC2 생성
  • nginx를 도커로 실행할 예정이므로 도커 설치 및 nginx를 실행하는 스크립트를 원격지에 복사하여 실행하도록 한다.

init.sh

#/bin/bash

sudo yum update -y
sudo yum install docker -y
sudo systemctl start docker
sudo usermod -aG docker ec2-user
sudo systemctl enable docker
sudo docker run --name=nginx -d -p 80:80 nginx

인스턴스의 ami 값은 리전마다 다를 수 있으니 주의!

  • 인스턴스 생성할 때 볼 수 있다.

web.tf

resource "aws_instance" "web" {
	ami		                    = "ami-0f19932fc7b89784a"
	instance_type	            = "t3.small"
	subnet_id	                = aws_subnet.subnet.id
	vpc_security_group_ids      = [aws_security_group.sg.id]
	key_name	                = aws_key_pair.kp.key_name	
	associate_public_ip_address = true # public ip 생성
 
    # 로컬에 있는 파일을 원격지로 복사
	provisioner "file" {
	source = "./script/init.sh"
		destination = "/home/ec2-user/init.sh"

		connection {
			type        = "ssh"
			host        = self.public_ip
			user        = "ec2-user"
			private_key = tls_private_key.pk.private_key_pem
		}
 	}

    # 원격지에 커맨드 실행
  	provisioner "remote-exec" {
    		inline = [
      			"chmod +x /home/ec2-user/init.sh",
      			"/home/ec2-user/init.sh"
    		]

    		connection {
      			type        = "ssh"
      			host        = self.public_ip
      			user        = "ec2-user"
      			private_key = tls_private_key.pk.private_key_pem
    		}
  	}

	tags = {
		Name = "web-server" 
	}
}


# 테라폼 실행 후 출력 값
output "web_public_ip" {
  value = self.public_ip
}

실행

초기화

terraform init

  • 작성한 테라폼 코드에 필요한 모듈들을 설치한다.

실행 계획

terraform plan
  • 코드에 문제가 있는지 실행해준다. 실제로 생성되는 것은 아니고 실행 계획을 세워준다. 오류가 발생하지 않아도 실제로 적용했을 때 오류가 발생 할 수 있다!

적용

  • -auto-approve 옵션은 실행여부를 묻지 않고 바로 실행한다.
terraform apply -auto-approve
  • 완료 후 public ip 값을 출력해준다.
  • pem key 생성

접속

  • 출력된 ip로 웹서버를 접근해보자.

ssh 접속

ssh -i terraform.pem ec2-user@15.152.69.231
  • init.sh 파일이 복사되어 실행 된 것을 확인 할 수 있다.
  • 도커로 nginx가 실행 되었다.

종료

테스트 용도라면 반드시 종료 시켜주자.

  • -auto-approve 옵션은 실행여부를 묻지 않고 바로 실행한다.
terraform destroy -auto-approve

인프라 구성 확인

EC2

VPC

서브넷

보안그룹


코드

profile
물흐르듯 개발하다 대박나기
post-custom-banner

0개의 댓글