데브옵스 플랫폼이 선택한 프로비저닝 도구

안녕하세요. 화해 개발팀 데브옵스 엔지니어 장영석입니다. 테라폼

 

화해 개발팀은 대부분의 인프라를 AWS에서 운영 중입니다. 화해의 프로젝트 실행 조직들은 크로스펑셔널팀 형태로 구성되어 있습니다. 각 팀 별 독립적인 과제가 진행되다 보니 다수의 팀으로부터 리소스를 생성하고 제거하는 작업 요청이 늘어나게 되었습니다. 리소스 생성의 대부분에서 동일한 과정이 반복되다 보니 각 기술 요소들의 가이드와 컨벤션 문서를 기반으로 표준화를 진행하고 있습니다.

 

하지만 표준화된 가이드를 통해 리소스를 생성한다고 해도 사람이 직접 작업을 진행해야 한다면 휴먼 에러의 위험성은 언제나 존재하게 됩니다. 또한 사용 완료된 환경을 제거하는 과정에서 누락되거나 잘못 삭제되는 경우도 발생합니다.

 

게다가 화해팀에서는 2022년 다수의 신규 실행 조직 론칭 계획이 있어 지금의 배포 방법으로는 요청을 감당하기 어려운 상황이 될 것이라 전망하였습니다. 데브옵스 플랫폼은 효율적인 배포 방법이 필요하다는 데 의견을 모았고, 이는 오토 프로비저닝 도구의 도입으로 이어지게 되었습니다.

 

프로비저닝 도구는 인프라 환경에 필요한 거의 대부분의 리소스를 코드로 관리하고 프로비저닝합니다. 또한 코드로 관리되기에 VCS를 사용하여 구성 파일의 버전 관리와 코드 리뷰 등이 가능해집니다. 이로 인해 사용자의 실수는 줄어들고 모듈화 된 코드를 재사용하여 안정적으로 새로운 환경을 구축해나갈 수 있습니다.

 


terraform {
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 3.27"
    }
  }

  required_version = ">= 0.14.9"
}

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

resource "aws_instance" "app_server" {
  ami           = "ami-830c94e3"
  instance_type = "t2.micro"

  tags = {
    Name = "ExampleAppServerInstance"
  }
}

<테라폼 AWS provider 구성 파일 예시>

 

 

 

테라폼은 무엇이 다른가?


다양한 프로비저닝 도구들이 있고 간혹 프로비저닝 단계를 지원하는 구성 관리 도구도 존재합니다. 각 툴마다 장단점이 많지만 데브옵스 플랫폼이 테라폼을 선택한 이유를 아래에서 소개합니다.

 

 

다양한 프로바이더와 모듈 지원

테라폼은 메이저 클라우드 프로바이더를 대부분 지원합니다. 화해팀에서는 AWS를 주력으로 사용하지만 GCP도 일부 사용하고 있고 앞으로 점점 다양한 환경으로 확장될 가능성이 높습니다. AWS Cloudformation이나 CDK 등도 고려하였으나 특정 클라우드 환경에 종속된다는 한계가 있어 테라폼에 높은 점수를 주었습니다.

 

화해팀_테라폼

<테라폼 프로바이더 Registry – 출처 테라폼 공식 홈페이지>  

 

 

또한 AWS와 GCP에서 재사용 가능한 모듈을 제공합니다. 빠른 환경 구성이 필요한 경우 요긴하게 사용될 수 있으며 새로운 모듈을 만들어내기 위한 우수한 참고자료가 되기도 합니다.

 

화해팀_테라폼

<테라폼 모듈 Registry – 출처 테라폼 공식 홈페이지>

 

 

 

프로바이더의 API 호출을 변환하여 사용

테라폼은 실제 인프라에 환경 생성 시 구성 파일을 각 프로바이더의 API 호출로 변환합니다. 덕분에 AWS CLI를 사용하던 입장에서 제공되는 기능의 유무와 각 인수가 의미하는 바를 파악하기 수월했고 친숙하게 다가왔습니다. 실제로 아래 테라폼(좌)과 AWS CLI(우)로 VPC 리소스 생성 시 필요한 인수명과 설명을 비교하면 대부분 일치하는 것을 볼 수 있습니다.

 

화해팀_테라폼

<테라폼과 AWS CLI 의 VPC 인수명 비교 – (좌) 테라폼 (우) AWS CLI> 

 

 

 

에이전트 설치 생략

테라폼은 프로바이더의 API를 사용하여 해당 클라우드의 에이전트를 통해 작업이 진행되기 때문에 별도의 에이전트 설치를 생략할 수 있습니다. 별도 에이전트의 설치가 필요한 상황이라면 주기적인 업데이트가 필요하고 각 버전별 호환성 문제가 발생할 여지가 있습니다. 또한 에이전트와 통신을 위한 포트를 열고 연결을 위한 추가 인증방식을 고려해야 할 수도 있습니다.

 

 

선언적 언어

선언적 언어는 구현하려는 최종 상태를 코드로 작성하는 것을 말합니다. 구성 파일에 최종 상태를 작성하고 작업 수행 시 상태 파일을 저장합니다. 테라폼은 구성 파일이 변경되면 저장된 상태 파일을 기준으로 기술된 최종 상태를 어떻게 적용할 것인지 계획하는 과정을 거칩니다. plan 명령어를 통해 사용자가 기대하는 실행 계획과 일치하는지 확인할 수 있습니다.


$ terraform plan
An execution plan has been generated and is shown below.
 
Resource actions are indicated with the following symbols:
  + create
 
Terraform will perform the following actions:
 
  # aws_ebs_volume.iac_in_action will be created
  + resource "aws_ebs_volume" "iac_in_action" {
        + arn               = (known after apply)
        + availability_zone = "us-east-1a"
        + encrypted         = (known after apply)
        + id                = (known after apply)
        + iops              = 1000
        + kms_key_id        = (known after apply)
        + size              = 100
        + snapshot_id       = (known after apply)
        + tags              = {
                + "Name" = "Terraform-managed EBS Volume for IaC in Action"
            }
            + type              = "io1"
    }
 
Plan: 1 to add, 0 to change, 0 to destroy.

<테라폼 plan 명령어 예시>

 

 

 

팀 단위에서 테라폼 상태 파일 관리하기


테라폼 상태 파일이란?

테라폼을 통해 생성한 인프라의 정보는 테라폼 상태 파일에 기록됩니다. 기본적으로 실행한 위치에 terraform.tfstate 파일이 생성되고 테라폼 구성 파일의 리소스를 실제 인프라 리소스와 매핑할 수 있는 형태로 기록됩니다.


resource "aws_instance" "example" {
  ami           = "ami-1234"
  instance_type = "t2.micro"
}

<구성파일 예시>

 


resource "aws_instance" "example" {
  ami           = "ami-1234"
  instance_type = "t2.micro"
}

{
  "version": 4,
  "terraform_version": "1.0.0"
  "serial": 1,
  "lineage": "1d-3fj-fjdklsjf"
  "outputs": {},
  "resources": [
    {
      "mode": "managed",
      "type": "aws_instance",
      "name": "example",
      "provider": "provider.aws",
      "instances": [
        {
          "schema_version": 1,
          "attributes": {
            "ami": "ami-1234",
            "availability_zone": "us-east-2c",
            "id": "i-00dfjkldjfkdljf",
            "instance_state": "running",
            "instance_type": "t2.micro",
            ...
          }
        }
      ]
    }
  ]
}

<구성파일 배포시 생성된 terraform.tfstate 파일 예시>

 

 

테라폼은 위 상태 파일을 통해 실제 AWS에 아이디가 i-00dfjkldjfkdljf 인 인스턴스가 구성 파일에서 이름이 example 인 aws_instance 타입임을 알게 됩니다. 즉, plan 명령어는 상태 파일을 기반으로 구성 파일과 실제 인프라 간의 차이를 파악하고 이를 출력하는 것입니다.

 

이런 상태 파일은 개인 프로젝트로 진행하는 경우 로컬에서 관리하는 것이 좋습니다. 하지만 실제 운영환경에서 팀 단위의 프로젝트에 사용하게 된다면 아래와 같은 문제가 발생합니다.

 

상태 파일을 위한 공유 스토리지

모든 팀원이 동일한 상태 파일에 접근하기 위해 공유 스토리지에 위치해야 합니다.

 

상태 파일 동시 접근 제어를 위한 잠금기능

상태 파일이 공유 스토리지에 위치하기 위해서는 잠금 기능이 필요합니다. 여러 팀원이 동시에 접근하여 상태 파일을 업데이트하는 경우 데이터가 손실되거나 파손될 우려가 있습니다.

 

상태 파일의 환경별 격리

구성파일 변경의 영향을 받는 범위를 해당 환경으로 격리하는 것이 좋습니다. 사용자의 실수로 개발이나 테스트 환경의 변경이 운영환경에 영향을 미쳐 장애로 이어지는 상황이 발생할 수 있습니다.

 


 

상태 파일을 위한 공유 스토리지

여러 팀원이 접근 가능한 스토리지로 VCS를 생각할 수 있습니다. 하지만 상태 파일을 VCS에 저장한다면 사용자 실수로 업데이트를 누락하거나 최신 파일을 받지 않은 상태에서 인프라 변경을 시도할 수 있습니다. 또한 잠금 기능이 제공되지 않아 상태 파일의 데이터가 손실되거나 파손될 우려가 있습니다.

 

원격 백엔드 기능을 활용한 공유 스토리지 사용

원격 백엔드를 사용하면 위 내용의 단점들을 해결할 수 있습니다. 테라폼 원격 백엔드의 기본 설정은 로컬 스토리지입니다. 이를 AWS S3, 애저 스토리지, 구글 클라우드 스토리지, 테라폼 클라우드 등 각 클라우드 별 공유 스토리지로 설정하여 상태 파일을 관리할 수 있습니다.

 

공유 스토리지를 원격 백엔드로 설정하면 테라폼은 plan이나 apply 명령 실행 시 상태 파일을 해당 백엔드에서 자동으로 로드하며, apply 명령 실행 후에는 상태 파일을 백엔드에 자동 저장합니다. 앞서 VCS를 사용할 경우 단점으로 얘기되었던 사용자 실수로 인한 문제가 발생하지 않습니다.

 

 

화해팀_테라폼

<원격 백엔드 공유 스토리지 사용 예시>

 

 

또한 대부분의 클라우드 환경은 원격 백엔드 기능을 사용하여 잠금 기능을 사용할 수 있습니다. 대표적인 케이스로 AWS S3를 원격 백엔드로 사용 시 다이나모 DB를 통해 잠금 기능을 사용할 수 있습니다.

 

하지만 잠금 기능을 이용하기 위해서는 별도의 인프라 구축 과정이 필요하고 해당 리소스들을 관리해야 하는 부담감이 있습니다. 물론 원격 백엔드 삭제 시에도 관련 인프라 제거 과정이 추가되는 단점이 있습니다.

 

테라폼 프로젝트의 파일 레이아웃을 통한 환경별 상태 파일 격리

테라폼은 워크스페이스 기능을 제공하고 이를 통해 구성 파일에서의 분기 처리가 가능합니다.


$ terraform workspcae new example1
Created and switched to workspace "example1"!

 <새로운 작업 공간 생성 명령어 예시>

 


$ terraform workspace list
default
* example1

 <작업 공간 목록 조회 명령어 예시>

 


$ terraform workspcae new example1
Created and switched to workspace "example1"!

$ terraform workspace list
default
* example1

resource "aws_instance" "example" {
    ami = "ami-blahblah"
    instance_type = terraform.workspace == "default" ? "t2.medium" : "t2.micro"
}

< 워크스페이스를 활용한 구성파일 분기처리 예시>

 

 

하지만 구성 파일에 복잡한 분기 로직이 추가되고 상태 파일이 동일한 백엔드에 저장된다는 단점이 있습니다. 예를 들어 AWS S3를 원격 백엔드로 사용하고 있다면, 운영과 개발환경 상태 파일이 모두 같은 버킷에 저장되게 되고 접근 권한이나 인증을 분리하기 어렵습니다. 또한 현재 워크스페이스가 운영환경임을 잊고 인프라를 제거하거나 변경하는 등의 실수가 발생할 여지가 있습니다.

 

워크스페이스의 단점을 극복하기 위해 파일 레이아웃 방식으로 환경별 상태 파일을 격리했습니다.

.
├── modules : 재사용될 module 을 관리
│   ├── networks
│   ├── services
│   └── data-stores
├── dev
│   ├── networks : 네트워크와 관련된 리소스
│   ├── services : 서비스에 활용되는 리소스 (hh-cms-api...)
│   └── data-stores : 데이터 저장소로 사용되는 리소스
│       ├── rds
│       ├── s3
│       └── redis
├── test
├── prd
└── global : 환경 구분없이 사용되는 글로벌 리소스
    ├── s3
    └── iam

 <파일 레이아웃을 통한 환경별 격리 예시>

 

이처럼 상태 파일이 각 환경이나 리소스 별로 분리될 수 있도록 파일 레이아웃을 구성했습니다.

 

 

 

최종 선택은 테라폼 클라우드


우리는 결과적으로 위 단점들을 해소할 수 있는 테라폼 클라우드를 사용하기로 결정했습니다. 테라폼 클라우드는 상태 파일을 관리하기 위한 원격 백엔드와 잠금 기능을 제공하기에 사용자가 직접 구축할 필요가 없습니다. 인프라 변경사항의 적용 작업도 로컬이 아닌 테라폼 클라우드의 실행 환경을 사용하며 이와 관련된 히스토리와 배포 상태를 조회할 수 있습니다. 재사용을 위한 모듈의 배포 및 버전 관리 또한 손쉽게 구성할 수 있습니다.

 

 

 

마치며


화해의 데브옵스 플랫폼은 출범한 지 얼마 되지 않았음에도 기존 환경들을 분석하고 효율적인 리소스 관리를 위한 통합화, 표준화, 자동화 구현을 빠르게 진행해나가고 있습니다. 이번에는 오토 프로비저닝 도구 적용사례를 소개했지만 서버 이미지 관리 자동화를 위한 Packer 도입, 실시간 이벤트 로그 수집을 위한 Kafka Cluster, 장애 예측과 빠른 로그 정보 확인을 위한 Elasticsearch 등도 도입되어 확대 적용해가는 중입니다.

 

이러한 기술들을 함께 경험하고 더욱 성장시켜나가고 싶은 분들의 추가 합류를 기다리고 있습니다. 많은 관심 부탁드립니다.

 

 


 

 

이 콘텐츠가 마음에 드셨다면 데브옵스 플랫폼의 다른 콘텐츠도 확인해보세요!

표준 서비스 환경 자동 구축을 위한 서버 템플릿 도구 도입 사례

gunicorn 설정의 A to Z

 

 

채용정보 확인하기

 

6
by nc nd