Skip to content

코드로 인프라 관리하기 2판

코드를 통해 인프라를 설계하거나 프로비저닝을 하고자 하는 사람을 위한 책이다. IaC에 대한 추상화 된 이론과 개념, 원칙과 패턴을 소개하고, 의사코드를 제시한다.

이 책에서 IaC의 핵심 실행 방법으로 제시하는 것은 세 가지가 있다.

1. 모든 것을 코드로 정의한다.

코드로 모든 것을 정의하는 것이 도움되는 이유는 다음과 같다.

  • 재사용성: 모든 것을 코드로 정의하면 인스턴스 단위로 빠르게 수정하고 새롭게 빌드할 수 있다.
  • 일관성: 코드를 사용해 빌드한 시스템은 매번 같은 방식으로 빌드할 수 있기 때문에, 시스템의 예측 가능성과 테스트성을 높인다.
  • 투명성: 코드를 보면 시스템이 어떻게 구축되었는지 더 쉽고 빠르게 파악할 수 있다.

코드를 선언형으로 정의할 것인지, 명령형으로 정의할 것인지는 각 방식의 특징에 따라 고려해야한다.

  • 선언형 코드는 원하는 시스템의 상태를 정의하는 데 유영하며, 특히 원하는 결과에 큰 차이가 없을 때 유용하다. Ansible, Chef, Puppet, CloudFormation, Terraform 등 많은 IaC 툴이 선언형을 사용한다.
  • 동적인 요구사항에 대응하기 위해, 대부분의 선언형 인프라 도구는 언어를 확장하여 명령형 프로그래밍 기능을 추가한다.
  • 프로그래밍 가능한 명령형 언어는 동적인 라이브러리와 추상화 계층을 구축하는 데 더 적합하고, 테스트와 관리를 더 잘 지원한다는 장점이 있다. Pulumi와 AWS CDK 같은 최신 도구는 인프라에 더 동적인 코드를 구현하기 위해 프로그래밍 언어를 사용한다.
  • 단, 두 패러다임이 뒤섞이는 것은 좋지 않다.

인프라 코드를 잘 관리하기 위해선 다른 코드와 똑같이 품질 유지에 신경 써야 하고, 버전 관리 도구와 CI/CD를 적용해야 한다.

2. 코드를 지속적으로 테스트하고 딜리버리 한다.

코드를 항상 배포 가능한 상태로 유지함으로서 품질을 높일 수 있다. 테스트를 통해 아래와 같은 것들을 체크할 수 있다.

  • 기능성: 인프라에 애플리케이션이 올바르게 구성되는지를 확인할 수 있다.
  • 보안: 취약점이나 포트, 사용자 계정 처리, 엑세스 권한 등을 확인할 수 있다.
  • 성능: 특정 작업이 얼마나 빨리 완료되는지를 테스트하여 네트워크 구성이나 클라우드 플랫폼의 문제를 확인할 수 있다.
  • 확장성: 스케일링과 같은 확장이 올바르게 작동하는지 증명할 수 있다.
  • 가용성: 잠재적인 중단 상황에서도 시스템을 사용할 수 있는지를 확인할 수 있다. (카오스 엔지니어링)

선언형 코드에 대한 테스트에서는 변수에 대한 검증이나 여러 코드를 조합한 결과가 정상적인지를 검증할 수 있다. 명령형 코드에서는 추상화된 로직의 정상 작동 여부 등을 검증할 수 있다.

인프라 코드의 생성 속도 문제는 인프라 분할, 의존성 최소화, 프로그래시브 테스트, 영구 스택 인스턴스 등의 방식으로 개선할 수 있다.

리소스나 모듈간 의존성으로 인한 복잡도의 문제는 LocalStack이나 Moto와 같은 클라우드 벤더 모방 도구로 테스트 더블, 테스트 픽스처를 구현함으로써 해결할 수 있다.

테스트 구현을 위해 인프라 리소스 테스트를 위한 다양한 프레임워크를 사용할 수 있다. (ex. Awspec, Clarity, Inspec, Taskcat, Terratest)

3. 시스템을 작고 간단하게 빌드한다.

큰 시스템은 변경하기 어렵고 망가지기도 쉽다. 깔끔하게 정리된 인터페이스로 구성된 컴포넌트로 작은 시스템 구성을 유지하면, 테스트성과 변경 대응 속도를 높일 수 있다. 관리 및 유지보수하기 쉬운 단위로 쪼개는 것이 코드 변경 관리와 프로비저닝 및 테스트 속도 개선에 좋다.


사실 목차가 이 세 개의 방법을 중심으로 이루어진 것은 아니고, 이 외에도 서버 이미지 사전 빌드나 애플리케이션 클러스터, 인프라 코드 딜리버리 방법 등에 대한 구체적인 설명이 더 있었다. 하지만 나머지는 이런저런 패턴이 있다- 정도의 설명이라 다 기억하기보단 구현시에만 다시 펼쳐보면 좋을 것 같다.

다양한 패턴과 방식을 보며 상황에 따른 적절한 IaC 방식을 채택하기 위한 배경지식을 쌓을 수 있었다.

전에 CUE에 대한 아웃사이더님의 글을 보고도 생각한 건데, 결국 코드는 절차나 형상을 정의하기 위한 방식인 것 같다. 어떤 것을 대상으로 하냐, 그리고 요구사항 달성을 위해 그걸 사용하고 변경하는게 얼마나 편하냐를 두고 여러 언어와 방식이 만들어진다.

나는 한 명의 엔지니어로서 앞으로 어떻게 일해야 할 지 궁금하다.