Generating Config Files With Jinja2
한국어 원문으로 표시합니다.
목표
환경마다 다른 설정 파일을 하나의 템플릿과 데이터로 분해하고, 렌더링 결과가 깔끔하고 검증된 상태로 배치되게 만듭니다.
왜 중요한가
설정 파일을 환경 수만큼 두면 그 파일들은 반드시 서로 달라집니다. 템플릿은 "틀은 하나, 데이터는 여럿"으로 그 분기를 없앱니다. 실무에서 템플릿을 망치는 것은 문법이 아니라 두 가지입니다. 하나는 공백 — 제어 구문이 남긴 빈 줄이 YAML 설정을 깨뜨립니다. 다른 하나는 매번 달라지는 렌더링 결과 — 타임스탬프 한 줄 때문에 파일이 매 실행마다 바뀌고, 핸들러가 매번 돌아 서비스가 매번 재시작됩니다. 마지막으로 validate 는 잘못된 설정이 서비스를 죽이는 경로를 막는 가장 싼 안전장치입니다. 자동 배포를 켜는 순간 이 옵션은 선택이 아닙니다.
단계
- 이 실습의 플레이북은
/root/ans/tpl/site.yml하나를 씁니다./root/ans/tpl/templates/basic.j2로/root/ans/tpl/out/basic.conf를 만드세요. 결과에service = checkout줄이 있어야 합니다. /root/ans/tpl/templates/filters.j2로/root/ans/tpl/out/filters.conf를 만드세요.UPPER=CHECKOUT,TIMEOUT=30(정의되지 않은 변수의 기본값),REPLICAS=3세 줄이 나와야 합니다./root/ans/tpl/templates/upstream.j2로/root/ans/tpl/out/upstream.conf를 만드세요. 백엔드 3개가server 10.0.0.11:8080;형태로 각각 한 줄씩 나와야 합니다.- 같은 템플릿을 다른 변수로 렌더링해
/root/ans/tpl/out/prod.conf(tls = on, debug 없음)와/root/ans/tpl/out/dev.conf(tls = off, debug 있음)를 만드세요. upstream.conf에 빈 줄이 하나도 없고server줄 앞에 불필요한 들여쓰기가 없게 공백을 제어하세요.{%- -%}를 쓰거나/root/ans/tpl/site.yml의template태스크에trim_blocks/lstrip_blocks를 켜면 됩니다./root/ans/tpl/templates/node.j2로/root/ans/tpl/out/node.conf를 만드세요.hostname,arch는 팩트에서,generated_for는inventory_hostname(=web1)에서 옵니다./root/ans/tpl/site.yml의template태스크에validate와backup: true를 붙여/root/ans/tpl/out/validated.conf를 만드세요. 내용은key=value한 줄입니다./root/ans/tpl/out/site.nginx를 만드세요.upstream checkout_backend {블록 안에 4칸 들여쓴server줄 3개, 그리고listen 8080;과server_name checkout.labhub.internal;이 각각 4칸 들여쓰기로 들어갑니다. 빈 줄은 1줄 이하여야 합니다.
참고
- 실습 파드는 실습마다 새로 뜹니다.
/root/ans/inventory/hosts.ini가 없으면 첫 실습에서 만든 것과 같은 인벤토리(web1·web2·db1,ansible_host=127.0.0.1,ansible_port=2222,ansible_user=root,[prod:children]에 web·db)를 먼저 다시 만드세요. 구조는/opt/lab/fixtures/ansible/inventory.sample.ini를 참고하면 됩니다. template모듈은src에 롤/플레이북 기준 상대 경로를,dest에 대상 경로를 받습니다.- 필터를 이어 쓸 수 있습니다:
{{ name | default('unknown') | upper }} - 흔한 실수 1:
{% for %}를 그대로 두어 결과에 빈 줄이 남는 것. - 흔한 실수 2: 템플릿에 시각이나 랜덤 값을 넣어 매번 결과가 달라지는 것. 그러면 멱등성이 깨집니다.
변수를 넣은 기본 템플릿 렌더링
이 실습의 플레이북은 /root/ans/tpl/site.yml 하나를 씁니다. /root/ans/tpl/templates/basic.j2 로 /root/ans/tpl/out/basic.conf 를 만드세요. 결과에 service = checkout 줄이 있어야 합니다.
{{ 변수 }} 로 값을 출력합니다. 결과에 Jinja2 구문이 남아 있으면 렌더링이 안 된 것입니다.
upper 와 default 필터 쓰기
/root/ans/tpl/templates/filters.j2 로 /root/ans/tpl/out/filters.conf 를 만드세요. UPPER=CHECKOUT, TIMEOUT=30(정의되지 않은 변수의 기본값), REPLICAS=3 세 줄이 나와야 합니다.
필터는 파이프로 잇습니다. 정의되지 않은 변수에 기본값을 주는 필터가 무엇인지 생각해 보세요.
리스트를 도는 반복 넣기
/root/ans/tpl/templates/upstream.j2 로 /root/ans/tpl/out/upstream.conf 를 만드세요. 백엔드 3개가 server 10.0.0.11:8080; 형태로 각각 한 줄씩 나와야 합니다.
{% for %} 와 {% endfor %} 사이에 반복할 줄을 둡니다. 백엔드 3개가 각각 한 줄이 되어야 합니다.
환경에 따라 다른 설정 내보내기
같은 템플릿을 다른 변수로 렌더링해 /root/ans/tpl/out/prod.conf(tls = on, debug 없음)와 /root/ans/tpl/out/dev.conf(tls = off, debug 있음)를 만드세요.
같은 템플릿을 다른 변수로 두 번 렌더링합니다. prod 에는 debug 가 나오면 안 됩니다.
공백 제어로 빈 줄 없애기
upstream.conf 에 빈 줄이 하나도 없고 server 줄 앞에 불필요한 들여쓰기가 없게 공백을 제어하세요. {%- -%} 를 쓰거나 /root/ans/tpl/site.yml 의 template 태스크에 trim_blocks/lstrip_blocks 를 켜면 됩니다.
{%- / -%} 또는 template 모듈의 trim_blocks/lstrip_blocks 를 쓰세요. 결과에 빈 줄이 하나도 없어야 합니다.
팩트와 inventory_hostname 쓰기
/root/ans/tpl/templates/node.j2 로 /root/ans/tpl/out/node.conf 를 만드세요. hostname, arch 는 팩트에서, generated_for 는 inventory_hostname(=web1)에서 옵니다.
팩트 변수는 ansible_ 로 시작합니다. 대상 이름은 inventory_hostname 입니다.
validate 와 backup 붙이기
/root/ans/tpl/site.yml 의 template 태스크에 validate 와 backup: true 를 붙여 /root/ans/tpl/out/validated.conf 를 만드세요. 내용은 key=value 한 줄입니다.
validate 는 %s 자리에 임시 파일 경로가 들어갑니다. 검사에 실패하면 배치되지 않습니다.
그룹 변수로 nginx 설정 통째로 만들기
/root/ans/tpl/out/site.nginx 를 만드세요. upstream checkout_backend { 블록 안에 4칸 들여쓴 server 줄 3개, 그리고 listen 8080; 과 server_name checkout.labhub.internal; 이 각각 4칸 들여쓰기로 들어갑니다. 빈 줄은 1줄 이하여야 합니다.
upstream 블록 안의 server 줄은 4칸 들여쓰기입니다. 공백 제어와 반복을 함께 써야 합니다.