Ansible 실전 · 템플릿(Jinja2) · 이론
Jinja2 — 데이터에서 설정 파일로
한 줄 요약
템플릿은 "환경마다 다른 설정 파일"을 하나의 틀 + 환경별 데이터로 분해한다.
왜 이게 필요했나
nginx 설정을 dev·stage·prod 각각 두면 세 파일이 서로 달라진다. 백엔드 서버가 늘 때마다 세 곳을 고쳐야 하고, 한 곳을 빠뜨리면 그 환경만 트래픽이 몰린다. 템플릿은 서버 목록을 데이터로 두고 틀을 한 번만 쓰게 만든다. 백엔드가 늘면 데이터 한 줄만 늘어난다.
어떻게 동작하나
Jinja2 에서 쓰는 문법은 세 가지뿐이다.
{{ 값 }}— 값 출력{% 제어 %}— if / for 같은 제어 구문{# 주석 #}— 렌더링되지 않는 주석
여기에 필터가 붙는다. {{ name | upper }}, {{ timeout | default(30) }}, {{ data | to_nice_json }} 처럼 파이프로 이어 쓴다. default 필터는 특히 중요하다 — 정의되지 않았을 수 있는 값에 안전한 대체값을 주어, 변수가 없을 때 <no value> 나 오류가 나가는 것을 막는다.
가장 자주 문제가 되는 것은 공백이다. {% for %} 같은 제어 구문은 그 자체가 한 줄을 차지하므로 렌더링 결과에 빈 줄이 남는다. YAML 설정이라면 이 빈 줄이 파일을 깨뜨리기도 한다. 해결책은 두 가지다. 구문에 {%- / -%} 를 써서 앞뒤 공백을 지우거나, template 모듈에 trim_blocks/lstrip_blocks 를 켜는 것이다.
template 모듈의 두 옵션도 알아 두면 사고를 막는다. validate 는 렌더링 결과를 지정한 명령으로 검사해 통과할 때만 배치한다. backup: true 는 덮어쓰기 전에 사본을 남긴다. 설정 파일을 자동으로 배포하는 순간, 잘못된 설정이 서비스를 죽이는 경로가 열린다. validate 는 그 경로를 막는 가장 싼 장치다.
현장에서 만나는 모습
첫째, 렌더링 결과가 매번 달라지는 템플릿. 타임스탬프를 주석에 넣으면 파일이 매번 바뀌어 핸들러가 매번 돌고 서비스가 매번 재시작된다. 이 한 줄 때문에 무중단 배포가 무너지는 사례가 흔하다.
둘째, 팩트를 쓰는 템플릿. ansible_facts 의 값을 그대로 쓰면 서버마다 다른 설정이 자동으로 나온다. 다만 특수 환경에서는 팩트가 예상 밖 값을 내므로 default 로 방어선을 둔다.
셋째, 템플릿에 로직을 너무 많이 넣기. if 가 다섯 겹 쌓이면 그것은 템플릿이 아니라 프로그램이다. 그런 분기는 변수 계산 단계로 끌어올려 템플릿은 단순하게 유지하는 편이 유지보수에 낫다.
다음 실습에서 할 것
기본 렌더링에서 시작해 필터·반복·조건을 차례로 쓰고, 공백 제어로 결과를 깔끔하게 만든다. 팩트와 inventory_hostname 을 템플릿에서 쓰고, validate 로 잘못된 설정이 배치되지 않게 막는다. 마지막에는 그룹 변수의 백엔드 목록에서 nginx 설정을 통째로 생성한다.