일반적인 팁

일반적인 팁 (General tips)

이 개념은 모든 Ansible 활동과 산출물(playbook, roles, inventory, variables)에 적용돼요. Ansible을 오래 잘 쓰기 위한 기본기를 다지는 팁들이라고 보면 돼요.

출처: 문서

본문

심플하게 유지하기 (Keep it simple)

가능하면 언제나 일을 단순하게 하세요. 고급 기능은 꼭 필요할 때만 사용하고, 자신의 사용 사례에 가장 잘 맞는 기능을 선택하세요.

예를 들어 vars, vars_files, vars_prompt, --extra-vars를 모두 동시에 쓰면서 외부 인벤토리 파일까지 쓸 일은 아마 없을 거예요. 어떤 것이 복잡하게 느껴진다면, 사실 복잡한 것이니까 더 단순한 해결책을 찾는 시간을 가져 보세요.

버전 관리를 사용하기 (Use version control)

플레이북, 롤, 인벤토리, 변수 파일을 git이나 다른 버전 관리 시스템에 두고, 변경할 때마다 의미 있는 코멘트와 함께 커밋하세요. 버전 관리는 여러분이 인프라를 자동화하는 규칙을 언제, 왜 바꿨는지 설명하는 감사 추적(audit trail)을 제공해 줘요.

CLI 출력 사용자화하기 (Customize the CLI output)

Ansible CLI 명령의 출력은 Callback 플러그인을 사용해 바꿀 수 있어요.

설정 의존 콘텐츠 피하기 (Avoid configuration-dependent content)

자동화 프로젝트를 이해·수정·공유하기 쉽게 만들려면 설정 의존적인 콘텐츠를 피해야 해요. 예를 들어 프로젝트의 루트로 ansible.cfg를 참조하는 대신, playbook_dir이나 role_name 같은 매직 변수를 사용해 프로젝트 디렉터리 내의 알려진 위치를 기준으로 경로를 결정할 수 있어요. 이렇게 하면 자동화 콘텐츠를 유연하고, 재사용 가능하며, 유지 관리하기 쉽게 유지할 수 있어요. 자세한 내용은 특별 변수(special variables)를 참고하세요.

플레이북 팁 (Playbook tips)

이 팁들은 플레이북과 롤을 더 읽기 쉽고, 유지·디버그하기 쉽게 만들어 줘요.

공백 활용하기 (Use whitespace)

블록이나 작업 앞에 빈 줄 하나를 두는 것처럼 공백을 넉넉히 사용하면 플레이북을 훑어보기 쉬워져요.

플레이·작업·블록에 항상 이름 붙이기

플레이, 작업, 블록의 - name: 은 선택 사항이지만 매우 유용해요. Ansible은 출력에서 실행하는 각 이름 있는 개체의 이름을 보여주거든요. 각 플레이·작업·블록이 무엇을 하는지, 왜 하는지 설명하는 이름을 선택하세요.

항상 상태(state)를 명시하기

많은 모듈에서 state 파라미터는 선택 사항이에요. 모듈마다 state의 기본 설정이 다르고, 일부 모듈은 여러 state 설정을 지원하죠. state: presentstate: absent를 명시적으로 설정하면 플레이북과 롤이 훨씬 명확해져요.

코멘트 사용하기 (Use comments)

작업 이름과 명시적 state가 있더라도, 플레이북·롤(또는 인벤토리/변수 파일)의 일부에 더 많은 설명이 필요할 때가 있어요. #로 시작하는 어떤 줄이든 코멘트를 추가하면 다른 사람들(그리고 나중의 자신)이 플레이·작업(또는 변수 설정)이 무엇을, 어떻게, 왜 하는지 이해하는 데 도움이 돼요.

완전한 컬렉션 이름(FQCN) 사용하기

각 작업에 올바른 모듈이나 플러그인을 어떤 컬렉션에서 찾을지의 모호함을 피하려면 완전한 컬렉션 이름(FQCN)을 사용하세요. 빌트인 모듈과 플러그인에는 ansible.builtin 컬렉션 이름을 접두사로 사용해요. 예를 들어 ansible.builtin.copy처럼요.

인벤토리 팁 (Inventory tips)

이 팁들은 인벤토리를 잘 정리된 상태로 유지하는 데 도움이 돼요.

클라우드에서는 동적 인벤토리 사용하기

인프라의 정식 목록을 유지하는 클라우드 프로바이더나 다른 시스템에서는, 정적 인벤토리 파일을 수동으로 업데이트하는 대신 동적 인벤토리로 그 목록을 가져오세요. 클라우드 리소스에서는 태그를 사용해 프로덕션과 스테이징 환경을 구분할 수 있어요.

인벤토리를 기능별로 그룹화하기

하나의 시스템은 여러 그룹에 속할 수 있어요. "How to build your inventory"와 "Patterns: targeting hosts and groups"를 참고하세요. 그룹의 노드 기능 이름(예: webservers, dbservers)으로 그룹을 만들면, 플레이북이 기능을 기준으로 머신을 대상으로 삼을 수 있어요. 그룹 변수 시스템으로 기능별 변수를 할당하고, 기능별 사용 사례를 다루는 Ansible 롤을 설계할 수 있어요. Role 문서를 참고하세요.

프로덕션과 스테이징 인벤토리 분리하기

각 환경에 별도의 인벤토리 파일이나 디렉터리를 사용하면 프로덕션 환경을 개발·테스트·스테이징 환경과 분리할 수 있어요. 이렇게 하면 -i로 무엇을 대상으로 삼을지 고를 수 있어요. 모든 환경을 한 파일에 담으면 놀라운 일이 생길 수 있어요! 예를 들어 인벤토리에서 사용하는 모든 vault 비밀번호는 그 인벤토리를 사용할 때 사용 가능해야 해요. 인벤토리에 프로덕션과 개발 환경이 모두 있다면, 그 인벤토리를 쓰는 개발자가 프로덕션 시크릿에 접근할 수 있게 돼요.

vault 처리된 변수를 안전하게 보이게 유지하기

민감하거나 기밀인 변수는 Ansible Vault로 암호화해야 해요. 하지만 변수 값뿐 아니라 변수 이름까지 암호화하면 값의 출처를 찾기 어려워져요. 이를 우회하려면 ansible-vault encrypt_string으로 변수를 개별적으로 암호화하거나, 다음 간접(indirection) 계층을 추가해 시크릿을 노출하지 않으면서 변수 이름을 (예: grep으로) 접근 가능하게 유지할 수 있어요:

  • 그룹 이름을 딴 group_vars/ 하위 디렉터리를 만든다.
  • 이 하위 디렉터리 안에 varsvault라는 두 파일을 만든다.
  • vars 파일에 필요한 모든 변수를 정의한다(민감한 것 포함).
  • 민감한 변수는 모두 vault 파일로 옮기고, 이 변수들 앞에 vault_ 접두사를 붙인다.
  • vars 파일의 변수들을 jinja2 문법으로 일치하는 vault_ 변수를 가리키게 조정한다: db_password: "{{ vault_db_password }}".
  • vault 파일을 암호화해 그 내용을 보호한다.
  • 플레이북에서는 vars 파일의 변수 이름을 사용한다.

플레이북을 실행하면 Ansible이 암호화되지 않은 파일에서 변수를 찾아, 그 변수가 암호화된 파일에서 민감한 변수 값을 끌어와요. 변수·vault 파일의 개수나 이름에는 제한이 없어요. 이 전략을 인벤토리에서 사용해도, 그 인벤토리로 실행할 때(예: ansible-playbook 또는 AWX/Ansible Tower)에는 모든 vault 비밀번호를 사용할 수 있어야 한다는 점을 기억하세요.

실행 트릭 (Execution tricks)

이 팁들은 Ansible 산출물이 아니라 Ansible을 사용하는 방식에 적용돼요.

실행 환경(Execution Environments) 사용하기

Execution Environments라고 하는 휴대용 컨테이너 이미지로 복잡성을 줄이세요.

먼저 스테이징에서 시도하기

변경 사항을 프로덕션에 배포하기 전에 스테이징 환경에서 테스트하는 것은 항상 좋은 생각이에요. 환경의 크기가 같을 필요는 없고, 환경 간 차이를 그룹 변수로 제어할 수 있어요. 다음 예처럼 --syntax-check 플래그로 스테이징 환경에서 문법 오류도 확인할 수 있어요:

ansible-playbook --syntax-check

배치 단위로 업데이트하기

serial 키워드로 배치(batch)에서 한 번에 업데이트할 머신 수를 제어하세요. "Controlling where tasks run: delegation and local actions"을 참고하세요.

OS와 배포판 차이 다루기

그룹 변수 파일과 group_by 모듈은 함께 작동해, 서로 다른 설정·패키지·도구를 요구하는 다양한 운영체제와 배포판에서 Ansible이 실행되게 도와줘요. group_by 모듈은 특정 기준을 만족하는 호스트의 동적 그룹을 만들어요. 이 그룹은 인벤토리 파일에 정의할 필요가 없어요. 이 방식으로 서로 다른 OS나 배포판에서 서로 다른 작업을 실행할 수 있어요.

예를 들어 다음 플레이는 운영체제 이름을 기준으로 모든 시스템을 동적 그룹으로 분류해요:

- name: Talk to all hosts just so we can learn about them
  hosts: all
  tasks:

    - name: Classify hosts depending on their OS distribution
      ansible.builtin.group_by:
        key: os_{{ ansible_facts['distribution'] }}

이후 플레이는 다음처럼 hosts 줄에 이 그룹들을 패턴으로 사용할 수 있어요:

- hosts: os_CentOS
  gather_facts: False
  tasks:

    # Tasks for CentOS hosts only go in this play.
    - name: Ping my CentOS hosts
      ansible.builtin.ping:

그룹 변수 파일에 그룹별 설정을 추가할 수도 있어요. 다음 예에서 CentOS 머신은 asdf 값으로 42를, 다른 머신은 10을 받아요. 그룹 변수 파일로 변수를 설정할 뿐 아니라 시스템에 롤을 적용할 수도 있어요.

---
# file: group_vars/all
asdf: 10

---
# file: group_vars/os_CentOS.yml
asdf: 42

참고: 세 이름이 모두 일치해야 해요. group_by 작업이 만든 이름, 이후 플레이의 패턴 이름, 그리고 그룹 변수 파일 이름이요.

작업이 아니라 OS별 변수만 필요할 때는 include_vars로 같은 설정을 쓸 수 있어요:

- name: Use include_vars to include OS-specific variables and print them
  hosts: all
  tasks:

    - name: Set OS distribution dependent variables
      ansible.builtin.include_vars: "os_{{ ansible_facts['distribution'] }}.yml"

    - name: Print the variable
      ansible.builtin.debug:
        var: asdf

이 방식은 group_vars/os_CentOS.yml 파일에서 변수를 가져와요.

더 알아보기 (Learn more)

  • 유지보수와 협업을 위해 심플함, 버전 관리, 명확한 이름·state·코멘트, FQCN 사용이 기본이에요.
  • 클라우드는 동적 인벤토리, 환경은 분리된 인벤토리, 민감 변수는 vault로 암호화하되 이름은 보이게 유지하세요.
  • 스테이징 테스트, serial 배치, group_by로 OS 차이까지 다루면 운영에서 안심할 수 있어요.