LabHub
배우기 러닝패스 코스

Ansible 실전 · 느린 플레이북의 정체 · 실습

플레이북이 느린 진짜 이유를 재고 나서 고친다

LabHub 에서 이어서 보기

목표

플레이북이 느린 이유를 콜백으로 먼저 재고, 팩트 수집·캐시·파이프라이닝·동시 실행·비동기라는 다섯 개의 손잡이를 차례로 돌립니다. 마지막에는 측정 결과에서 고칠 곳을 뽑아 주는 작은 도구를 직접 만듭니다.

왜 중요한가

"플레이북이 느리다" 는 신고는 늘 오지만 그 안에는 성격이 다른 원인이 섞여 있습니다. 대상 백 대에 팩트를 전부 모으느라 느린 것과, 태스크마다 SSH 를 세 번 왕복해서 느린 것과, 한 대가 십 분짜리 작업을 하는 동안 나머지 아흔아홉 대가 서서 기다려서 느린 것은 고치는 방법이 완전히 다릅니다. 그래서 순서가 중요합니다 — 먼저 재고, 그다음 고칩니다. 재지 않고 고치면 아는 데를 고치게 되고, 아는 데는 대개 병목이 아닙니다. 그리고 손잡이마다 대가가 있습니다. 캐시는 빠르지만 거짓 사실을 만들고, free 전략은 빠르지만 호스트 사이의 순서 약속을 깹니다. 이 실습은 각 손잡이를 돌려 보고 그 대가까지 함께 봅니다.

단계

1. /root/ansperf/ansible.cfg 에 기본 인벤토리를 ./inventory/hosts.ini 로 두고 ansible.posix.profile_tasks 콜백을 켜세요. /root/ansperf/inventory/hosts.ini 에는 web 그룹의 web1(work_sec 1)·web2(2)와 db 그룹의 db1(3)을 적습니다 (셋 다 ansible_host=127.0.0.1 ansible_port=2222, [all:vars]ansible_userroot). /root/ansperf/slow.yml 은 팩트를 모두 모으고 3초·2초·1초를 각각 쉬는 태스크 셋과 /root/ansperf/out/baseline.marker 를 쓰는 태스크 하나로 만드세요. 실행 결과를 /root/ansperf/out/profile_baseline.txt 에 저장합니다.
2. /root/ansperf/subsets.yml 을 만드세요 — 플레이 수준에서 gather_facts: false 로 자동 수집을 끄고, web1ansible.builtin.setup두 번 부릅니다. 한 번은 인자 없이 전부, 한 번은 gather_subset: [min] 으로 최소만 모읍니다. 각각 register 로 받아 /root/ansperf/out/facts_all.json/root/ansperf/out/facts_min.json 에 그 태스크가 돌려준 팩트를 JSON 으로 저장하고 실행하세요.
3. /root/ansperf/ansible.cfggathering = smart, fact_caching = ansible.builtin.jsonfile, fact_caching_connection = ./factcache, fact_caching_timeout = 3600 을 더하세요. 그리고 대상이 스스로 알려 주는 지역 팩트를 만듭니다 — /etc/ansible/facts.d/lab.fact[app] 절과 release=1.0.0 을 적으세요. /root/ansperf/release.ymlweb1ansible_local.lab.app.release 를 변수 outfile 이 가리키는 파일에 쓰는 플레이북입니다. 캐시 디렉터리를 비운 뒤 이 플레이북을 돌려 /root/ansperf/out/rel1.txt 를 남기세요.
4. 앞 단계가 끝난 지금 캐시에는 1.0.0 이 들어 있습니다. /etc/ansible/facts.d/lab.factrelease2.0.0 으로 올리세요. 플레이북을 그대로 다시 돌려 /root/ansperf/out/rel2_cached.txt 를 남기고, 이어서 캐시를 비우는 옵션을 붙여 다시 돌려 /root/ansperf/out/rel3_fresh.txt 를 남기세요. 세 파일의 값이 어떻게 갈리는지 직접 확인합니다.
5. /root/ansperf/ansible.cfg[ssh_connection] 절을 더하고 pipelining = True 를 켜세요. 그다음 기본값과 다른 설정을 전부 담은 출력(ansible-config dump --only-changed -t all)을 /root/ansperf/out/config.txt 에 저장하고, 파이프라이닝을 켠 채로 web1 에 애드혹 ping 이 되는지 확인하세요.
6. /root/ansperf/ansible.cfg[defaults]forks = 10 을 더하세요. /root/ansperf/free.yml 을 만듭니다 — strategy: free 이고 팩트는 모으지 않으며, 태스크 둘로 이루어집니다. 첫째는 그 호스트의 work_sec 만큼 쉬고, 둘째는 out/free-<호스트이름>.txt<호스트이름> <work_sec> 한 줄을 씁니다. 실행 출력은 /root/ansperf/out/free.txt 에 저장하세요.
7. /root/ansperf/async.yml 을 만드세요 — web1 에서 8초짜리 작업을 async: 120 poll: 0 으로 던져 놓고 register 로 받습니다. 그다음 태스크에서 /root/ansperf/out/meanwhile.txt 를 쓰고(그 사이에 할 일이 있다는 뜻입니다), ansible.builtin.async_status 로 끝날 때까지 기다린 뒤 그 결과를 /root/ansperf/out/async.json 에 JSON 으로 저장하고 실행하세요.
8. /root/ansperf/slowest.sh 를 만드세요 — 첫 인자로 받은 측정 출력 파일에서 콜백 요약을 읽어 오래 걸린 순서대로 <초>s <태스크이름> 을 한 줄씩 출력합니다. 몇 줄을 낼지는 둘째 인자로 받고 기본값은 3 입니다. 파일이 없으면 표준 오류에 알리고 0 이 아닌 값으로 끝냅니다. 이 도구를 1단계의 /root/ansperf/out/profile_baseline.txt 에 돌려 결과를 /root/ansperf/out/slowest.txt 에 저장하세요.

참고

단계 8개

  1. 고치기 전에 먼저 잰다
  2. 팩트 수집이 무엇을 들고 오는지 세어 본다
  3. 팩트를 파일에 캐시해 두 번째 실행을 건너뛴다
  4. 캐시가 만드는 거짓 사실
  5. SSH 왕복을 줄이고, 바뀐 설정을 파일로 남긴다
  6. 동시에 몇 대를 붙잡을지, 서로를 기다리게 할지
  7. 긴 작업은 던져 놓고 나중에 거둔다
  8. 측정 결과에서 고칠 곳을 뽑아 주는 도구