LabHub
배우기 러닝패스 코스

Ansible 실전 · 플레이북을 시험한다 · 실습

돌려 보기 전에 막는다 — 문법·린트·전제 조건을 관문으로

LabHub 에서 이어서 보기

목표

문법 검사가 통과시키는 나쁜 플레이북에서 출발해 ansible-lint 의 규칙과 프로파일로 한 층씩 끌어올리고, 예외를 가장 좁은 범위로 두는 법을 익히고, assert 로 전제 조건을 먼저 막고, 이 셋을 하나의 관문 스크립트로 묶습니다.

왜 중요한가

앤서블의 위험한 점은 잘못 쓴 플레이북도 잘 돌아간다는 것입니다. 이름 없는 태스크도, 파이프가 든 셸도, 권한을 안 정한 파일 쓰기도 전부 초록색으로 끝납니다. 문제는 여섯 달 뒤에 옵니다 — 리포트가 언제나 changed 라 아무도 안 읽게 되고, 서버마다 파일 권한이 달라지고, 실패한 태스크의 이름이 shell 이라 로그를 봐도 무엇이 죽었는지 모릅니다. 린트는 그 여섯 달을 커밋 직전으로 당겨 옵니다. 다만 린트를 켜는 순간 팀은 곧바로 다음 문제를 만납니다 — 지적이 수백 개 나오고, 그중 몇 개는 정말 예외가 필요합니다. 그때 저장소 전체에서 규칙을 끄는 것한 줄만 빼는 것을 구분하지 못하면 린트는 한 달 만에 껍데기가 됩니다. 이 실습은 그 구분과, 린트가 못 보는 것(값이 말이 되는가)을 assert 로 막는 자리까지 함께 세웁니다.

단계

1. /root/anslint/ansible.cfg 의 기본 인벤토리를 ./inventory/hosts.ini 로 두고, 그 파일에 web 그룹의 web1·web2 를 적으세요 (둘 다 ansible_host=127.0.0.1 ansible_port=2222, [all:vars]ansible_userroot). /root/anslint/messy.yml 에는 이름 없는 플레이 하나에 태스크 셋을 적습니다 — 이름 없이 파이프가 든 shell 태스크, 소문자로 시작하는 이름의 command: mkdir -p 태스크, copy: content=... dest=... 처럼 한 줄로 적은 태스크입니다. ansible-playbook --syntax-check messy.yml 을 돌려 출력을 /root/anslint/out/syntax.txt 에 저장하세요.
2. ansible-lint -f pep8 messy.yml 의 출력을 /root/anslint/out/lint_before.txt 에 저장하세요(한 줄에 지적 하나씩 나오는 형식입니다). 그다음 같은 파일을 JSON 형식으로 린트해 걸린 규칙 id 만 중복 없이 사전순으로 한 줄씩 /root/anslint/out/rules.txt 에 저장하세요.
3. /root/anslint/site.yml 을 새로 쓰세요 — 이름 있는 플레이 하나에 이름 있는 태스크 셋입니다. 첫째는 /root/anslint/out/data 디렉터리를 만들고, 둘째는 /root/anslint/out/app.confport=8080 한 줄을 쓰고, 셋째는 /root/anslint/out/upper-<호스트이름>.txt 에 그 호스트 이름을 대문자로 한 줄 씁니다. 셸 명령은 하나도 쓰지 않습니다. ansible-lint --profile basic site.yml 이 통과해야 하고, 플레이북을 실제로 돌려 출력을 /root/anslint/out/run.txt 에 저장하세요.
4. /root/anslint/site.yml 의 모든 모듈을 FQCN(ansible.builtin.<모듈>)으로 바꾸고, 파일과 디렉터리를 만드는 태스크마다 mode 를 적으세요. ansible-lint --profile production site.yml 이 통과해야 하고, 그 출력을 /root/anslint/out/lint_production.txt 에 저장하세요.
5. /root/anslint/site.yml 에 네 번째 태스크를 더하세요 — ansible.builtin.commandtar -czf /root/anslint/out/bundle.tgz -C /root/anslint/out app.conf 를 실행하고 changed_when: false 를 붙입니다. 린트는 이 태스크를 command-instead-of-module 로 잡는데, unarchive 모듈은 푸는 일만 하고 묶지는 못하므로 여기서는 셸 명령이 맞습니다. 그 한 줄만 규칙에서 빼는 주석을 달아 --profile production 을 다시 통과시키고, 플레이북을 다시 돌려 묶음을 실제로 만드세요.
6. /root/anslint/site.yml 에 다섯 번째 태스크를 더하세요 — 이름은 소문자로 시작하는 nginx health probe 이고, /root/anslint/out/health.txtok 한 줄을 씁니다. 그리고 /root/anslint/.ansible-lint 를 만들어 profile: production, exclude_pathsmessy.ymlout/, skip_listname[casing] 을 적으세요. 인자 없이 ansible-lint 를 돌려 디렉터리 전체가 통과하는 것을 확인하고 출력을 /root/anslint/out/lint_repo.txt 에 저장하세요.
7. /root/anslint/checks.yml 을 만드세요 — localhost 에서 팩트를 모으지 않고, 플레이 변수로 app_port: 8080, app_env: staging, allowed_envs: [staging, prod] 를 둡니다. 첫 태스크는 app_port 가 정수이고 1024 이상 65535 이하인지 확인하고, 둘째 태스크는 app_envallowed_envs 안에 있는지 확인합니다. 둘 다 ansible.builtin.assert 로 쓰고 fail_msgsuccess_msg 를 답니다. 기본값 그대로 돌린 출력을 /root/anslint/out/assert_ok.txt 에, -e app_port=80 으로 덮어써 돌린 출력을 /root/anslint/out/assert_fail.txt 에 저장하세요.
8. /root/anslint/gate.sh 를 만드세요 — 첫 인자로 받은 디렉터리(기본값은 현재 디렉터리)로 옮겨 가 세 가지를 차례로 확인합니다. 그 디렉터리 바로 아래의 *.yml 마다 문법 검사를 하고 OK syntax <파일> 또는 FAIL syntax <파일> 을 출력하고, 인자 없이 ansible-lint 를 돌려 OK lint 또는 FAIL lint 를 출력하고, checks.yml 이 있으면 그것을 돌려 OK assert 또는 FAIL assert 를 출력합니다. 하나라도 실패하면 0 이 아닌 값으로 끝납니다. 이 관문을 지금 디렉터리에서 돌려 출력을 /root/anslint/out/gate.txt 에 저장하세요.

참고

단계 8개

  1. 문법 검사를 통과하는 나쁜 플레이북
  2. 린트가 무엇을 잡는지 규칙 id 로 센다
  3. basic 프로파일까지 끌어올린다
  4. production 프로파일이 더 요구하는 두 가지
  5. 규칙은 살려 두고 한 줄만 뺀다
  6. 저장소 전체에 걸리는 규칙을 설정 파일에 적는다
  7. 값이 말이 되는지 플레이북 스스로 묻게 한다
  8. 세 층을 하나의 관문으로 묶는다