best-practice
디렉터리 레이아웃⚑
- 디렉토리의 최상위 수준에는 다음과 같은 파일과 디렉토리로 디자인합니다.
production # 프로덕션 인벤토리
staging # 스테이징 인벤토리
group_vars/
├─ group1.yml # 그룹별 변수
└─ group2.yml
host_vars/
├─ hostname1.yml # 호스트별 변수
└─ hostname2.yml
library/ # 커스텀 모듈 (optional)
module_utils/ # 모듈 유틸리티 (optional)
filter_plugins/ # 필터 플러그인 (optional)
site.yml # 마스터 플레이북
webservers.yml # 웹서버 계층 플레이북
dbservers.yml # DB서버 계층 플레이북
roles/
├─ common/
│ ├─ tasks/ # main.yml 등
│ ├─ handlers/ # main.yml
│ ├─ templates/ # .j2 템플릿
│ ├─ files/ # 스크립트·파일
│ ├─ vars/ # 역할 변수
│ ├─ defaults/ # 기본 변수
│ └─ meta/ # 의존성 정의
├─ webtier/
├─ monitoring/
└─ fooapp/
대체 디렉터리 레이아웃⚑
- 인벤토리별로
group_vars/
·host_vars/
를 완전 분리할 때 유용합니다.
inventories/
├─ production/
│ ├─ hosts
│ ├─ group_vars/
│ └─ host_vars/
└─ staging/
├─ hosts
├─ group_vars/
└─ host_vars/
library/
module_utils/
filter_plugins/
site.yml
webservers.yml
dbservers.yml
roles/
├─ common/
├─ webtier/
├─ monitoring/
└─ fooapp/
클라우드에서 동적 인벤토리 사용⚑
- 클라우드 환경에서는 정적 파일 대신 동적 인벤토리를 사용하세요.
- 자체 시스템에서 관리하는 호스트 목록에도 적용 가능합니다.
인벤토리 파일
- Ansible에서 "인벤토리"는 단순히
.ini
파일만을 의미하지 않습니다. - 인벤토리는 Ansible이 인식 가능한 여러 형식(Format)으로 작성된 서버(호스트) 및 그룹 정의 정보를 뜻합니다. 즉,
.ini
는 가장 기본적인 표현 방식 중 하나일 뿐이며, 다양한 포맷이 존재합니다.
인벤토리 형식 종류
형식 | 확장자 | 설명 |
---|---|---|
INI (기본형) | 없음 또는 .ini | [group] 섹션 기반의 간단한 포맷. 전통적으로 가장 널리 사용됨 |
YAML | .yml , .yaml | 구조화된 형식. 동적 인벤토리나 plugin 기반에서 선호됨 |
JSON | .json | 잘 사용되진 않지만 지원됨 |
Python script | .py | 동적 인벤토리용. AWS, GCP, K8s 등 외부 리소스에서 정보를 수집함 |
Inventory Plugin | .yml | Ansible 2.8+ 이후 공식 방식. aws_ec2 , gcp_compute 등 사용 |
예시 1: INI 형식 인벤토리
[webservers]
web1.example.com
web2.example.com
예시 2: YAML 형식 인벤토리
all:
children:
webservers:
hosts:
web1.example.com:
web2.example.com:
요약 정리
질문 | 답변 |
---|---|
인벤토리 = ini 파일인가요? | ❌ 아니며, .ini 는 인벤토리를 표현하는 방식 중 하나일 뿐입니다. |
실무에서 가장 많이 쓰는 형식은? | ✅ .ini 형식이 여전히 가장 널리 쓰입니다. 그러나 YAML 기반 plugin 사용도 점점 증가하는 추세입니다. |
디렉토리 자체가 인벤토리 될 수 있나? | ✅ 예. inventory/production/ 구조처럼 hosts , group_vars/ , host_vars/ 를 포함하면 디렉토리 전체를 인벤토리로 지정할 수 있습니다. |
동적 인벤토리
동적 인벤토리는 클라우드나 외부 시스템의 실시간 정보를 기반으로 인벤토리를 생성하는 방식입니다. 스크립트 기반 또는 YAML 기반(Plugin)으로 구현할 수 있으며, 대표적으로 AWS, GCP, Azure, Kubernetes 환경에서 많이 사용됩니다.
스크립트 기반 (예: AWS EC2) Ansible에서 제공하는 aws_ec2.py
스크립트를 사용해 EC2 인스턴스를 실시간으로 조회할 수 있습니다.
pip install boto3 botocore
ansible-inventory -i aws_ec2.py --list
ansible-playbook -i aws_ec2.py site.yml
YAML 기반 Plugin (권장) Ansible 공식 aws_ec2
Plugin을 이용해 YAML 파일 하나만으로도 자동 인벤토리를 구성할 수 있습니다.
inventory/
└── aws_ec2.yml
plugin: aws_ec2
regions:
- ap-northeast-2
filters:
tag:Environment: production
hostnames:
- private-ip-address
keyed_groups:
- key: tags.Name
ansible-inventory -i inventory/aws_ec2.yml --list
ansible-playbook -i inventory/aws_ec2.yml site.yml
기타 유용한 Inventory Plugins
plugin 이름 | 설명 |
---|---|
aws_ec2 | AWS EC2 인스턴스를 인벤토리로 자동화 |
gcp_compute | GCP VM 인스턴스를 자동 수집 |
k8s | Kubernetes Node/Pod 인벤토리 |
constructed | 기존 인벤토리에서 조건 기반으로 그룹 구성 |
ini, yaml | 전통적인 INI / YAML 정적 인벤토리 포맷 |
host_list, script | 임시 생성 리스트 또는 커스텀 스크립트 기반 인벤토리 |
실무 추천 요약
환경/상황 | 추천 방식 |
---|---|
온프레미스 수동 서버 관리 | INI 인벤토리 + group_vars/ , host_vars/ |
클라우드 자동화 환경 | YAML 기반 Inventory Plugin (aws_ec2 , gcp_compute 등) |
혼합 환경 | constructed , meta , script 플러그인 조합하여 활용 |
스테이징 vs 프로덕션 구분 방법⚑
- 각각의 환경에 별도 인벤토리 파일(
production
,staging
)을 두고-i
플래그로 선택 - 그룹과 지리적 위치를 적절히 조합해 정의
# ini
[atlanta_webservers]
www-atl-1.example.com
...
[webservers:children]
atlanta_webservers
boston_webservers
그룹 변수 및 호스트 변수⚑
group_vars/<group>.yml
에 그룹 단위 변수 정의host_vars/<hostname>.yml
에 호스트 단위 변수 정의- 공통 변수는
group_vars/all.yml
에
# group_vars/all.yml
ntp: ntp-boston.example.com
backup: backup-boston.example.com
그룹 변수 및 호스트 변수 예시
1. 인벤토리 예시 (production)⚑
webservers
가 그룹 이름이고, 그 아래에 속한web1.example.com
,web2.example.com
이 해당 그룹에 속한 호스트(서버)
# ini
[webservers]
web1.example.com
web2.example.com
[dbservers]
db1.example.com
2. group_vars 디렉토리 구조 및 내용⚑
group_vars/
├─ all.yml
├─ webservers.yml
└─ dbservers.yml
- group_vars/all.yml
ntp_server: ntp-boston.example.com
backup_server: backup-boston.example.com
- group_vars/webservers.yml
http_port: 80
max_clients: 200
- group_vars/dbservers.yml
db_port: 3306
db_backup_path: /var/backups/mysql
3. 플레이북 예시 (webservers.yml)⚑
- hosts: webservers
roles:
- common
- webtier
tasks:
- name: Show HTTP port
debug:
msg: "HTTP port is {{ http_port }}"
- name: Show NTP server
debug:
msg: "NTP server is {{ ntp_server }}"
설명⚑
group_vars/all.yml
에 정의된 변수는 모든 호스트에 공통으로 적용됩니다.group_vars/webservers.yml
에 정의된 변수는webservers
그룹에 속한 호스트에만 적용됩니다.- 플레이북이나 역할 내에서 별도 변수 선언 없이
{{ http_port }}
,{{ ntp_server }}
등으로 바로 참조 가능합니다. - 이렇게 하면 환경별, 그룹별 변수 관리를 깔끔하게 분리할 수 있습니다.
최상위 플레이북 역할별 분리⚑
- site.yml
- import_playbook: webservers.yml
- import_playbook: dbservers.yml
- webservers.yml
- hosts: webservers
roles:
- common
- webtier
ansible-playbook site.yml --limit webservers
로 부분 실행도 가능 역할별 태스크 및 핸들러 구성⚑
- roles/common/tasks/main.yml
- name: be sure ntp is installed
yum:
name: ntp
state: present
tags: ntp
# …
- name: restart ntpd
service:
name: ntpd
state: restarted
이러한 구성으로 가능한 것들⚑
# 전체 인프라 재구성
ansible-playbook -i production site.yml
# NTP만 재구성
ansible-playbook -i production site.yml --tags ntp
# 웹서버만 재구성
ansible-playbook -i production webservers.yml
# 보스턴 웹서버만
ansible-playbook -i production webservers.yml --limit boston
배포 vs 구성 조직⚑
- OS 구성(playbook)과 애플리케이션 배포(playbook)를 분리
deploy_*.yml
같은 별도 플레이북으로 멀티티어 배포 처리
롤링 업데이트⚑
- hosts: webservers
serial: 3 # 한 번에 3대씩 업데이트
roles:
- fooapp
항상 state 명시⚑
yum:
name: ntp
state: present # 명시적으로 작성
역할별 그룹화⚑
hosts: webservers
- 그룹화를 통해 대상 지정 및 그룹 변수 관리 용이
운영체제 및 배포판 차이 처리⚑
- name: OS별 동적 그룹 생성
group_by:
key: os_{{ ansible_facts['distribution'] }}
group_vars/os_CentOS.yml
등으로 OS별 변수 자동 적용
플레이북과 함께 모듈 번들링⚑
./library/ # 플레이북 경로 하위에 library 디렉터리 두기
공백 및 주석 활용⚑
#
주석과 빈 줄을 적절히 사용해 가독성 확보
태스크 항상 이름 지정⚑
- name: Install nginx
apt:
name: nginx
state: latest
단순하게 유지하기⚑
- 필요한 기능만 사용
- 복잡해지면 구조를 단순화할 기회로 판단
버전 관리⚑
- Git 등으로 플레이북·인벤토리 관리
- 변경 이력·사유 추적
변수 및 Vault⚑
group_vars/<group>/vars.yml
에 일반 변수group_vars/<group>/vault.yml
에 민감 변수 (vault_
접두어)vars.yml
에서 Jinja2로vault_
변수 참조vault.yml
은 암호화하여 커밋
역할 간 의존성 관리⚑
- 역할(role) 간에 실행 순서나 의존성이 있을 경우, 각 역할의
meta/main.yml
파일에dependencies
항목으로 명시합니다. - 예를 들어,
k3s
역할이secrets
역할에 의존한다면roles/k3s/meta/main.yml
에 다음과 같이 작성합니다.
dependencies:
- role: secrets
- 이렇게 하면
k3s
역할을 실행할 때 자동으로secrets
역할이 먼저 실행되어 필요한 초기 설정(예: SSH 키, 시크릿 등)이 적용된 후k3s
설치가 진행됩니다. - 역할 간 의존성 관리는 플레이북 내 역할 호출 순서와 별개로 역할 내부에서 명확히 정의할 수 있어 유지보수와 재사용성에 유리합니다.