Ansible 입문 가이드: 개념부터 실제 활용까지

이 문서에 대해

이 가이드는 Ansible 2.9.27 버전을 기준으로 작성되었습니다. 아래는 사용된 환경 정보입니다.

# cat /etc/system-release
Red Hat Enterprise Linux Server release 7.8 (Maipo)

# uname -a
Linux test01 3.10.0-1160.36.2.el7.x86_64 #1 SMP Wed Jul 21 11:57:15 UTC 2021 x86_64 x86_64 x86_64 GNU/Linux

# ansible --version
ansible 2.9.27
  config file = /etc/ansible/ansible.cfg
  configured module search path = [u'/home/vipxf/.ansible/plugins/modules', u'/usr/share/ansible/plugins/modules']
  ansible python module location = /usr/lib/python2.7/site-packages/ansible
  executable location = /bin/ansible
  python version = 2.7.5 (default, Nov 16 2020, 22:23:17) [GCC 4.8.5 20150623 (Red Hat 4.8.5-44)]

# rpm -qi ansible
Name        : ansible
Arch        : noarch
Version     : 2.9.27
Release     : 1.el7
Size        : 103 M
Repo        : installed
Summary     : SSH-based configuration management, deployment, and task execution system
URL         : http://ansible.com
License     : GPLv3+
Description : Ansible is a radically simple model-driven configuration management,
            : multi-node deployment, and remote task execution system. Ansible works
            : over SSH and does not require any software or daemons to be installed
            : on remote nodes. Extension modules can be written in any language and
            : are transferred to managed machines automatically.

Ansible 개념 이해

Ansible은 오픈 소스 기반의 구성 관리 및 자동화 도구입니다.

핵심 특징

  • 에이전트리스(Agentless) 방식: 관리 대상 노드에 별도 에이전트 설치 불필요. 제어 노드에만 Ansible 환경을 구축하면 됩니다.
  • 풍부한 내장 모듈: 대부분의 작업 시나리오를 충족하는 다양한 모듈 제공.
  • Python 기반: API 및 사용자 정의 모듈 개발이 용이합니다.
  • SSH 프로토콜 사용: 별도 데몬 없이 SSH를 통해 원격 노드와 통신합니다.
  • Playbook: YAML과 Jinja2 템플릿 언어를 사용하여 복잡한 작업을 정의하고 관리합니다.
  • 멱등성(Idempotency): 동일한 작업을 여러 번 수행해도 결과가 동일하도록 보장합니다.

Ansible 사용 모드

  • Ad-Hoc 명령: 단일 명령을 일괄 실행하여 일회성 작업이나 빠른 확인에 사용됩니다.
  • Playbook 실행: 여러 Task를 순차적으로 실행하여 복잡한 워크플로우를 자동화하는 주요 관리 방식입니다.

Ansible 아키텍처 및 실행 흐름

Ansible은 다음 다섯 가지 주요 구성 요소로 이루어집니다.

  • Ansible Core: Ansible의 핵심 엔진
  • Modules: 실제 작업을 수행하는 모듈들 (기본 및 사용자 정의)
  • Plugins: 연결 플러그인, 메일 플러그인 등 모듈의 기능을 확장합니다.
  • Playbooks: 작업을 정의하는 YAML 형식의 설정 파일
  • Inventory: 관리할 대상 호스트 목록을 정의합니다.

명령 실행 과정

  1. 설정 파일(기본: /etc/ansible/ansible.cfg)을 로드합니다.
  2. Inventory 파일(기본: /etc/ansible/hosts)을 읽어 대상 호스트 목록과 변수를 확인합니다.
  3. 호출된 모듈에 따라 임시 Python 파일을 생성합니다.
  4. 생성된 파일을 대상 호스트의 ~/.ansible/tmp 디렉토리로 전송합니다.
  5. 파일을 실행하여 작업을 수행하고 결과를 반환합니다.
  6. 임시 파일을 삭제하고 종료합니다.

Ansible 기본 정보

주요 디렉토리 구조

  • /etc/ansible/: 설정 파일, Inventory, Roles 디렉토리
  • /usr/bin/: Ansible 실행 파일 위치
  • /usr/lib/python2.7/site-packages/ansible: Python 라이브러리 디렉토리
  • /usr/share/ansible/: 모듈, 플러그인, Roles 디렉토리

설정 파일 (/etc/ansible/ansible.cfg) 주요 파라미터

inventory = /etc/ansible/hosts     # Inventory 파일 위치
library = /usr/share/ansible       # Ansible 모듈 디렉토리 (":"로 구분하여 여러 개 지정 가능)
forks = 5                          # 동시 실행 프로세스 수 (기본값 5)
remote_port = 22                   # 원격 연결 포트
host_key_checking = False          # SSH 호스트 키 검사 비활성화
timeout = 60                       # SSH 연결 타임아웃 (초)
log_path = /var/log/ansible.log    # 로그 파일 경로 (기본 비활성화)

실행 파일 목록

$ ll /usr/bin/*ansible*
lrwxrwxrwx 1 root root    20 Mar 17  2022 /usr/bin/ansible -> /usr/bin/ansible-2.7
lrwxrwxrwx 1 root root    20 Mar 17  2022 /usr/bin/ansible-2 -> /usr/bin/ansible-2.7
-rwxr-xr-x 1 root root  5933 Jan 16  2022 /usr/bin/ansible-2.7
lrwxrwxrwx 1 root root     7 Mar 17  2022 /usr/bin/ansible-config -> ansible
-rwxr-xr-x 1 root root 13432 Jan 16  2022 /usr/bin/ansible-connection
lrwxrwxrwx 1 root root    28 Mar 17  2022 /usr/bin/ansible-console -> /usr/bin/ansible-console-2.7
...

자주 사용되는 모듈

# 모듈 도움말 보기
ansible-doc -l                  # 사용 가능한 모든 플러그인 목록
ansible-doc -l | grep "copy"    # "copy"가 포함된 모듈 검색
ansible-doc <module_name>       # 특정 모듈 설명 보기
ansible-doc -s <module_name>    # Playbook 스니펫 보기

# 주요 모듈
- **command**: 기본 모듈, 변수/파이프/리다이렉션 등 셸 기능 미지원
- **ping**: 대상 호스트 연결성 테스트
- **shell**: 셸 기능(변수, 파이프 등) 지원 명령 실행
- **script**: 로컬 스크립트를 원격 호스트에서 실행
- **setup**: 대상 호스트의 시스템 정보(facts) 수집
- **copy**: 로컬 파일을 원격 호스트로 복사
- **file**: 파일 속성(권한, 소유자 등) 변경
- **service**: 서비스 상태 관리 (시작, 중지, 재시작)
- **yum**: 패키지 설치, 업데이트, 제거
- **user**, **group**: 사용자 및 그룹 관리

Ansible 명령어

명령어 집합

ansible               # Ad-Hoc 명령 실행 (기본 모듈: command)
ansible-config        # Ansible 설정 확인
ansible-doc           # 모듈 문서 조회
ansible-galaxy        # Role 및 Collection 관련 작업
ansible-inventory     # Inventory 정보 출력
ansible-playbook      # Playbook 파일 실행
ansible-pull          # VCS에서 Playbook을 가져와 로컬에서 실행
ansible-vault         # 민감한 데이터 암호화/복호화

Ad-Hoc 명령 상세

# ansible <host-pattern> [-f forks] [-m module_name] [-a args]

# 주요 옵션
-v                    # 상세 출력 (-vvv, -vvvv)
-i inventory_file     # Inventory 파일 지정
-f forks              # 동시 실행 프로세스 수
-m module_name        # 사용할 모듈 지정
-a args               # 모듈 인자
-l hosts_ip           # 실행 대상을 특정 호스트로 제한

--become-method BECOME_METHOD    # 권한 상승 방법 (sudo, su)
--become-user BECOME_USER        # 권한 상승 대상 사용자
-K, --ask-become-pass            # 권한 상승 암호 입력 요청

--list-hosts        # 대상 호스트 목록만 출력
--syntax-check      # 구문 검사
-C, --check         # 변경 없이 테스트 실행 (dry-run)

# 명령 예시
ansible 192.168.56.3 -a 'hostname'  # command 모듈 사용
ansible Test -m ping                  # Test 그룹 핑 테스트
ansible all -m shell -a 'hostname && date'  # 모든 호스트에 셸 명령 실행

자주 사용하는 Ad-Hoc 명령 예제

# ping 모듈로 연결 확인
ansible ta -m ping

# command 모듈로 디렉토리 변경 후 ls 실행
ansible ta -m command -a "chdir=/home/ ls ./"

# shell 모듈로 복잡한 명령 실행
ansible ta -m shell -a 'hostname && date;cat /etc/system-release'

# script 모듈로 로컬 스크립트 실행
ansible ta -m script -a "/home/vipxf/test.sh"

# setup 모듈로 시스템 정보 수집
ansible ta -m setup -a "filter=ansible_os_family"

# copy 모듈로 파일 복사 및 권한 설정
ansible ta -m copy -a "src=/etc/hosts dest=~/test.hosts mode=664 owner=vipxf group=vipxf"

# file 모듈로 파일 생성
ansible ta -m file -a "path=~/testfile.txt state=touch mode=644"

# yum 모듈로 패키지 설치
ansible ta -m yum -a "name=httpd state=present"

# service 모듈로 서비스 시작
ansible ta -m service -a "name=sshd enabled=yes state=started"

Ansible 변수 사용

  • 변수명은 문자, 숫자, 밑줄(_)로 구성되며 숫자로 시작할 수 없습니다.
  • Python 키워드나 Playbook 키워드는 변수명으로 사용할 수 없습니다.
  • 변수는 Playbook, Inventory, 역할(Role), 명령줄 등 다양한 곳에서 정의할 수 있습니다.

변수 정의 방법

# 방법 1: Inventory에서 호스트/그룹 변수 정의
[groupname]
192.168.56.1 variable_name=value
[groupname:vars]
variable_name=value

# 방법 2: Playbook에서 vars 또는 vars_files로 정의
vars:
  - var_name: value
vars_files:
  - ./external_vars.yml

# 방법 3: register 키워드로 작업 결과를 변수로 저장
tasks:
  - name: test
    shell: /usr/bin/foo
    register: foo_result

# 방법 4: 명령줄에서 -e 또는 --extra-vars로 변수 전달
ansible-playbook test.yml --extra-vars "hosts=Test user=anliven"

# 방법 5: roles 키워드로 변수 전달
roles:
  - { role: ROLE_NAME, var: value }

시스템 변수 (Facts)

setup 모듈로 수집한 원격 호스트의 시스템 정보입니다.

ansible ta -m setup  # 모든 facts 정보 확인
ansible ta -m setup -a "filter=ansible_os_family"  # 특정 정보 필터링

변수 참조

# 일반 변수
{{ var_name }}

# register 또는 facts 변수
{{ var_name.stdout }}
{{ ansible_facts["eth0"]["ipv4"]["address"] }}

변수 우선순위 (높은 순)

  1. 명령줄에서 정의된 변수 (-e 또는 --extra-vars)
  2. Inventory의 연결 변수 (예: ansible_ssh_user)
  3. Play, include, role 등에서 정의된 일반 변수
  4. Inventory의 기타 변수
  5. Facts 변수

Ansible 인벤토리 (Inventory)

Inventory는 관리 대상 호스트의 집합을 정의합니다. 기본 파일은 /etc/ansible/hosts입니다.

인벤토리 파일 예시

192.168.56.1    # 그룹 없는 호스트
test.example.com

[Test]  # 그룹 정의
192.168.56.1
192.168.56.[2:5]  # 범위 지정
anliven-[a:d].example.com  # 문자 범위

[Test:vars]  # 그룹 변수
ansible_ssh_user="anliven"
ansible_ssh_pass="anliven"

[Test2]
192.168.56.1 ansible_ssh_user=anliven ansible_ssh_pass=Anliven  # 호스트별 변수

[TestGroup:children]  # 그룹 중첩
Test
Test2

[all:vars]  # 모든 호스트에 적용되는 전역 변수
ansible_ssh_port="22"

Ansible Playbook

Playbook은 YAML 형식으로 작성된 작업 자동화 스크립트입니다.

Playbook 기본 구조

---
- hosts: ta  # 대상 호스트
  remote_user: vipxf  # 원격 실행 사용자
  gather_facts: no  # Facts 수집 비활성화
  vars:  # 변수 정의
    - package: vim
  tasks:  # 작업 목록
    - name: install vim
      yum: name={{ package }} state=latest
    - name: copy file
      copy: src=/root/conf/httpd.conf dest=/home/vipxf/
      notify: restart service  # 변경 시 핸들러 호출
  handlers:  # 핸들러 (알림을 받은 작업만 실행)
    - name: restart service
      service: name=httpd state=restarted

Playbook 실행

# 구문 검사
ansible-playbook --syntax-check sample.yaml

# 변경 없이 테스트 (dry-run)
ansible-playbook -C sample.yaml

# 상세 모드 실행
ansible-playbook -v sample.yaml

# 특정 태그만 실행
ansible-playbook sample.yaml --tags "conf,http"

# 특정 태그 제외
ansible-playbook sample.yaml --skip-tags "conf"

조건부 실행 (when)

- name: example
  hosts: ta
  tasks:
    - name: RedHat 계열에서만 실행
      shell: echo "RedHat"
      when: ansible_os_family == "RedHat"

    - name: 이전 작업 성공 시 실행
      shell: echo "step1"
      register: result
    - name: step2 실행
      shell: echo "step2"
      when: result.rc == 0

루프 (with_items)

- name: iterate example
  hosts: ta
  tasks:
    - name: 패키지 설치
      yum: name={{ item }} state=present
      with_items:
        - httpd
        - nginx
        - mysql

    - name: 딕셔너리 루프
      debug: msg="{{ item.name }}: {{ item.value }}"
      with_items:
        - { name: 'one', value: '111' }
        - { name: 'two', value: '222' }

역할 (Roles)

Roles는 Playbook을 모듈화하여 재사용성을 높입니다.

# 디렉토리 구조 예시
site.yml
roles/
    common/
        tasks/main.yml
        handlers/main.yml
        templates/
        files/
        vars/main.yml
        defaults/main.yml
        meta/main.yml
    webserver/
        tasks/main.yml
        ...

# Playbook에서 Roles 호출
---
- hosts: webserver
  roles:
    - common
    - { role: webserver, port: 8080 }

Ansible Vault (암호화)

ansible-vault는 민감한 데이터를 암호화하는 도구입니다.

주요 명령어

# 파일 암호화
ansible-vault encrypt secret.yml

# 파일 복호화
ansible-vault decrypt secret.yml

# 암호화된 파일 보기
ansible-vault view secret.yml

# 암호 변경
ansible-vault rekey secret.yml

# 암호화된 Playbook 실행
ansible-playbook secret.yml --ask-vault-pass

성능 최적화

# SSH 키 검사 비활성화
host_key_checking = False

# 동시 실행 프로세스 수 증가
forks = 20

# Facts 수집 비활성화 (필요 없는 경우)
gather_facts: False

# 파이프라이닝 활성화 (sudo 미사용 시)
pipelining = True

# 비동기 작업 및 폴링
- name: long task
  shell: sleep 10 && echo "done"
  async: 15
  poll: 2

자주 사용하는 팁

SSH 키 기반 인증

ssh-keygen -t rsa
ssh-copy-id -i ~/.ssh/id_rsa.pub user@remote_host

root 비밀번호 입력 생략

---
- hosts: ta
  become: yes
  become_method: su
  become_user: root
  vars:
    ansible_become_pass: "{{ root_pass_input }}"
  tasks:
    - name: test
      shell: date

# 실행: ansible-playbook playbook.yml -e root_pass_input=my_password

여러 핸들러에 알림 보내기

tasks:
  - name: config change
    template: src=config.j2 dest=/etc/config
    notify: "config update"
handlers:
  - name: restart service
    service: name=app state=restarted
    listen: "config update"
  - name: reload service
    service: name=app state=reloaded
    listen: "config update"

태그: Ansible IT Automation Configuration Management Ad-Hoc Playbook

5월 25일 17:43에 게시됨