ロール — 規約で畳む再利用の単位
한국어 원문으로 표시합니다.
한 줄 요약
롤은 플레이북 조각을 정해진 디렉터리 이름에 나눠 담은 것이고, 그 규약 덕분에 설정 없이 재사용된다.
왜 이게 필요했나
플레이북 하나에 nginx 설치, 앱 배포, 로그 로테이션, 모니터링 에이전트까지 다 넣으면 300줄이 된다. 그다음 두 번째 서비스가 생기면 사람들은 그 파일을 복사한다. 복사된 순간부터 두 파일은 서로 다른 속도로 늙는다. 6개월 뒤 "왜 A 서버만 로그가 안 지워지지"의 답은 언제나 "복사본이 갱신되지 않아서"다.
롤은 이 문제를 "재사용 단위를 파일 시스템 구조로 강제한다"로 푼다. 롤 안에서 태스크·기본값·핸들러·템플릿이 각자의 자리를 가지므로, 남이 만든 롤도 열어 보지 않고 어디에 무엇이 있는지 안다.
어떻게 동작하나
| 디렉터리 | 담는 것 | 자동 로드 |
|---|---|---|
tasks/main.yml |
실행할 태스크 | 롤 호출 시 |
defaults/main.yml |
덮어쓰기를 기대하는 기본값 | 가장 낮은 우선순위 |
vars/main.yml |
바뀌면 안 되는 내부 값 | 높은 우선순위 |
handlers/main.yml |
핸들러 | 자동 등록 |
templates/ |
Jinja2 템플릿 | template 모듈이 경로 없이 찾음 |
files/ |
그대로 복사할 파일 | copy 모듈이 경로 없이 찾음 |
meta/main.yml |
의존 롤, 메타데이터 | 의존 롤을 먼저 실행 |
핵심은 defaults 와 vars 의 구분이다. 사용자가 바꿀 것 같은 값은 반드시 defaults 에 둔다. vars 에 두면 우선순위가 높아 밖에서 덮어쓰기가 사실상 불가능해지고, 그 롤은 재사용할 수 없게 된다.
meta/main.yml 의 dependencies 는 "이 롤 전에 저 롤이 필요하다"를 선언한다. 같은 의존 롤이 여러 번 나와도 기본적으로 한 번만 실행된다.
현장에서 만나는 모습
첫째, 이름 충돌. 롤이 여러 개면 변수 이름이 겹친다. 그래서 롤 변수에는 롤 이름을 접두어로 붙이는 것이 관례다 — port 가 아니라 webapp_port.
둘째, 롤 안에서 절대 경로를 쓰지 않기. templates/ 와 files/ 는 롤 기준으로 자동 탐색되므로 파일 이름만 적으면 된다. 절대 경로를 박으면 그 롤은 그 서버에서만 동작한다.
셋째, 롤도 멱등해야 한다. 롤을 쓰는 플레이북을 두 번 돌려 changed=0 이 나오는지 확인하는 습관은 롤에서도 그대로다.
변수 우선순위가 사고를 만든다
앤서블의 변수는 스물두 단계의 우선순위가 있습니다. 전부 외울 필요는 없지만 자주 부딪히는 다섯 개의 순서 는 알아야 합니다(아래로 갈수록 강함).
1. 롤의 defaults/main.yml ← 가장 약하다. 덮어쓰라고 있는 것
2. inventory group_vars
3. inventory host_vars
4. play 의 vars
5. -e (extra vars) ← 가장 강하다. 무엇도 못 이긴다
여기서 나오는 규칙 둘입니다.
- 롤의 기본값은
defaults/에 둡니다.vars/에 두면 우선순위가 높아 사용자가 덮어쓸 수 없습니다. "롤 변수를 바꿨는데 반영이 안 된다" 의 원인이 대개 이것입니다. -e는 디버깅용입니다. 스크립트에 상시로 넣으면 인벤토리 설정이 전부 무시되어, 나중에 왜 그 값이 나오는지 아무도 못 찾습니다.
값이 어디서 왔는지는 물어보면 됩니다.
ansible -i inv host -m debug -a "var=app_port"
ansible-inventory -i inv --host web-01 --yaml # 그 호스트에 적용된 전부
멱등성을 깨는 모듈
앤서블의 값어치는 "두 번 돌려도 같다" 입니다. 이것을 깨는 것이 몇 가지 있습니다.
| 쓰면 안 되는 것 | 대신 |
|---|---|
shell: echo x >> /etc/hosts |
lineinfile, blockinfile |
command: mkdir /opt/app |
file: state=directory |
shell: sed -i … |
lineinfile, template |
command: curl … | bash |
get_url + command (검증 후) |
셸을 꼭 써야 한다면 creates 나 removes 로 조건을 겁니다.
- name: 설치 스크립트 (한 번만)
command: /opt/setup.sh
args:
creates: /opt/.installed # 이 파일이 있으면 건너뛴다
changed_when: false 는 다른 이야기입니다. 그것은 "이 명령은 상태를 안 바꾼다"
는 선언이라 조회 명령에만 씁니다. 실제로 바꾸는 명령에 붙이면 리포트가 거짓말을
하게 됩니다.
롤을 나누는 기준
한 롤이 커지면 나누고 싶어지는데, 기준이 없으면 조각만 늘어납니다.
- 다른 곳에서 그대로 쓸 수 있는가 — 없으면 나눌 이유가 없습니다.
- 의존이 한 방향인가 — 롤 A 가 B 를, B 가 A 를 부르면 순환입니다.
- 변수 이름이 겹치지 않는가 — 롤마다 접두를 붙입니다(
nginx_port).
세 번째가 실무의 함정입니다. 두 롤이 port 라는 변수를 쓰면 나중 것이 이깁니다.
앤서블은 경고하지 않습니다. 롤 이름을 접두로 붙이는 관례 가 이것을 막습니다.
다음 실습에서 할 것
webapp 롤을 뼈대부터 만들어 기본값·태스크·템플릿·핸들러를 채우고, baseline 롤을 의존으로 걸어 실행 순서를 확인한다. 같은 롤을 다른 변수로 두 번 호출해 재사용성을 증명하고, 두 번째 실행에서 changed=0 을 만든다.