LabHub
学习 学习路径 课程

Ansible 实战

分批并委托给负载均衡器,做一次不停机发布

在 LabHub 中继续学习

한국어 원문으로 표시합니다.

목표

호스트 집합을 배치로 쪼개고, 배포 중인 서버를 로드밸런서에서 빼고 넣고, 배치마다 상태를 판정해 사고가 다음 배치로 번지지 않게 하는 플레이북을 쓸 수 있게 됩니다.

왜 중요한가

기본 동작에서 Ansible 은 태스크 하나를 전 호스트에서 끝내고 다음 태스크로 갑니다. 서비스를 재시작하는 태스크가 있으면 그 순간 전 호스트가 함께 내려갑니다. 그래서 무중단 배포는 도구가 아니라 플레이북의 구조로 만듭니다. 쪼개고(serial), 빼고 넣고(delegate_to), 배치마다 판정합니다(max_fail_percentage). 이 중 하나만 빠져도 무중단이 아닙니다 - 빼지 않으면 요청이 배포 중인 서버로 들어가고, 판정하지 않으면 망가진 판이 남은 서버로 번집니다. 그리고 serial 을 걸면 run_once 와 핸들러의 의미까지 조용히 바뀝니다. 그 사실을 모르고 쓰면 '한 번만 돌 줄 알았던 태스크' 가 배치 수만큼 돕니다.

단계

  1. /root/ans/roll/inventory/hosts.ini 에 web 그룹(web1·web2·web3, ansible_host=127.0.0.1, ansible_port=2222)과 lb 그룹(lb1, ansible_connection=local)을 적으세요. /root/ans/roll/p01.ymlserial: 2 를 걸고, 호스트마다 자기 배치의 구성원을 쉼표로 이어 /root/ans/roll/out/01-<호스트>.txt 에 적게 하세요.
  2. /root/ans/roll/p02.ymlserial 을 목록 [1, 100%] 로 주어 카나리 배치를 만들고, 1단계와 같은 방식으로 /root/ans/roll/out/02-<호스트>.txt 에 배치 구성원을 적으세요.
  3. /root/ans/roll/p03.ymlserial: 2 를 걸고, run_once: truedelegate_to: lb1 을 붙인 태스크 하나로 /root/ans/roll/out/03-runonce.txtbatch <배치구성원> ran on <실행한호스트> 형식의 줄을 남기세요.
  4. /root/ans/roll/p04.ymlserial: 1 로 만들고, 모든 태스크를 lb1 로 위임/root/ans/roll/out/lb/ 디렉터리를 만든 뒤 호스트마다 drained-<호스트>.txtenabled-<호스트>.txt 를 각각 host=<호스트> 내용으로 남기세요.
  5. /root/ans/roll/p05.yml 에서 delegate_to: lb1delegate_facts: true 를 함께 준 set_factlb_pool_size 를 플레이 대상 수로 세우고, 그 값을 hostvars 로 읽어 /root/ans/roll/out/05-lbfact.txtlb_pool_size=<값> on_web=<웹 호스트에서 본 값> 형식으로 남기세요. 웹 호스트 쪽에는 값이 없어야 합니다.
  6. /root/ans/roll/p06.ymlserial: 2 로 만들고, 호스트마다 /root/ans/roll/out/06-<호스트>.conf 를 놓는 태스크가 핸들러를 부르게 하세요. 핸들러는 run_once: truedelegate_to: lb1/root/ans/roll/out/06-handlers.txtrestarted: <배치구성원> 줄을 남깁니다.
  7. /root/ans/roll/p07.ymlserial: 1 · max_fail_percentage: 0 으로 만들고, 플레이 varshealthy_hosts[web1, web3] 으로 두세요. 태스크는 /root/ans/roll/out/07-deployed-<호스트>.txt 를 남기는 배포 표식과 healthy_hosts 에 들어 있는지를 보는 assert 확인 둘입니다. 실행 출력을 /root/ans/roll/out/07-run.txt 로 저장하세요.
  8. /root/ans/roll/p08.yml 에 플레이 둘을 두세요. 첫 플레이는 web 을 serial: [1, 100%] · max_fail_percentage: 0 으로 돌며 배치 기록을 /root/ans/roll/out/08-batches.txt 에 남기고, 호스트마다 /root/ans/roll/out/08/ 아래에 drained-·release-(내용 release=2.4.0enabled- 표식을 남기고 그 사이에 assert 로 상태를 확인합니다(세 대 모두 정상). 둘째 플레이는 lb1 에서 그 기록을 모아 /root/ans/roll/out/rolling.jsonbatches·drained·enabled 를 적습니다. 마지막으로 같은 플레이북을 한 번 더 돌려 출력을 /root/ans/roll/out/08-run2.txt 에 저장하되 changed=0 이어야 합니다.

참고

두 대씩 끊어 올리기

/root/ans/roll/inventory/hosts.ini 에 web 그룹(web1·web2·web3, ansible_host=127.0.0.1, ansible_port=2222)과 lb 그룹(lb1, ansible_connection=local)을 적으세요. /root/ans/roll/p01.ymlserial: 2 를 걸고, 호스트마다 자기 배치의 구성원을 쉼표로 이어 /root/ans/roll/out/01-<호스트>.txt 에 적게 하세요.

지금 배치에 누가 들어와 있는지는 실행 중에 변수로 알 수 있습니다. ansible_play_batch 를 쉼표로 이어 적으면 배치가 어떻게 나뉘었는지가 파일에 남습니다.

카나리 한 대 먼저, 나머지 한 번에

/root/ans/roll/p02.ymlserial 을 목록 [1, 100%] 로 주어 카나리 배치를 만들고, 1단계와 같은 방식으로 /root/ans/roll/out/02-<호스트>.txt 에 배치 구성원을 적으세요.

목록의 원소는 숫자와 비율을 섞어 쓸 수 있습니다. 마지막 원소를 100% 로 두면 '남은 전부' 라는 뜻이 됩니다.

run_once 는 배치마다 한 번이다

/root/ans/roll/p03.ymlserial: 2 를 걸고, run_once: truedelegate_to: lb1 을 붙인 태스크 하나로 /root/ans/roll/out/03-runonce.txtbatch <배치구성원> ran on <실행한호스트> 형식의 줄을 남기세요.

같은 줄을 여러 번 돌려도 파일이 늘어나지 않아야 합니다. 줄 단위로 '없으면 넣는' 모듈을 쓰세요. 몇 줄이 나오는지 세어 보면 run_once 의 범위가 드러납니다.

로드밸런서에서 빼고 다시 넣기

/root/ans/roll/p04.ymlserial: 1 로 만들고, 모든 태스크를 lb1 로 위임/root/ans/roll/out/lb/ 디렉터리를 만든 뒤 호스트마다 drained-<호스트>.txtenabled-<호스트>.txt 를 각각 host=<호스트> 내용으로 남기세요.

위임된 태스크 안에서도 대상은 원래 호스트입니다. 파일 이름과 내용에 그 이름을 그대로 쓰면 '누구를 뺐는지' 가 로드밸런서 쪽 기록에 남습니다. 이 단계에서는 배치마다가 아니라 호스트마다 일어나야 합니다.

사실을 누구 앞으로 적을 것인가

/root/ans/roll/p05.yml 에서 delegate_to: lb1delegate_facts: true 를 함께 준 set_factlb_pool_size 를 플레이 대상 수로 세우고, 그 값을 hostvars 로 읽어 /root/ans/roll/out/05-lbfact.txtlb_pool_size=<값> on_web=<웹 호스트에서 본 값> 형식으로 남기세요. 웹 호스트 쪽에는 값이 없어야 합니다.

플레이 대상 수는 실행 중에 변수로 알 수 있습니다. 웹 호스트 쪽에서 같은 이름을 읽을 때는 없을 수도 있으니 기본값을 주어 없음 이 찍히게 하세요.

핸들러는 플레이 끝이 아니라 배치 끝에 돈다

/root/ans/roll/p06.ymlserial: 2 로 만들고, 호스트마다 /root/ans/roll/out/06-<호스트>.conf 를 놓는 태스크가 핸들러를 부르게 하세요. 핸들러는 run_once: truedelegate_to: lb1/root/ans/roll/out/06-handlers.txtrestarted: <배치구성원> 줄을 남깁니다.

핸들러는 이름으로 이어집니다. 몇 줄이 남는지 세어 보면 핸들러가 언제 도는지 알 수 있습니다 - 플레이 끝에 한 번이라면 한 줄이어야 합니다.

한 대가 무너지면 거기서 멈춘다

/root/ans/roll/p07.ymlserial: 1 · max_fail_percentage: 0 으로 만들고, 플레이 varshealthy_hosts[web1, web3] 으로 두세요. 태스크는 /root/ans/roll/out/07-deployed-<호스트>.txt 를 남기는 배포 표식과 healthy_hosts 에 들어 있는지를 보는 assert 확인 둘입니다. 실행 출력을 /root/ans/roll/out/07-run.txt 로 저장하세요.

이 플레이북은 일부러 실패합니다. 출력을 파일로 받을 때 실패로 스크립트가 멈추지 않게 하세요. 세 번째 호스트의 배포 표식이 생기는지 아닌지가 이 단계의 답입니다.

한 바퀴를 돌고 요약을 남긴다

/root/ans/roll/p08.yml 에 플레이 둘을 두세요. 첫 플레이는 web 을 serial: [1, 100%] · max_fail_percentage: 0 으로 돌며 배치 기록을 /root/ans/roll/out/08-batches.txt 에 남기고, 호스트마다 /root/ans/roll/out/08/ 아래에 drained-·release-(내용 release=2.4.0enabled- 표식을 남기고 그 사이에 assert 로 상태를 확인합니다(세 대 모두 정상). 둘째 플레이는 lb1 에서 그 기록을 모아 /root/ans/roll/out/rolling.jsonbatches·drained·enabled 를 적습니다. 마지막으로 같은 플레이북을 한 번 더 돌려 출력을 /root/ans/roll/out/08-run2.txt 에 저장하되 changed=0 이어야 합니다.

빼기와 넣기는 로드밸런서에 위임하고 배포는 대상에서 합니다. 표식을 세는 것은 파일을 찾는 모듈로, 배치 기록을 읽는 것은 파일을 읽어 오는 모듈로 하면 두 번째 플레이가 짧아집니다. 두 번째 실행이 조용하려면 모든 태스크가 멱등해야 합니다.