Terraform Flexible Deployment Options 으로 MEGATHON 환경 구축하기

김예지
Cloud Villains
Published in
14 min readDec 19, 2023

개요

메가존클라우드는 지난 10월 27일 DNB 고객사분들을 대상으로 Devops Quest 해결 방식 이벤트인 ‘MEGATHON(메가톤)’을 진행하였습니다. 이번 행사는 Devops 도구에 관심이 있지만 사용해 볼 기회가 없었던 개발자 및 엔지니어분들을 위해 다양한 기능들을 마음껏 활용하며 Devops 파이프라인을 구축해볼 수 있는 퀘스트형 이벤트로 개최 되었습니다. Devops 도구로는 Terraform Enterprise 및 Gitlab Ultimate이 제공되었습니다.

본 행사를 위해 저희 Devops product팀은 Terraform FDO(Flexible Deployment Options)를 활용하여 행사에 사용될 Terraform enterprise 환경을 구축하였습니다. Terraform FDO는 올해 9월에 새롭게 런칭 된 기능으로 Docker 또는 Kubernetes 환경에서 Terraform enterprise를 빠른 시간에 설치 및 시작할 수 있는 배포 옵션입니다.

이를 적용하여 이번 메가톤 행사에서는 Amazon EKS(Elastic Kubernetes Service) 환경에 Terraform enterprise를 배포하였습니다. Amazon EKS는 AWS 클라우드에서 Kubernetes를 실행 하는 데 사용 되는 관리형 Kubernetes 서비스 입니다.

본 행사를 진행하는 동안 많은 참가자들이 동 시간대에 코드를 작성하고 배포하는 작업이 이루어졌는데요, Amazon EKS에 Terraform enterprise를 배포함으로써 참가자들의 많은 작업량에도 클러스터의 높은 신뢰성 및 가용성을 보장하도록 구성하였습니다.

본 행사에서 사용된 아키텍처는 다음과 같습니다.

Amazon EKS 환경에서 Terraform FDO 배포를 위해 사전 요구 사항으로 PostgreSQL, Blob Storage, Redis가 있습니다. 이에 해당하는 서비스로 본 행사에서는 AWS RDS, AWS S3, AWS ElastiCache를 사용하였습니다.

이번 게시글은 Terraform FDO 기능을 중점적으로 알아보고자 함에 목적이 있기 때문에 사전 요구 사항이 생성되어 있다고 전제하며, 구축 순서는 다음과 같습니다.

  1. Amazon EKS Cluster 구축
  2. Terraform enterprise 이미지 다운로드
  3. Helm 배포
  4. 테스트

구축

1. Amazon EKS Cluster 구축

모든 AWS 리소스들은 Terraform code로 작성하여 생성되었습니다. 마찬가지로 사전 요구 사항에 해당하는 AWS 리소스들도 Terraform code로 선언하여 생성하였으며 해당 코드에 대한 자세한 설명은 생략합니다. Terraform code는 module 방식으로 작성되었으며 계층 구조는 아래와 같습니다.

./modules
├── EKS
│ ├── README.md
│ ├── data.tf
│ ├── ec2.tf
│ ├── eks-awsloadbalancercontroller.tf
│ ├── eks-ebscsidrivercontroller.tf
│ ├── eks-efscsidrivercontroller.tf
│ ├── eks.tf
│ ├── env.sh
│ ├── flag.tf
│ ├── main.tf
│ ├── output.tf
│ ├── security_group.tf
│ └── variable.tf
├── Elasticache
│ ├── README.md
│ ├── outputs.tf
│ ├── replication_group.tf
│ ├── security_group.tf
│ ├── subnet_group.tf
│ ├── user.tf
│ ├── vars.tf
│ └── versions.tf
├── Network
│ ├── 01.vpc.tf
│ ├── 02.gw.tf
│ ├── 03.subnets.tf
│ ├── 04.rt.tf
│ ├── README.md
│ ├── outputs.tf
│ ├── vars.tf
│ └── versions.tf
├── PostgreSQL
│ ├── 01.rds.tf
│ ├── README.md
│ ├── output.tf
│ ├── variables.tf
│ └── versions.tf
└── S3
├── 01.s3.tf
├── README.md
├── outputs.tf
├── var.tf
└── versions.tf

첫 번째로 Network 모듈을 통해 Amazon VPC 및 네트워킹 서비스를 생성합니다. VPC 외의 네트워킹 서비스에는 Subnet, Internet gateway, NAT gateway, Routing table이 있습니다.

EKS 클러스터를 생성하는 경우 고려해야 할 사항으로 VPC는 DNS 호스트 이름과 DNS resolution을 모두 지원해야 합니다. 그렇지 않을 경우 추후 생성할 EKS 노드가 클러스터에 등록할 수 없기 때문입니다.

다음으로 EKS 모듈을 통해 Amazon EKS 클러스터와 노드 그룹을 생성합니다. 클러스터는 Terraform에서 제공하는 EKS Public module을 활용하였습니다. 클러스터의 노드 그룹의 경우, Amazon EKS 관리형 노드 그룹을 생성합니다. 노드 그룹 권장 크기와 인스턴스 타입 등을 설정합니다.

추가적으로 EKS 클러스터와 함께 AWS Load Balancer Controller 기능을 설치하여 EKS 클러스터의 AWS Elastic Load Balancer를 관리할 수 있도록 합니다. AWS Load Balancer Controller는 API 서버의 ingress 이벤트를 감지하여 AWS ALB, Target groups, Listeners, Rules등의 리소스를 생성하거나 변경합니다.

해당 AWS Load Balancer Controller를 생성하기 위해 Terraform을 사용 하였습니다. Terraform은 인프라 프로비저닝 도구라는 핵심에 다시금 주목하여 추후 인프라 운영 관리 측면까지 고려해보았을 때, Load balancer는 네트워크 구성 요소이므로 테라폼 코드로 관리하는 것이 유리하다고 판단되어 이와 같이 구성하였습니다.

Terraform에서 제공하는 Helm Provider를 활용하여 AWS Load Balancer Controller를 생성합니다. Helm은 쿠버네티스 애플리케이션 관리를 편리하게 할 수 있는 도구입니다. 하기 예시 코드와 같이 helm_release 블럭을 선언하여 관련 리소스를 생성할 수 있도록 합니다. Image 리포지토리, EKS Service account 정보 등을 내부 set 블럭에 작성하여 쿠버네티스 구성 파일인 yaml 파일과 병합할 수 있도록 합니다.

resource "helm_release" "helm_AWSLoadBalancerController" {
depends_on = [module.eks]
name = "aws-load-balancer-controller"

repository = "<https://aws.github.io/eks-charts>"
chart = "aws-load-balancer-controller"

namespace = "kube-system"

set {
name = "image.repository"

# 프라이빗 레포지토리 사용
value = "aws_account_id.dkr.ecr.us-east-1.amazonaws.com/amazon/aws-load-balancer-controller"
}

}

모든 구성을 마치고 Terraform을 실행시켜 EKS 클러스터를 정상적으로 시작합니다.

2. Terraform enterprise 이미지 다운로드

CLI에서 사용자 정의 namespace를 생성합니다.

$ kubectl create namespace <TFE_NAMESPACE>

생성한 namespace에 image pull secret을 생성하여 <DOCKER_REGISTRY_URL> 에서 Terraform enterprise 컨테이너를 가져올 수 있도록 합니다. Docker registry URL은 images.releases.hashicorp.com 혹은 내부 컨테이너 레지스트리 URL을 사용합니다. 이번 행사에서는 Hashicorp 공식 컨테이너 레지스트리를 사용하였습니다.

$ kubectl create secret docker-registry terraform-enterprise
--docker-server=<DOCKER_REGISTRY_URL>
--docker-username=<DOCKER_REGISTRY_USERNAME>
--docker-password=<DOCKER_REGISTRY_PASSWORD> -n <TFE_NAMESPACE>

Hashicorp helm 리포지토리를 추가 합니다.

$ helm repo add hashicorp <https://helm.releases.hashicorp.com>

override-values.yaml 파일에 추가적인 설정 정보를 작성하여 terraform-enterprise 차트에 적용될 수 있도록 합니다.

$ helm template terraform-enterprise hashicorp/terraform-enterprise –n <TFE_NAMESPACE> - values <OVERRIDES_FILE>

3. Helm 배포

Helm 명령어로 Terraform enterprise를 설치합니다.

$ helm install terraform-enterprise hashicorp/terraform-enterprise –n <TFE_NAMESPACE> - values <OVERRIDES_FILE>

kubectl 명령어로 pod 정보를 출력하여 terraform-enterprise가 성공적으로 시작 되었는지 확인합니다.

$ kubectl get pods -n <TFE_NAMESPACE>

행사 도메인에 정상적으로 접근 가능한지 확인합니다.

이로써 Terraform enterprise FDO 서버를 성공적으로 구축하였습니다. 추후 관리자, 조직, 워크 스페이스 등의 부가적인 초기 설정 과정을 거쳐 마무리 하였습니다.

4. 테스트

테스트를 진행하기에 앞서 짧은 준비 기간 동안 릴리즈된지 한 달 채 되지않은 Terraform FDO 기능을 적용한다는 것이 부담스럽기도 했습니다. 구축을 시작한 단계에서도 문제가 생기면 안정적인 SaaS 형태의 Terraform cloud를 채용할 계획에 있었습니다.

하지만 서론에서 언급했듯이 참가자들의 동시에 진행되는 많은 작업량에 따라 이를 빠른 속도로 처리하기 위해 FDO 방식을 채택하였습니다. 그리고 클러스터의 높은 신뢰성 및 가용성 보장에 대한 우려스러운 점에 대해 확인해 보기 위해 다음과 같은 테스트를 진행하였습니다.

실제 행사 진행 시에 Terraform 서버가 무리 없이 참가자들의 작업량을 견딜 수 있도록 부하 테스트를 진행하였습니다. 테스트는 Terraform 서버에 여러 Terraform workspace를 동시에 다량 생성하여 모두 작업이 중지되거나 실패하지 않고 정상적으로 생성되는지 확인 하였습니다. 테스트 초기에는 최소 사양으로 서비스를 배포한 후, 테스트 결과를 고려하여 인스턴스 타입 및 성능을 조정하여 재진행하는 과정을 반복하였습니다.

하기 예시 코드는 부하 테스트용 코드 중 일부분으로, 참가자 60명을 최대 인원으로 추산하여 그들이 Terraform workspace를 동시에 배포하는 시나리오를 구현한 코드입니다. 해당 코드는 Terraform에서 제공하는 Terraform Enterprise Provider를 사용하여 tfe_workspace 리소스 블럭을 활용하여 작성하였습니다. 참고로 Terraform Cloud/Enterprise Provider를 활용하여 Terraform cloud에서 지원하는 많은 리소스들과 상호작용할 수 있으며, 이는 Terraform Cloud와 Enterprise 모두를 지원합니다.

resource "tfe_workspace" "load_test" {
count = 60
name = "load_test-${count.index}"
organization = data.tfe_organization.org.name
tag_names = ["load_test"]
project_id = tfe_project.load_test.id
vcs_repo {
identifier = "username/test-prj"
oauth_token_id = "ot-XSJcgrBobGbXXXXX"
}
force_delete = true
auto_apply = true

depends_on = [ tfe_project_variable_set.test ]
}

최종적으로 이번 행사 기술 지원을 도와주신 npc분들이 Terraform enterprise 사전 교육 자료를 참고하여 기능을 검증하고 가이드 자료를 검토해 주셨습니다. 또한, 당일 진행 될 퀘스트 시나리오를 실제로 진행해보며 별다른 문제사항은 없는지 확인하는 과정을 거쳤습니다.

npc 분들이 사용자 관점에서 세밀하게 검토하고 직접 기여해주신 덕분에 더욱 원활하게 행사를 진행할 수 있었습니다. 이번 게시글을 빌려 테스트 및 시나리오 고안 등 이외에도 여러 준비에 힘써주신 npc 분들께 감사의 말씀 전합니다.

모니터링

행사 당일 참가자분들은 사전 준비 후에 퀘스트 시나리오에 따라 열심히 테스트를 진행해주셨습니다. 그에 따른 모니터링 체계로 다음과 같이 구축하였습니다.

Terraform 서버를 구동 중인 Amazon EKS 클러스터의 리소스 구동 정보를 Prometheus를 통해 실시간으로 수집하고 Grafana 대시보드를 통해 확인할 수 있도록 하였습니다.

화면에 표시된 파란 박스는 클러스터에서 컨테이너를 띄우고 있는 작업 단위인 Pod 의 개수를 출력합니다. 해당 Pods 가 참가자들의 작업량에 따라 갯수가 사전 설정 값을 기준으로 자동으로 감소하거나 증가합니다.

또한, 화면 하단의 그래프를 통해 노드별 CPU나 메모리 사용량 등을 확인 할 수 있습니다. 화면에 표시된 파란 우상향 화살표를 통해 참가자들이 사전 준비를 마치고 Terraform을 실행하는 10시경 부터 트래픽이 급격하게 증가하는 것을 확인할 수 있습니다.

이처럼 행사가 진행되는 하루 동안 지속적으로 서버 트래픽을 모니터링 하며 발생할 수 있는 이슈 상황에 대해 대비하였습니다.

마치며

이번 행사를 통해 참여해주신 분들께 메가존클라우드에서 지원하고 있는 Devops tools의 다양한 기능들을 소개해드릴 수 있는 자리가 되어 뜻깊었습니다.

특히, 저희 팀에서는 Terraform Flexible Deployment Options을 사용하여 컨테이너 기반의 선언적이고 유연한 클라우드 서비스를 제공하기 위해 노력하였습니다. 실제 엔터프라이즈 고객분들이 궁금해하시고 많이 사용되는 기술들을 소개해드리고자 많은 고민끝에 선별하여 몇 가지 사전 가이드를 제공하였습니다. 더 많은 기능들을 소개하고자하는 욕심이 있었지만 함께 핸즈온 과정을 진행할 수 있는 시간이 한정적이기 때문에 몇 가지 주제들을 덜어내어 아쉬운 마음이 남기도 했습니다. 기회가 된다면 추후 개최될 행사에서 참가자 분들이 관심 가지실 만한 주제들을 고안하여 추가적으로 소개 드리면 좋을 것 같습니다.

마지막으로 본 행사에 참여해주신 분들, 기술 및 운영 지원에 도움주신 모든 분들께 감사의 말씀을 전합니다. 앞으로도 메가존클라우드와 저희 Devops Product팀에 많은 기대와 관심 부탁 드립니다. 감사합니다.

참고 링크

--

--