본문 바로가기
사이드 프로젝트

[CI/CD 프로젝트] Terraform을 사용하여 bastion 서버 생성하기

by 간장공장공차장 2024. 11. 19.
반응형

테라폼이란?

  • 테라폼은 HashiCorp에서 개발한 IaC(Infrastructure as a Code)도구이다.
  • 클라우드 및 온프레미스 리소스를 파일로 명시하여 인프라를 선언적으로 관리할 수 있다.
    • 이러한 구성 파일은 버전 관리, 재사용 및 공유가 가능하여 관리가 용이하다.
  • 일관된 워크플로우를 사용하여 인프라의 전체 수명 주기 동안 프로비저닝 및 관리할 수 있다.
  • 컴퓨팅, 스토리지, 네트워킹과 같은 저수준 구성 요소부터 애플리케이션과 같은 고수준 구성 요소까지 관리 가능하다.
  •  

테라폼 용어

  • Provider
    Terraform이 관리할 수 있는 리소스 유형 및/또는 데이터 소스 세트를 추가 ex. AWS
  • Resources
  • 리소스란 특정 Provider가 제공해주는 조작 가능한 대상의 최소 단위 ex. aws_instance
  • HCL
    Terraform 에서 사용하는 언어

How to Use Provider

프로바이더 선언은 아래와 같이 진행한다.

Provider를 사용하기 위해서는 아래 두 파일이 필요하다.

  • Provider Requirements : "어떤 제공자를 설치하고 사용할지"에 대한 정보이다. Terraform이 이 정보를 기반으로 필요한 제공자를 다운로드하고 설치할 수 있다.
terraform {
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 4.0"
    }
  }

  required_version = ">= 1.0.0"
}
  • Provider Configuration : "어떤 방식으로 그 제공자를 사용할지"를 설정한다. 이때 자격 증명이나 리전과 같은 구체적인 설정이 이루어진다.
provider "aws" {
  access_key = var.access_key
  secret_key = var.secret_key
  region     = "ap-northeast-2"
}

variable "access_key" {}
variable "secret_key" {}

변수 사용하기

GitOps 방식에서는 보안을 높이기 위해 credentials 정보는 따로 명시하는 것이 바람직하다.

tfvars를 사용하여 민감 정보를 명시하고, .gitignore에 포함하도록 한다.

  • .tf 파일에서 변수 정의하기
### 변수 명 정의
variable "access_key" {}
variable "secret_key" {}

variable "image_id" {
  type = string
}
  • .tfvars 파일에서 변수 실제 값 명시하기(변수 값들을 별도로 정의하여 관리할 때 사용된다.)
image_id = "ami-064c81ce3a290fde1"
access_key = "<access_key>"
secret_key = "<secret_key>"

실습

1. 환경 생성

먼저, 로컬에서 테라폼을 설치 후, 정상적으로 설치되었는지 확인한다. 별도 버전을 명시하지 않았으므로 최신버전이 설치된다. 24/10/1 기준으로 v1.5.7버전이 설치되었다.

 

다음으로, 프로젝트를 위한 폴더/파일 생성한다.

➜  practice git:(main) ✗ tree
.
└── web_infra
    ├── provider.tf
    ├── terraform.tfvars
    └── web_infra.tf

2 directories, 3 files

위 이론편에서 언급한 바와 같이 provider를 이용하고자 한다면 provider requirements와 provider configuration 파일이 있어야 한다.

다만, provider requirements는 Terraform은 사용되는 provider 블록을 기반으로 필요한 provider를 자동으로 추론하고 다운로드할 수 있으므로, 이 실습에서는 생략하고 configuration만 명시하도록 한다.(비권장)

2. Provider 설정

GitOps 방식의 경우 보안을 위해 credentials 정보를 관리해주는 것이 반드시 필요하다.

이를 위해서 중요한 정보는 terraform.vartf로 구분하고, gitignore로 넣어주어 진행한다.

terraform.tfvars
access_key = "<access_key>"
secret_key = "<secret_key>"
provider.tf
provider "aws" {
  access_key = var.access_key
  secret_key = var.secret_key
  region = "ap-northeast-2"
}

variable "access_key" {}
variable "secret_key" {}

terraform init 을 통해 프로젝트에서 사용하는 Terraform 모듈과 Provider를 초기화합니다.

terraform init 

아래와 같이 AWS Provider가 설치된 것을 볼 수 있다.

3. EC2 접근을 위한 Key 설정

EC2를 생성해야하기 떄문에 EC2에서 사용할 공개키가 필요하다.

보통 EC2를 생성할 때 pem키를 다운 받는데 이것이 Private Key이고, EC2에 설정되는 키는 Public Key이다.

이미 사용하고 있는 pem파일이 있어 따로 공개키는 생성하지 않고 진행한다.

공개키가 필요한 경우 아래 명령어로 생성하도록 한다.

### 공개키 추출
ssh-keygen -t rsa -b 4096 -C "your_email@example.com"

결과로 ssh-rsa . . . 와 같은 값이 나오는데, 이것을 사용하면 된다.

  • 공개키를 사용하는 경우
web_infra.tf
resource "aws_key_pair" "web_admin" {
  key_name = "web_admin"
  public_key = file("~/.ssh/web_admin.pub")
}
  • 기존 키를 사용하는 경우
web_infra.tf
data "aws_key_pair" "existing_key" {
  key_name = "ssh_key"
}

공개키를 생성하였다면, 어떤 변경사항이 생길 지를 확인한다.

terraform plan

 

이 실습에서는 기존 키를 사용하기 때문에 apply는 생략하고 진행한다.

 

❖ 참고

  • resource
    • 정의: resource 블록은 Terraform을 사용하여 생성, 수정 또는 삭제할 수 있는 AWS 리소스를 정의한다.
    • 사용 목적: 실제 인프라를 생성하거나 관리할 때 사용된다. 예를 들어, EC2 인스턴스, S3 버킷, 보안 그룹 등이 여기에 해당한다.
    • 상태 관리: Terraform은 리소스를 생성하면 상태 파일에 그 정보를 저장하고, 이후 변경 사항을 추적하여 필요한 작업을 수행한다.
  • data
    • 정의: data 블록은 Terraform이 이미 존재하는 리소스의 정보를 읽어오는 데 사용된다.
    • 사용 목적: 기존 리소스의 속성이나 정보를 조회할 때 사용됩니다. 새로운 리소스를 생성하지 않지만, 이미 존재하는 리소스에 대한 정보(예: IP 주소, ARN, 키 페어 등)를 가져올 수 있다.
    • 상태 관리: data 블록은 Terraform 상태 파일에 영향을 주지 않으며, 실제 리소스를 관리하지 않습니다. 단순히 조회만 수행한다.

4. EC2에 적용되는 SG 생성

sg는 terraform을 통해서 생성해보겠다.

web_infra.tf
resource "aws_security_group" "ssh_sg" {
  name = "allow_ssh_from_all"
  description = "Allow SSH port from all"
  ingress {
    from_port = 22
    to_port = 22
    protocol = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  }
}
$ terraform plan 

$ terraform apply 

하게되면 오류가 나는 것을 알 수 있다. VPC를 설정하지 않았기 때문이다..

EC2를 생성할 vpc와 subnet을 설정한다.

실제 값 : tfvars 로 관리

terraform.tfvars 끝에 아래의 값을 추가해준다.

terraform.tfvars 
vpc_id = "vpc-id"
subnet_id = "subnet-id"

web_infra.tf에는 변수 값를 가져올 수 있도록 변수를 설정해준다.

web_infra.tf
variable "vpc_id" {
  description = "The ID of the VPC"
}

variable "subnet_id" {
  description = "The ID of the subnet where the instance will be launched"
}

설정 후에 생성을 위해 apply 해주면, 정상적으로 생성되는 것을 볼 수 있다.

$ terraform apply 

aws 콘솔에서 정상적으로 리소스가 생성된 것을 확인할 수 있다.

위의 ssh_sg 보안 그룹은 22번 포트에 대한 inbound만 허용하고 있기 때문에 outbound까지 허용하는 보안그룹을 생성해준다.

web_infra.tf
resource "aws_security_group" "ssh_outbound" {
  vpc_id = var.vpc_id
  name = "allow_all_outbound"
  description = "Allow All Outbound"
  egress {
    from_port   = 0
    to_port     = 0
    protocol    = "-1"
    cidr_blocks = ["0.0.0.0/0"]
  }
}

같은 방법으로 plan, apply 를 적용해준다.

5. EC2 생성

web_infra.tf
resource "aws_instance" "ssh-web" {
  vpc_id = var.vpc_id
  ami = "ami-0e18fe6ecdad223e5" # amzn-linux-2023
  instance_type = "t2.micro"
  key_name = data.aws_key_pair.existing_key.key_name
  vpc_security_group_ids = [
    aws_security_group.ssh_sg.id,
    aws_security_group.ssh_outbound.id
  ]
  subnet_id = var.subnet_id
  associate_public_ip_address = true
}
$ terraform plan

$ terraform apply

아래의 명령어를 통해서 생성된 EC2의 ip를 확인하여 접속해본다.

$ terraform console
> aws_instance.web.public_ip

$ ssh -i ssh_key.pem ec2-user@public_ip

출처

https://developer.hashicorp.com/terraform/intro

https://www.44bits.io/ko/post/terraform_introduction_infrastrucute_as_code

반응형