본문 바로가기
IT/Terraform

Terraform - 웹 클러스터 및 로드밸런서 배포, 상태 관리, 환경 격리, 모듈

by 스마일엔지니어 2025. 2. 4.

웹 서버 클러스터 배포

: 하나의 서버가 죽더라도 다른 서버가 실행할 수 있게끔  →  downtime 최소화, 서비스 quality ↑

*ASG (Auto Scaling Group) 이용 // Launch Configuration 보단 Template 사용 권장하나 이번에 configuration 사용해보기로!

 

 

main.tf에서 resource 부분 삭제하고 해당 부분 업데이트

 

 

auto scaling group까지 구성 + lifecycle (create_before_destroy=true -> 무한 루핑 방지, 리소스 낭비 X)하여 전체 main.tf를 업데이트 한다.

 

 

public ip 에 대한 에러가 뜬다. 왜냐하면 현재 ec2에 대한 auto scaling group을 실행할 것이기 때문에

출력변수 부분(output)인 인스턴스는 사용할 필요가 없으므로 삭제해줘야 한다. 추가적으로 입력 변수 서버 포트 부분에서 default = 8080 을 추가해주었다.

 

 

추가적으로 가용영역과 서브넷이 설정되어있지 않았다는 오류가 생겼기에 이에 대한 정보도 구성해줘야 한다.

 

 

 

첫 번째 사진에서 vpc는 디폴트로 설정해주고 추가적으로 앞서 auto scaling group에서

'vpc_zone_identifier = data.aws_subnets.default.ids' 를 넣어서 서브넷을 참조할 수 있도록 해준다.

 

 

실행이 정상적으로 되고 AWS EC2 인스턴스를 보면 asg 인스턴스 2개가 생성된 것을 볼 수 있다.

 

 

로드 밸런서 배포

 

- 로드 밸런서의 구성

리스너: 어떤 포트를 설정할 것인지

*리스너 규칙: 리스너로 들어오는 요청을 받아 특정 경로(예: /foo 및 /bar ) 또는 호스트 이름(예: foo.example.com 및 bar.exam ple.com )과 일치하는 요청을 특정 대상 그룹에 보내야 한다.

타겟그룹: 어떤 대상에게 전달할 것인지

 

- 로드밸런서 유형

어플리케이션 로드밸런서 (L7 Load Balancer)

네트워크 로드밸런서 (L4 Load Balancer)

클래식 로드밸런서 (Classic Load Balancer)

 

 

*전체적인 구성도

 

 

*main.tf 파일 업데이트

 

로드밸런서 형성

 

 

로드밸런서에 대한 리스너 구성 (80번 포트인 HTTP 이용)

 

 

로드밸런서에 대한 보안그룹 형성

protocol = "-1" 은 모든 프로토콜에 대해 열겠다라는 의미

 

 

타겟그룹 설정

 

 

앞서 ASG Resource란에 타켓그룹 식별할 수 있도록 참조식을 넣어주고 health check type을 설정해둔다.

 

 

리스너 규칙 및 출력 변수인 도메인 네임 설정

 

 

 

정상적으로 실행되는 것을 확인할 수 있다.

 

마지막으로 tfd (terraform destroy --auto-approve) 통해 자원을 반환해주도록 한다.

 

- health check

1. Service Discovery

2. Circuit Breaking: 회로 차단기 (문제가 되는 회로에 대해 차단, 타겟 그룹에 대한 문제를 인식하여 해결하는 기술)

 

 

상태관리

테라폼에서의 상태(tfstate)란?

Terraform을 실행할 때마다 Terraform 상태 파일에 생성된 인프라에 대한 정보가 기록하는 것이다.

=> 상태 파일을 공유할 수 있는 업무 프로세스 만들어주는 것이 매우 중요 !!! // 공유 저장소 필요

 

lock

: 하나의 사용자가 정보/상태를 업데이트하는 동안 다른 사용자가 접근하지 못하게 하는 것

 

무엇보다 공유 저장소는 Private 하게!!! (Amazon S3, Azure Storage, Google Cloud Storagem, Terraform Cloud 등...)

Amazon S3의 경우 lock 기능은 DynamoDB를 통해 지원해준다.

=> S3와 DynamoDB를 만들어서 데이터 저장

 

 

main.tf 편집기 들어가 provider 설정 (이전과는 다른 새로운 main.tf, 새로운 디렉토리에서 해야 함)

 

 

S3 Bucket 이름은 aws 파티션 안에 있는 모든 계정에 있어 유니크하게 만들어줘야 함!!

버켓이름: terraform-state-tjdgns(성훈)-wave 그리고 공백 오류가 생겼어서 공백 있으면 안됨!!

 

 

버켓에 대한 정보를 모두 볼 수 있게끔 하고 암호화 (encryption)

 

 

버켓에 대한 public access 차단

 

 

 

Lock 기능위한 DynamoDB

 

 

 

apply한 결과 정상적으로 결과가 출력되고 해당 이름의 버킷이 생성된 것을 볼 수 있다.

 

 

- 상태 파일 올리기 : Terraform code에 백엔드 구성을 추가해야 한다.

1. 보통 테라폼 코드는 맨위에 작성

2. 백엔드를 새로 구성하는 것이기에 apply 전에 init을 해줘야 한다. (init 하라고 에러가 뜨긴 뜸)

 

 

init을 하고나면 global/ 객체(키)가 생성된다.

 

 

출력 변수 추가

 

테라폼 제한 사항

 

  1. Terraform 코드를 작성하여 S3 버킷과 DynamoDB 테이블을 생성하고 해당 코드를 로컬 백엔드에 전송한다.
  2. Terraform 코드로 돌아가서 새로 생성된 S3 버킷 및 DynamoDB 테이블을 사용하도록 원격 백엔드 구성을 추가하고 terraform init를 실행하여 로컬 상태를 S3에 복사한다.

=> 반드시 먼저 로컬 백엔드를 구성하고 원격 백엔드로 보내야 함!!!

 

S3 버킷과 DynamoDB 테이블을 삭제하려면 이 2단계 프로세스를 반대로 수행해야 한다.

  1. Terraform 코드로 이동하여 백엔드 구성을 제거하고 terraform init를 다시 실행하여 Terraform 상태를 로컬 디스크에 다시 복사한다.
  2. terraform destroy를 실행하여 S3 버킷과 DynamoDB 테이블을 삭제한다.

=> 삭제할 때도 바로 destroy하는 것이 아니라 원격 백엔드에서 로컬 백엔드로 보낸 다음 원격 백엔드를 삭제해야 함!!!

 

 

 

(상태 파일 - Dev, Prod, QA ...) 환경 격리

 

- 작업 공간(workspace)을 통한 격리 

- 파일 레이아웃을 통한 격리 (좀 더 직관적)

 

 

1. 작업 공간(workspace)을 통한 격리

 

storage 디렉토리 내 파일을 workspace-demo 라는 디렉토리를 만들어서 복사

 

 

 

 

그리고 디렉토리를 통째로 복사하다보니 configure 충돌이나서

init할 때 옵션에 -reconfigure을 하여 재구성해준다.

 

 

init 이 제대로 되면

새로운 작업 공간 example1을 생성하고 apply 해준다.

 

 

 

작업공간이 env, global, workspaces-example이 생성되었고 

env - example1

global - s3

workspace-example - terraform.tfstate

각각의 파일들이 존재하여 격리하는 것을 볼 수 있다.

 

 

 

2. 파일 레이아웃(디렉터리 구조)로 격리

 

 

 

 

stage / services / webserver-cluster 안으로 main.tf 이동시키기

 

 

Terragrunt run-all : 일일이 디렉토리마다 apply할 필요없이 여러 폴더에서 동시에 실행

 

 

 

main.tf 다음과 같이 업데이트

 

 

terraform.tf에 s3 백엔드 생성  

 

output.tf에 2개의 출력 변수(address, port) 추가

 

 

 

 

데이터베이스 엔진 버전에 대한 에러가 뜨는데 t2.micro -> t3.micro로 정정해준다.

 

그리고 invalid master user name 에러가 뜨는데 var 참조식에 " " 가 붙었기 때문에 생기는거라 이를 삭제해줘야 한다.

 

아이디 및 비밀번호 정보를 넣어준다.

username: smile9855

password: 1234qwer

 

 

다음과 같이 정상적으로 됐다는 출력결과가 뜬다.

 

 

AWS 상에서 다음과 같은 경로 상에 terraform.tfstate 오브젝트가 있는 것을 볼 수 있다.

 

 

Q. 앞서 destroy하다가 ctrl+c 해서 중지시키다가 다시 했을 때 lock에 관한 에러가 걸리는 이유?

 

 

버킷 상에 lock 파일이 존재하는데 실행하다가 중지시키면 lock파일이 그대로 남아버려서 다시 실행했을 때 다른 사용자로 인식하고 에러를 내버림!! -> -lock=false 옵션을 넣는다.

 

cluster-wave 파일 상 main.tf

 

 

http 응답하는 란에

echo "${data.terraform_remote_state.db.outputs.address}" >> index.html

echo "${data.terraform_remote_state.db.outputs.port}" >> index.html

두 줄을 추가하여 주소와 포트번호를 출력할 수 있게 하고 데이터베이스 구성도 해준다.

그리고 terraform init을 해준다음 apply를 해준다.

 

 

 

init 및 apply 결과까지 정상적으로 나온 것을 확인했다. 

(unable to bucket name 에러가 뜨긴 했지만 버킷 이름 에러 유의하자 !!)

 

 

curl을 통해 

hello world

domain address

port

제대로 출력되는 것을 확인할 수 있다.

 

 

user-data.sh 쉘 스크립트 파일 작성

 

앞서 html 호출 부분에서 address부분과 port 부분을 지우고 쉘 스크립트 파일을 불러올 수 있는 코드를 작성한다.

 

 

apply하여 정상적으로 작동이 됐고 curl한 결과 결과가 동일한 결과가 올바르게 나왔음을 확인할 수 있다.

 

해당 주소에 대하여 http 접속한 결과 hello world, domain address 그리고 port 번호가 나오는 웹이 나온 것을 확인할 수 있다.

 

 

모듈

: 재사용이 가능한 코드들을 모아줌! (동일한 모듈의 코드를 재사용)

 

- 테라폼의 모듈은 매우 간단!

- 폴더에 있는 모든 Terraform 구성 파일 세트는 모듈

 

root 모듈: terraform apply 실행시키는 모듈

 

 

 

 

stage/service/webserver-cluster 에서 terraform destroy 

 

 

 

terraform-demo 안에 있는 stage 디렉토리를 module이란 디렉토리로 복사

 

 

모듈 내 (module/service/webserver-cluster/main.tf) main.tf에서 공급자 (provider 부분) 제거한다.

공급자는 루트모듈에서만 정의해야한다.

 

 

반대로, stage/service/webserver-cluster/main.tf에서는 공급자를 제외한 나머지 부분을 제거한다.

d + shift + g 아래 행 내용 모두 제거

추가적으로 모듈에 대한 부분을 작성해준다.

 

 

모듈 입력

: 여러 개의 환경에 대해 동일한 인프라를 구성하기 위해  코드를 중복으로 이용 (시험에 나옴,,)

 

 

modules/service/webserver-cluster/variables.tf 파일에서 인스턴스 타입, 최소 및 최대 크기에 대한 구성을 추가

 

 

 

 

modules/service/webserver-cluster/main.tf 에서 보안그룹 변수참조에 대한 부분을 수정 및 remote state 내용 추가

 

 

 

인스턴스 타입 참조하도록 참조식 정정

 

 

 

stage/service/webserver-cluster/main.tf 밑 작성

 

 

apply 실행이 정상적으로 되었다. 

 

'IT > Terraform' 카테고리의 다른 글

Terraform - Final Scenario  (1) 2025.02.06
Terraform - Module, Provisioning  (1) 2025.02.05
Terraform - Baseline  (2) 2025.02.03