정적 인벤토리와 동적 인벤토리: 확장에 적합한 Ansible 전략 선택

정적 및 동적 Ansible 인벤토리를 비교하고, 클라우드, 온프레미스 및 혼합 환경을 위한 실용적인 지침을 제공합니다.

정적 인벤토리와 동적 인벤토리: 확장에 적합한 Ansible 전략 선택

Ansible 인벤토리는 Ansible이 접근할 수 있는 머신 목록과, 해당 머신에 도달하는 방법을 설명하는 그룹 및 변수입니다. 이 목록이 잘못되면 플레이북이 완벽하더라도 실행이 위험할 수 있습니다. 새 호스트를 놓치거나, 삭제된 호스트를 계속 관리하거나, 그룹 이름이 변경되어 데이터베이스 작업을 웹 노드에 실행할 수 있습니다.

정적 인벤토리와 동적 Ansible 인벤토리 중 선택은 성숙도 배지가 아닙니다. 정적 파일은 여전히 많은 소규모의 안정적인 환경에서 가장 깔끔한 해결책입니다. 동적 인벤토리는 일반적으로 인프라가 클라우드 API, 오토스케일링 그룹, Kubernetes, Terraform 또는 다른 진실 공급원에 의해 생성 및 삭제될 때 더 좋습니다. 유용한 질문은 "어느 것이 더 고급인가?"가 아니라 "이 호스트에 대한 진실이 이미 어디에 있는가?"입니다.

Ansible 인벤토리 이해하기

핵심적으로 Ansible 인벤토리는 Ansible이 관리할 호스트 목록입니다. 이러한 호스트는 서버, 네트워크 장치 또는 기타 관리 노드가 될 수 있습니다. 인벤토리는 그룹별로 구성되는 등 다양한 방식으로 구조화될 수 있으며, 이를 통해 인프라의 하위 집합에 구성을 적용할 수 있습니다.

인벤토리 파일(또는 소스)은 INI 또는 YAML 형식일 수 있습니다. 예를 들어, 간단한 INI 형식의 인벤토리는 다음과 같습니다:

[webservers]
web1.example.com
web2.example.com

[databases]
db1.example.com

이 구조는 webserversdatabases라는 두 개의 그룹을 정의하며, 각 그룹에 특정 호스트가 할당됩니다. Ansible은 플레이북에서 이러한 그룹을 대상으로 지정하여, 예를 들어 webservers 그룹의 모든 호스트에 웹 서버 구성을 배포할 수 있습니다.

정적 인벤토리: 단순성과 제어

정적 인벤토리는 호스트 목록이 명시적으로 정의되고 수동으로 유지 관리되는 인벤토리 소스를 의미합니다. 이는 일반적으로 인프라가 변경될 때 업데이트되는 일반 텍스트 파일(INI 또는 YAML)을 사용하여 수행됩니다.

정적 인벤토리의 특징

  • 수동 정의: 호스트와 그룹 멤버십이 파일에 직접 나열됩니다.
  • 고정 구조: 인벤토리는 수동으로 편집할 때까지 일정하게 유지됩니다.
  • 시작하기 쉬움: 소규모의 안정적인 환경에서 설정하기 쉽습니다.
  • 예측 가능성: Ansible이 대상으로 삼을 호스트를 항상 정확히 알 수 있습니다.

정적 인벤토리의 장점

  • 단순성: 소규모의 예측 가능한 환경에서는 정적 인벤토리를 관리하기가 간단합니다.
  • 제어: 포함할 호스트와 그룹화 방법을 완전히 제어할 수 있습니다.
  • 이해 용이성: 구조를 읽고 이해하기 쉽습니다.

정적 인벤토리의 단점

  • 확장성 문제: 많은 수의 호스트를 수동으로 관리하는 것은 시간이 많이 걸리고 오류가 발생하기 쉽습니다.
  • 유지 관리 오버헤드: 인프라의 모든 추가, 제거 또는 변경에는 인벤토리 파일을 수동으로 업데이트해야 합니다.
  • 동적 환경에 부적합: 인스턴스가 자주 시작 및 종료되는 클라우드 환경에서는 정적 인벤토리가 빠르게 구식이 됩니다.

정적 인벤토리를 사용해야 하는 경우

정적 인벤토리는 다음과 같은 경우에 탁월한 선택입니다:

  • 변경이 드문 소규모 온프레미스 인프라.
  • 고정된 머신 세트가 있는 개발 또는 테스트 환경.
  • 관리 노드에 대한 정밀한 제어가 가장 중요하고 변경이 드문 상황.

동적 인벤토리: 자동화와 탄력성

반면 동적 인벤토리를 사용하면 Ansible이 호스트를 자동으로 검색하고 관리할 수 있습니다. 호스트를 수동으로 나열하는 대신 Ansible은 외부 데이터 소스(예: 클라우드 공급자 API, CMDB 또는 스크립트)를 쿼리하여 인프라의 현재 상태를 검색합니다.

동적 인벤토리 작동 방식

동적 인벤토리 소스는 일반적으로 Ansible의 동적 인벤토리 API를 따르는 스크립트 또는 플러그인으로 구현됩니다. Ansible이 인벤토리 데이터가 필요하면 이 스크립트 또는 플러그인을 실행하여 관련 시스템을 쿼리하고 JSON 형식으로 호스트 정보를 반환합니다. 이 JSON 출력에는 호스트, 그룹 및 관련 변수가 포함됩니다.

Ansible은 많은 클라우드 공급자 및 서비스에 대한 기본 지원을 제공하므로 동적 인벤토리를 쉽게 통합할 수 있습니다. 예를 들어 AWS EC2를 동적 인벤토리 소스로 사용하려면 aws_ec2 인벤토리 플러그인을 설치할 수 있습니다.

동적 인벤토리의 특징

  • 자동 검색: 외부 소스에서 호스트를 검색합니다.
  • 실시간 업데이트: 인벤토리는 인프라의 현재 상태를 반영합니다.
  • 클라우드 공급자와의 통합: AWS, Azure, GCP 및 기타 클라우드 플랫폼과 원활하게 작동합니다.
  • 태깅 및 메타데이터: 그룹화 및 변수 할당을 위해 외부 소스의 태그와 메타데이터를 활용합니다.

동적 인벤토리의 장점

  • 확장성: 수백 또는 수천 개의 호스트가 있는 환경을 쉽게 처리합니다.
  • 자동화: 수동 인벤토리 유지 관리를 제거하여 오류를 줄이고 시간을 절약합니다.
  • 복원력: 새로 프로비저닝되거나 종료된 리소스를 자동으로 처리합니다.
  • 유연성: 클라우드 컴퓨팅의 동적 특성에 적응합니다.

동적 인벤토리의 단점

  • 복잡성: 초기 설정 및 구성이 정적 인벤토리보다 더 복잡할 수 있습니다.
  • 외부 시스템에 대한 의존성: 외부 데이터 소스의 가용성과 정확성에 의존합니다.
  • 과도한 관리 가능성: 신중하게 구성하지 않으면 Ansible이 관리 대상이 아닌 리소스를 관리하려고 시도할 수 있습니다.

인기 있는 동적 인벤토리 소스

  • 클라우드 공급자 플러그인: aws_ec2, azure_rm, gcp_compute.
  • 컨테이너 오케스트레이터: kubernetes.core.k8s.
  • CMDB 및 자산 시스템: ServiceNow, NetBox 또는 내부 서비스 카탈로그.
  • 사용자 정의 스크립트: 유효한 JSON을 출력하는 모든 스크립트.

예: AWS EC2 동적 인벤토리 사용

AWS EC2 인스턴스를 동적 인벤토리로 사용하려면 일반적으로 aws_ec2 플러그인을 구성합니다. 여기에는 AWS 리전, 자격 증명 및 필터를 지정하는 Ansible 인벤토리 구성 파일(예: aws_ec2.yml)을 생성하는 작업이 포함될 수 있습니다.

# aws_ec2.yml
plugin: aws_ec2
regions:
  - us-east-1
filters:
  instance-state-name: running
keyed_groups:
  - key: tags.Environment
    prefix: env
  - key: tags.Project
    prefix: project
compose:
  ansible_host: private_ip_address

이 구성을 사용하면 Ansible이 us-east-1에서 실행 중인 EC2 인스턴스를 쿼리합니다. EnvironmentProject 태그를 기반으로 그룹을 자동으로 생성하고 각각 env_project_ 접두사를 붙입니다. 또한 각 인스턴스의 ansible_host를 개인 IP 주소로 설정합니다.

그런 다음 이 동적 인벤토리 소스를 사용하여 Ansible 명령 또는 플레이북을 실행할 수 있습니다:

ansible-inventory --graph -i aws_ec2.yml
ansible-playbook -i aws_ec2.yml site.yml

동적 인벤토리로 전환해야 하는 경우

정적 인벤토리에서 동적 인벤토리로 전환하는 결정은 종종 인프라의 특성과 운영 성숙도에 의해 결정됩니다.

동적 인벤토리를 고려해야 하는 징후

  • 인프라 성장: 수동 인벤토리 편집으로 인해 호스트 누락, 오래된 호스트 또는 느린 검토가 발생하는 경우.
  • 클라우드 채택: 리소스가 일시적이고 자동 확장되는 AWS, Azure 또는 GCP와 같은 클라우드 플랫폼을 많이 사용하는 경우.
  • 빈번한 변경: 인프라가 자주 업데이트되거나, 확장 또는 축소되거나, 빈번한 배포가 이루어지는 경우.
  • 자동화 목표: 더 높은 수준의 자동화를 달성하고 인프라 관리에서 수동 개입을 줄이기 위해.
  • 오케스트레이션 통합: Kubernetes와 같은 컨테이너 오케스트레이터를 사용하는 경우, 동적 인벤토리는 포드 및 서비스 관리에 필수적입니다.

전환 프로세스

  1. 인프라 평가: 호스트가 관리되는 위치(클라우드, 온프레미스, 컨테이너)와 프로비저닝 방식을 이해합니다.
  2. 데이터 소스 식별: 인프라의 최종 목록을 보유한 외부 시스템(예: 클라우드 공급자 API, CMDB)을 결정합니다.
  3. 적절한 플러그인/스크립트 선택: 데이터 소스에 적합한 동적 인벤토리 플러그인 또는 스크립트를 선택하거나 개발합니다.
  4. 그룹화 및 변수 구성: 호스트를 그룹화하는 방법(예: 태그, 인스턴스 유형별)과 변수 할당 방법을 정의합니다.
  5. 철저히 테스트: 프로덕션에 배포하기 전에 스테이징 환경에서 동적 인벤토리에 대해 Ansible 명령을 실행합니다.
  6. 필요시 플레이북 업데이트: 플레이북이 새로운 그룹화 및 변수 구조와 호환되는지 확인합니다.

인벤토리 관리 모범 사례

정적 또는 동적 인벤토리 중 무엇을 선택하든 모범 사례를 준수하면 효율적이고 안정적인 Ansible 운영이 보장됩니다:

  • 체계적으로 유지: 의미 있는 그룹 이름과 일관된 호스트 명명 규칙을 사용합니다.
  • 변수 활용: Ansible 변수(host_vars, group_vars)를 사용하여 구성 차이를 관리하고 플레이북에서 반복을 피합니다.
  • 별칭 및 팩트 사용: 정적 인벤토리의 경우 별칭 사용을 고려합니다. 동적 인벤토리의 경우 동적 변수 할당을 위해 클라우드 공급자 태그와 메타데이터를 최대한 활용합니다.
  • 정기적으로 검토 및 감사: 특히 정적 인벤토리를 사용하는 경우 정기적으로 인벤토리의 정확성과 완전성을 확인합니다.
  • 자격 증명 보안: API 액세스가 필요한 동적 인벤토리 플러그인을 사용할 때는 자격 증명이 안전하게 관리되는지 확인합니다(예: Ansible Vault, IAM 역할 사용).

실제 사례

소규모 정적 환경의 경우 일반 인벤토리 파일이 복잡한 통합보다 더 나을 수 있습니다. 소규모 사무실이나 소규모 프로덕션 배포에서 세 대의 웹 서버, 한 대의 데이터베이스 서버 및 한 대의 배스천 호스트를 상상해 보십시오:

[webservers]
web01 ansible_host=10.20.1.11
web02 ansible_host=10.20.1.12
web03 ansible_host=10.20.1.13

[databases]
db01 ansible_host=10.20.2.20

[all:vars]
ansible_user=deploy

모든 사람이 Git에서 해당 파일을 검토할 수 있습니다. db01을 잘못된 그룹으로 이동하는 풀 리퀘스트는 쉽게 발견할 수 있습니다. 관리할 클라우드 자격 증명이 없고, 디버깅할 플러그인 캐시가 없으며, API 중단으로 인한 놀라움도 없습니다. 서버 목록이 분기에 한 번 변경된다면 정적 인벤토리는 약점이 아닙니다.

문제는 파일이 더 이상 현실을 반영하지 않을 때 시작됩니다. 한 팀이 Terraform을 통해 인스턴스를 추가하고, 다른 팀이 인시던트 중에 노드를 종료하며, Ansible 인벤토리는 "누군가 기억할 때" 나중에 업데이트됩니다. 이 간격이 오래된 자동화의 원천입니다. 연결할 수 없는 호스트와 같은 오류가 발생하거나, 더 나쁜 경우 새 호스트가 추가되지 않았기 때문에 플릿의 절반만 패치합니다.

동적 인벤토리는 외부 시스템이 이미 권위 있는 것으로 취급될 때 가장 잘 작동합니다. AWS에서는 EC2 태그일 수 있습니다. 데이터 센터에서는 NetBox일 수 있습니다. 플랫폼 팀에서는 프로비저닝 파이프라인에 의해 채워진 서비스 카탈로그일 수 있습니다. 인벤토리 플러그인은 해당 진실의 읽기 전용 역할을 해야 하며, 운영자가 새로운 그룹 로직을 발명하는 두 번째 장소가 되어서는 안 됩니다.

태그 품질은 플러그인보다 더 중요합니다. 이 AWS 예제는 EnvironmentProject 태그로 그룹화합니다:

plugin: amazon.aws.aws_ec2
regions:
  - us-east-1
filters:
  instance-state-name: running
keyed_groups:
  - key: tags.Environment
    prefix: env
  - key: tags.Project
    prefix: project
compose:
  ansible_host: private_ip_address

모든 인스턴스에 해당 태그가 있고 태그 값이 일관된 경우에만 깔끔합니다. prod, productionProduction은 정규화하지 않으면 다른 그룹을 생성합니다. 중요한 플레이북을 동적 인벤토리로 이동하기 전에 다음을 실행하십시오:

ansible-inventory -i aws_ec2.yml --graph
ansible-inventory -i aws_ec2.yml --list --yaml

빈 그룹, 예상치 못한 그룹 이름, 개인 IP를 사용해야 하는 공용 IP, 너무 많은 곳에 나타나는 호스트를 찾으십시오. 그래프 출력은 종종 실패한 플레이북보다 더 빨리 실수를 잡아냅니다.

혼합 접근 방식은 일반적이며 완전히 합리적입니다. 네트워크 어플라이언스, 레거시 데이터베이스 서버 및 배스천 호스트에는 정적 인벤토리를 유지하고, 자동 확장되는 애플리케이션 노드에는 동적 인벤토리를 사용할 수 있습니다. Ansible은 한 번에 여러 인벤토리 소스를 로드할 수 있습니다:

ansible-playbook -i inventory/static.ini -i inventory/aws_ec2.yml site.yml

소스를 결합할 때는 그룹 이름을 신중하게 지정하십시오. 정적 파일과 동적 플러그인이 모두 webservers를 생성하면 Ansible이 그룹 멤버십을 병합합니다. 이는 유용할 수 있지만 실수를 숨길 수도 있습니다. 소스나 의도를 드러내는 그룹 이름(예: aws_web, dc_web, prod_web, legacy_db)을 사용한 다음 의도적으로 상위 그룹을 만드는 것이 좋습니다.

또한 마이그레이션 전에 변수 처리 방법을 결정하십시오. 동적 인벤토리는 호스트와 메타데이터를 검색하는 데 능숙하지만 애플리케이션 구성을 저장하기에 항상 가장 좋은 장소는 아닙니다. 장기적인 설정은 Ansible에 속할 때 group_vars/host_vars/에 보관하고, Ansible 외부에 이미 존재하는 그룹화 팩트에는 태그 또는 메타데이터를 사용하십시오. Environment=prod와 같은 클라우드 태그는 좋은 그룹화 신호입니다. 데이터베이스 비밀번호는 그렇지 않습니다.

캐싱에 대해 간략히 언급할 가치가 있습니다. 많은 동적 인벤토리 플러그인은 모든 명령이 공급자 API를 호출하지 않도록 결과를 캐시할 수 있습니다. 캐싱은 실행 속도를 높이고 속도 제한 문제를 줄일 수 있지만, 또 다른 질문을 제기합니다: 인벤토리가 얼마나 오래되어도 괜찮은가? 배포 자동화의 경우 짧은 캐시가 괜찮을 수 있습니다. 스케일 이벤트 후 긴급 대응의 경우 인벤토리를 명시적으로 새로 고쳐야 할 수 있습니다.

전환은 위험한 일회성 전환으로 수행할 필요가 없습니다. 동적 인벤토리를 생성하고 정적 파일과 비교하는 것으로 시작하십시오. 그런 다음 동적 소스를 통해 읽기 전용 명령을 실행하십시오:

ansible -i aws_ec2.yml env_prod -m ping
ansible -i aws_ec2.yml env_prod -m setup -a "filter=ansible_hostname"

그런 다음 위험이 낮은 플레이북 하나를 이동하십시오. 팀이 그룹화 및 변수 동작을 신뢰할 때까지 이전 인벤토리를 유지하십시오. 최고의 인벤토리 전략은 운영자가 장애 중에 설명할 수 있는 전략이지, 종이에 가장 많은 자동화가 있는 전략이 아닙니다.