인프랩 IaC 구축기 (Part 1)
안녕하세요. 인프랩 데브옵스 엔지니어 선비입니다.
오늘은 AWS CDK에서 Terraform으로 글에서 다룬 AWS CDK/Terraform, 그리고 인프콘 2022에서 발표했던 Terragrunt를 지나서 Pulumi에 정착하게 된 인프랩의 IaC 구축기를 풀어보고자 합니다.
이번 Part 1 글에서는 Terragrunt를 두고 또 한 번 새로운 도구로 넘어오게 된 배경과 과정,
그리고 이제는 정착할 수 있을 것이라고 생각하는 이유에 대해 한 번 이야기해보려고 합니다.
IaC?
먼저 이 글을 통해서 IaC를 처음 접하시는 분들을 위해 IaC에 대한 간략한 소개와,
인프랩 데브옵스 팀이 어째서 IaC를 정말 중요하게 생각하고 있는지에 대해 말씀드리겠습니다.
IaC는 Infrastructure as Code(코드형 인프라)의 약자로, 코드를 통해서 인프라를 관리하는 것을 의미합니다. IaC는 인프라 관리를 자동화하는 다양한 방법 중에서도 소프트웨어 개발 방법론 등 소프트웨어 개발을 위한 수많은 기술과 도구들을 인프라 관리에 적용할 수 있도록 하므로 특히 강력한 방법이라고 할 수 있습니다.
제가 인프랩에 합류한 2021년 9월 당시까지만 하더라도 인프랩의 인프라 구성은 메인 서비스 컨테이너와 Redis 캐시, PostgreSQL 데이터베이스, 람다 함수 몇 가지 정도로 그다지 복잡하지 않았습니다. 또한 변화가 일어나는 경우도 많지 않았기 때문에 이 때의 인프라 구성 작업은 대부분 웹 콘솔에서 수동으로 진행되었고 몇 개의 리소스만 AWS CDK를 이용하여 구성하는 상태였습니다.
하지만 2021년 말부터 랠릿이 개발되면서 인프라 구성 업무가 급속도로 늘기 시작했습니다.
그 때는 제가 인프랩에 데브옵스로 합류하면서 팀 내 비효율을 기술로 해결하겠다는 당찬 포부와 함께 2년 내에 만들고자 했던 두 가지에 집중하던 시기였는데요,
- 전문 지식이 없이도 팀원들이 고수준의 자동화를 직접 구축할 수 있도록 도와주는 추상화가 잘 된 신뢰할 수 있는 파이프라인 시스템
- 팀원들이 방향 설정과 동기 부여에 사용할 만한 모든 데이터를 일관적인 방식으로 수집하고 시각화하는 모니터링 시스템
몇 가지 조사를 한 후 단기간 내에는 이러한 목표를 달성하기 어렵다는 결론을 내림과 동시에, 이들을 달성하기 위해서는 첫째로 반드시 개인이 아닌 팀으로서 효율적으로 협업할 수 있어야 하고, 둘째로 내일은 오늘보다 더 효율적으로 일할 수 있게 만드는 환경이 준비되어야 한다는 생각을 하게 되었습니다.
즉, 시행착오를 통해 알아낸 정보를 일시적으로 활용하는 것을 넘어 업무 흐름에 적용함으로써 팀원들의 노력을 차곡차곡 쌓아나갈 수 있는 업무 방식이 기반이 되어야 한다고 생각하였습니다.
그리하여 시급한 업무를 진행하는 시간을 빼고는 대부분의 시간과 노력을 업무 방식 개선에 투자하게 되었고, IaC 도입은 가장 핵심적인 업무 방식 개선 방안이었습니다.
이 때 생각했던 원하는 수준의 IaC는 다음과 같았습니다.
- 특별한 경우를 제외하고는 모든 인프라 구성을 IaC를 이용해서 할 수 있다.
- 팀에서 한 번 구축해본 구성의 인프라는 누구든지 쉽고 빠르게 재구축할 수 있다.
- 인프라 구성 요구사항의 만족 여부와 사내 정책 준수 여부, 구성 실수의 존재는 일차적으로 사람이 아니라 컴퓨터가 확인한다.
사실 도입 시도 초반에는 이러한 생각이 적정 기술의 영역을 넘어선 과도한 기술적 욕심일 수 있겠다는 생각을 했었습니다.
하지만 저희 팀은 이러한 기술적 시도에 대해 비교적 열린 분위기였고, 무엇보다 이러한 꿈이 이루어지는 경우에 얻을 수 있는 실질적인 이점이 정말 클 것이라고 확신했기 때문에 적어도 되는 데까지는 해보자는 마음으로 최대한 시간을 짜내서 다양한 실험을 해보았습니다.
지금은 개발파트가 다수의 목적 조직으로 분할되면서 인프라 구성이 매우 복잡해졌고, 목적 조직 외적으로도 검색 기능/영상 처리/자막 기능 등 다수의 작업을 동시에 진행해 구성 작업이 폭발적으로 증가하여 이러한 준비를 해둔 것이 옳은 선택이었다고 생각하고 있습니다.
아직 테스트 자동화와 배포 파이프라인 구성 등 몇 가지 일이 남아있지만, 인프라 정책이나 시행착오를 통해 얻어낸 노하우를 작성해두었다가 하나 하나 찾아보던 때와는 비교할 수 없을 정도로 빠르고 정확하게 인프라를 구성하고 있습니다.
Terraform, Terragrunt에서 이루지 못한 것
AWS CDK에서 Terraform으로 글과 인프콘 2022 발표에서 저희가 AWS CDK를 두고 Terraform을 사용하게 된 결정적인 요인으로 CloudFormation 계층의 존재로 인한 Drift 탐지 및 해결의 어려움을 꼽았었는데요.
아래는 2021년 말에 팀원과 나눈 대화인데, 위 문제로 인해 AWS CDK 및 IaC에 대해 팀원이 이미 강한 불신을 갖고 있는 상태였습니다.
팀원: Route 53 Hosted Zone은 어떻게 연결했어요?
선비: AWS CDK로 Import 해서 연결했습니다.
팀원: 예??? 아니 삭제되면 어떡하려고요???
선비: 왜 삭제되죠…?
다행히 Terraform을 사용하면서부터는 IaC가 하겠다고 한 동작만 할 것임을 신뢰할 수 있어 업무 방식의 기반으로써 사용할 준비가 되었다고 생각했습니다.
그러나 Terraform에도 아쉬운 점이 있었는데, 그 중에서도 HCL이라는 도메인 특화 언어를 이용한다는 특징에서 비롯된 다음과 같은 아쉬움들이 크게 느껴졌습니다.
- 코드 작성 과정에서 IDE의 도움(자동 완성, 타입 힌팅, 리팩터링 등)을 받기가 어렵다는 점
- 간단한 조건문만 사용하더라도 코드의 가독성을 크게 떨어뜨리고 모듈 및 스택의 목적을 파악하기 어려워진다는 점
- Terraform이 지원하지 않는 경우 간단한 추가 기능도 직접 구현하여 사용하기가 어렵다는 점
저희는 이러한 아쉬움을 완화하기 위해서 Terragrunt를 이용한 래퍼 스택 패턴1으로 중복된 코드를 최대한 제거하고, Go 언어 기반의 Terratest로 테라폼 모듈에 대한 테스트를 자동화하였습니다. 이를 통해 각각의 인프라 스택 및 모듈이 명확한 용도를 가지고 사용될 수 있도록 하여 팀원들이 이를 수정하는 것에 어려움을 느끼지 않도록 하고자 하였습니다.
그러나 Terragrunt와 Terratest로도 잘 쓸 수 있을만한 IaC 환경을 구축하기는 역부족이었습니다. 팀원들뿐만 아니라 저조차도 IDE의 도움 없이 HCL 코드들을 돌아다니며 인프라 구성을 이해하는 것은 너무 힘들었고, Terratest는 사실상 Go 언어를 이용하여 Terraform 스택을 실행해주는 도구에 지나지 않아서 코드의 단위 테스트가 불가능했으며 통합 테스트만으로 모든 인프라 구성을 테스트하기에는 시간이 너무 오래 걸렸습니다.
IDE의 지원이 없는 상황에서 Terragrunt를 이용하여 진행했던 코드 DRY 작업은 오히려 프로젝트 구성을 이해하기 어렵게 만드는 걸림돌로 작용했습니다.
그 외에도 악명 높은 node_modules에 버금가는 수준의 .terragrunt-cache 디렉토리 구조와 느린 동작 속도는 스택 및 모듈 종속성을 관리하는 더 나은 방식이 없을지 고민하게 만들었고,
Terragrunt run-all 실행 출력이 스택 별로 섞여 알아보기 어려웠던 점, Atlantis 기반 CI/CD 구축이 각종 버그로 인해 예상보다 오랜 시간이 소요되고 있었던 상황 등이 겹쳐 인프콘 2022 발표를 한 지 얼마 되지 않아서 Terragrunt 기반의 IaC 구성에 회의감을 느끼고 대안을 찾아 나서게 되었습니다.
그러던 중 2022년 8월 말, 『코드로 인프라 관리하기(2판)』의 한국어 번역본이 출간한다는 소식을 듣고 예약주문을 해서 출간하자마자 보게 되었습니다. 정말 운이 좋게도 그 당시의 저에게 꼭 필요했던 내용만 들어 있던 책이었고 IaC에 대해 궁금해하던 것들과 고민하던 것들에 대해 답을 내릴 수 있었습니다.
그리고 이 시점에서 만족할 만한 IaC 구성에 대한 보다 구체적인 조건을 세우게 되었고 Pulumi를 이용하여 이를 만족하는 인프라 프로젝트를 구축하기 시작했습니다.
Pulumi에서 찾은 것
- 범용 프로그래밍 언어 기반
- 함수 등 일반적인 프로그래밍 지식에 기반한 인프라 코드 추상화
- 패키지 관리자, 테스팅 프레임워크 등 그 언어의 생태계 활용
- 자동 완성, 타입 힌팅 등 IDE의 도움을 받아 개발
- 슬랙 메시지 전송, 커스텀 로깅, 비밀 값 로딩, 복합 테스트 등 원하는 대로 확장 가능
- IaC를 통하지 않고 생성한 리소스를 IaC에 쉽게 Import 할 수 있어야 함.
- SasS를 사용하지 않고 AWS S3를 State 저장소로 사용하도록 구성
Pulumi로 처음부터 모든 것을 잘 해결했던 것은 아닌데요,
(후속 글에서 자세히 다룰) Node/TypeScript 환경에서 패키지 관리자, 모노레포 관리 도구, 테스팅 프레임워크 등을 이용하여 Pulumi IaC 프로젝트를 구성하는 과정에서 생각보다 많은 시행착오가 있었고
그 과정에서 소스맵이 제대로 동작하지 않는다거나 하는 다양한 문제를 만나기도 하였습니다.
또한 Pulumi 자체적으로도
- #2522 와 같이 Pulumi Cloud SasS를 사용하지 않으면 StackReference를 제대로 사용하지 못하는 이슈(현재는 해결됨)
- Pulumi Automation API를 기반으로 스택 간 입출력을 관리하도록 하였는데 자동 완성 및 타입 힌팅 등 IDE의 도움을 받지 못하는 문제
- 스택 테스트 시 스택 설정 값을 모킹하기 어려운 문제
등이 있었습니다.
이러한 문제들을 현재는 모두 해결한 상태인데, 앞으로 이어질 글에서 어떤 시도를 거쳐 어떻게 해결했는지 하나씩 상세한 내용을 말씀드릴 예정입니다.
이제 한동안은 Pulumi에 정착해서 글 서두에서 말씀드린 목표를 달성하기 위해 집중할 수 있을 것이라고 생각하고 있는데요,
현재 IaC 구성이 위에서 말씀드린 몇 가지 조건을 만족하도록 만드는데 성공했기 때문이기도 하지만 앞으로 어떤 요구사항이 새로 생기더라도 TypeScript라는 범용 프로그래밍 언어를 이용하여 해결할 수 있을 것이라는 믿음이 있기 때문에 Pulumi 자체에 문제가 발생하지 않는 이상 또 다른 무언가로 전환하지 않고 개선해나갈 수 있을 것 같습니다.
아래는 Terragrunt를 사용하던 때에 염원하던 몇 가지입니다.
Pulumi Automation API와 TypeScript Generic을 활용하여 코드의 모든 영역에서 자동 완성과 타입 힌팅이 동작하도록 구성했습니다.
Pulumi Mock을 기반으로 설정 값 및 리소스 구성에 대한 단위 테스트를 구성했습니다.
테스트 픽스처 리소스를 이용하여 최소한의 비용으로 스택에 대한 복잡한 통합 테스트도 구성할 수 있도록 하였습니다.
아직 Pulumi 실행을 중앙 집중식 배포 파이프라인에서만 하도록 구성하지는 못해서 각 데브옵스 엔지니어의 PC에서 실행하도록 하고 있는데요, 최소한의 안전장치로 누가 어떤 스택을 실행하였는지 슬랙 알림을 발송하도록 구성하였습니다.
비밀 값을 AWS Secrets Manager에서 불러와서 캐싱해두고 사용하는 부분을 직접 구현하여 사용하고 있습니다. (Infisical로 전환하는 것을 고려하고 있습니다.)
추가로 오류 메시지 등을 추상화하여 알아보기 쉽게 출력하도록 구성하였습니다.
Nx를 이용하여 단일 Node 패키지 내에서 스택 및 컴포넌트 간 종속성을 관리하고 있습니다.
이어질 게시물에서 관심 있는 분들이 따라해보실 수 있도록 Pulumi Automation API 기반 인프라 프로젝트 구성부터 타입 힌팅 활성화를 위한 제네릭 코드 구성, Jest 기반 테스트 구성, Pulumi TypeScript vs Golang, Nx를 이용한 스택 종속성 관리, 스택 이름 규칙, IaC 밖에서 생성한 리소스의 Codegen 및 State Import 방법 등에 대해 구체적으로 다루어보도록 하겠습니다.
번외로 2023년 8월 10일에 Terraform이 Hashicorp에 의해서 MPL에서 BUSL로 라이선스가 전환됨에 따라서 오픈 소스 포크인 OpenTofu가 등장하는 등 Terraform 생태계가 약간 흔들리고 있는데, 이에 영향을 받지 않을 수 있다는 것도 Pulumi 전환에 따른 예상하지 못한 이점인 것 같습니다.
결론
약 2년의 시간 동안 인프랩의 IaC가 어떤 과정을 거쳐 왔는지에 대해 간략하게 이야기해보았습니다.
이제 와서 돌이켜보면 AWS CDK, Terraform, Terragrunt를 계속 사용했더라도 각자의 단점을 안고 가면서 최선의 방식으로 쓰는 방법이 분명 있었을 것이라고 생각합니다.
하지만 더 나은 작업 환경에 대한 필요성과 가능성을 강하게 느끼고 있었고, 운이 좋게도 적절한 시기에 이러한 생각을 정리하여 명확한 요구사항으로 만들 수 있었으며, 저희 조직이 그 필요를 충족하기 위한 도전을 지원할 수 있는 팀이었기 때문에 이를 실행할 수 있었다고 생각합니다.
올해부터는 지난 2년 간의 준비를 발판으로 삼아 IaC와 같은 기반이 없었다면 불가능했을 다양한 작업을 진행해볼 계획입니다.
감사합니다.
- 파라미터 변수를 사용하는 스택 코드 모듈이 하나 존재하고, 이 모듈을 참조하며 실제 파라미터 값을 포함하는 스택 프로젝트가 다수 존재하는 형태. (키프 모리스, 『코드로 인프라 관리하기(2판)』, 챕터 7 스택 인스턴스 구성하기)↩