RHEL 에서 복잡한 Ansible 플레이북 구조화하기

AnsibleBeginner
지금 연습하기

소개

이 랩에서는 RHEL 에서 복잡한 Ansible 플레이북을 구조화하여 보다 관리하기 쉽고 확장 가능하며 재사용 가능한 자동화를 만드는 데 필수적인 기술을 배우게 됩니다. 기본 개념부터 고급 구성 전략까지 진행하며, 자동화가 실행될 호스트를 정확하게 제어하는 방법과 대규모 플레이북을 논리적이고 모듈식 구성 요소로 분해하는 방법에 중점을 둡니다.

먼저 기본 그룹 이름, 와일드카드, 제외 및 논리 연산자를 사용하여 인벤토리 내의 특정 노드를 대상으로 하는 호스트 선택을 마스터하게 됩니다. 다음으로 include_tasksimport_tasks를 사용하여 작업을 별도의 파일로 리팩토링하여 모듈화를 탐색합니다. 마지막으로 import_playbook을 사용하여 완전한 다중 플레이북 워크플로를 구성하는 방법을 배우고, 최종적으로 완전히 구조화되고 모듈화된 Ansible 프로젝트를 실행하고 검증하게 됩니다.

이것은 가이드 실험입니다. 학습과 실습을 돕기 위한 단계별 지침을 제공합니다.각 단계를 완료하고 실무 경험을 쌓기 위해 지침을 주의 깊게 따르세요. 과거 데이터에 따르면, 이것은 초급 레벨의 실험이며 완료율은 94%입니다.학습자들로부터 100%의 긍정적인 리뷰율을 받았습니다.

기본 및 와일드카드 패턴으로 호스트 선택하기

이 단계에서는 Ansible 자동화에서 특정 호스트를 대상으로 하는 기본 사항을 배우게 됩니다. 이 과정의 핵심은 관리하는 서버 목록을 제공하는 Ansible 인벤토리 파일과 플레이북 내의 hosts 지시문으로, 이 지시문은 특정 작업 세트가 실행되어야 하는 서버를 지정합니다. Ansible 을 설치하고, 기본 인벤토리 및 플레이북을 생성한 다음, 그룹 이름과 와일드카드 패턴을 사용하여 호스트를 선택하는 방법을 살펴보겠습니다.

먼저 환경에 Ansible 이 설치되어 있는지 확인합니다. Ansible 은 기본적으로 설치되어 있지 않으므로 DNF 패키지 관리자를 사용하여 설치해야 합니다. ansible-core 패키지는 ansible-playbook을 포함한 필수 Ansible 명령줄 도구를 제공합니다. 다음 명령을 실행합니다.

sudo dnf install -y ansible-core

다음과 유사한 출력이 표시되어야 합니다.

...
Installed:
  ansible-core-2.16.x-x.el9.x86_64
  ...
Complete!

다음으로, 파일을 정리하기 위해 이 연습을 위한 전용 디렉토리를 만듭니다. 이 단계의 모든 후속 작업은 이 새 디렉토리 내에서 수행됩니다.

mkdir -p ~/project/ansible_patterns
cd ~/project/ansible_patterns

이제 인벤토리 파일을 만듭니다. 인벤토리는 Ansible 명령, 모듈 및 작업이 작동하는 호스트 및 호스트 그룹을 정의하는 텍스트 파일입니다. 단순성을 위해 INI 형식을 사용합니다.

nano 편집기를 사용하여 inventory라는 파일을 만듭니다.

nano inventory

inventory 파일에 다음 내용을 추가합니다. 이 내용은 각각 두 개의 호스트를 포함하는 webserversdbservers라는 두 개의 그룹을 정의합니다.

[webservers]
web1.example.com
web2.example.com

[dbservers]
db1.lab.net
db2.lab.net

파일을 저장하고 Ctrl+X를 누른 다음 Y를 누르고 Enter를 눌러 nano를 종료합니다.

인벤토리가 준비되었으므로 간단한 플레이북을 만듭니다. 이 플레이북은 ansible.builtin.debug 모듈을 사용하여 메시지를 출력하고 작업이 실행되는 호스트를 확인합니다. 이는 시스템에 실제 변경을 가하지 않고 호스트 패턴을 테스트하는 좋은 방법입니다.

playbook.yml이라는 새 파일을 만듭니다.

nano playbook.yml

다음 YAML 내용을 추가합니다. 처음에는 webservers 그룹의 모든 호스트를 대상으로 합니다.

---
- name: Test Host Patterns
  hosts: webservers
  gather_facts: false
  tasks:
    - name: Display the inventory hostname
      ansible.builtin.debug:
        msg: "This task is running on {{ inventory_hostname }}"

편집기를 저장하고 종료합니다. 이제 ansible-playbook을 사용하여 플레이북을 실행합니다. -i 플래그는 사용자 지정 인벤토리 파일을 지정합니다.

ansible-playbook playbook.yml -i inventory

출력은 다음과 같아야 합니다.

PLAY [Test Host Patterns] ******************************************************

TASK [Display the inventory hostname] ******************************************
ok: [web1.example.com] => {
    "msg": "This task is running on web1.example.com"
}
ok: [web2.example.com] => {
    "msg": "This task is running on web2.example.com"
}

PLAY RECAP *********************************************************************
web1.example.com           : ok=1    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
web2.example.com           : ok=1    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

보시다시피 webservers 그룹의 호스트만 대상으로 지정되었습니다. 이제 와일드카드 (*) 를 사용하도록 플레이북을 수정해 보겠습니다. 와일드카드를 사용하면 더 유연한 패턴 일치가 가능합니다.

playbook.yml을 편집하고 hosts 줄을 hosts: "*.lab.net"으로 변경합니다. 와일드카드가 포함된 패턴은 따옴표로 묶어야 함을 기억하십시오.

---
- name: Test Host Patterns
  hosts: "*.lab.net"
  gather_facts: false
  tasks:
    - name: Display the inventory hostname
      ansible.builtin.debug:
        msg: "This task is running on {{ inventory_hostname }}"

플레이북을 다시 실행합니다.

ansible-playbook playbook.yml -i inventory

다음과 유사한 출력이 표시되어야 합니다.

PLAY [Test Host Patterns] ******************************************************

TASK [Display the inventory hostname] ******************************************
ok: [db1.lab.net] => {
    "msg": "This task is running on db1.lab.net"
}
ok: [db2.lab.net] => {
    "msg": "This task is running on db2.lab.net"
}

PLAY RECAP *********************************************************************
db1.lab.net                : ok=1    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
db2.lab.net                : ok=1    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

이번에는 플레이가 .lab.net으로 끝나는 호스트에서만 실행되었습니다. 마지막으로 특수 키워드 all을 사용하여 인벤토리에 정의된 모든 호스트를 대상으로 지정해 보겠습니다.

playbook.yml을 마지막으로 편집하고 hosts 줄을 hosts: all로 변경합니다.

---
- name: Test Host Patterns
  hosts: all
  gather_facts: false
  tasks:
    - name: Display the inventory hostname
      ansible.builtin.debug:
        msg: "This task is running on {{ inventory_hostname }}"

결과를 보려면 플레이북을 실행합니다.

ansible-playbook playbook.yml -i inventory

출력에는 모든 호스트가 대상으로 지정되었음을 보여줍니다.

PLAY [Test Host Patterns] ******************************************************

TASK [Display the inventory hostname] ******************************************
ok: [web1.example.com] => {
    "msg": "This task is running on web1.example.com"
}
ok: [web2.example.com] => {
    "msg": "This task is running on web2.example.com"
}
ok: [db1.lab.net] => {
    "msg": "This task is running on db1.lab.net"
}
ok: [db2.lab.net] => {
    "msg": "This task is running on db2.lab.net"
}

PLAY RECAP *********************************************************************
db1.lab.net                : ok=1    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
db2.lab.net                : ok=1    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
web1.example.com           : ok=1    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
web2.example.com           : ok=1    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

플레이북이 이제 인벤토리의 네 호스트 모두에서 실행되어 all 패턴의 강력함을 보여줍니다.

제외 및 논리 연산자를 사용한 호스트 선택 정제

이 단계에서는 제외 및 논리 연산자를 사용하는 방법을 배워 호스트 선택 기술을 향상시킵니다. 이러한 기능은 복잡한 환경을 관리할 때 필수적인 매우 구체적인 대상을 지정할 수 있게 해줍니다. ! (NOT) 연산자를 사용하여 호스트를 제외하고 & (AND) 연산자를 사용하여 그룹을 결합하는 방법을 배우게 됩니다. 이전 단계의 inventoryplaybook.yml 파일을 계속 사용합니다.

먼저 올바른 작업 디렉토리에 있는지 확인합니다.

cd ~/project/ansible_patterns

논리 연산자를 효과적으로 시연하기 위해 호스트 그룹 간에 일부 겹침을 만들어야 합니다. inventory 파일을 편집하여 웹 서버 하나와 데이터베이스 서버 하나를 포함하는 production이라는 새 그룹을 추가해 보겠습니다.

nano inventory

파일 끝에 [production] 그룹과 해당 멤버를 추가합니다.

[webservers]
web1.example.com
web2.example.com

[dbservers]
db1.lab.net
db2.lab.net

[production]
web1.example.com
db1.lab.net

파일을 저장하고 Ctrl+X를 누른 다음 Y를 누르고 Enter를 눌러 nano를 종료합니다.

이제 제외를 연습해 보겠습니다. NOT 을 의미하는 ! 연산자를 사용하면 선택에서 호스트 또는 그룹을 제외할 수 있습니다. playbook.yml을 수정하여 dbservers 그룹에 속하지 않는 모든 호스트를 대상으로 지정합니다.

nano playbook.yml

아래와 같이 hosts 줄을 업데이트합니다. all,!dbservers 패턴은 모든 호스트를 선택한 다음 dbservers 그룹에 속한 호스트를 제거합니다.

---
- name: Test Host Patterns
  hosts: all,!dbservers
  gather_facts: false
  tasks:
    - name: Display the inventory hostname
      ansible.builtin.debug:
        msg: "This task is running on {{ inventory_hostname }}"

편집기를 저장하고 종료한 다음 플레이북을 실행합니다.

ansible-playbook playbook.yml -i inventory

웹 서버만 대상으로 지정되는 것을 볼 수 있습니다.

PLAY [Test Host Patterns] ******************************************************

TASK [Display the inventory hostname] ******************************************
ok: [web1.example.com] => {
    "msg": "This task is running on web1.example.com"
}
ok: [web2.example.com] => {
    "msg": "This task is running on web2.example.com"
}

PLAY RECAP *********************************************************************
web1.example.com           : ok=1    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
web2.example.com           : ok=1    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

예상대로 webservers 그룹의 호스트만 대상으로 지정되었습니다.

다음으로 논리 AND 연산자를 살펴보겠습니다. & 연산자는 지정된 그룹에 모두 존재하는 호스트만 선택합니다 (교집합). 플레이북을 수정하여 webservers 그룹에 있고 production 그룹에도 있는 호스트를 대상으로 지정해 보겠습니다.

nano playbook.yml

hosts 줄을 webservers,&production으로 변경합니다.

---
- name: Test Host Patterns
  hosts: webservers,&production
  gather_facts: false
  tasks:
    - name: Display the inventory hostname
      ansible.builtin.debug:
        msg: "This task is running on {{ inventory_hostname }}"

저장하고 플레이북을 실행합니다.

ansible-playbook playbook.yml -i inventory

이번에는 두 그룹의 교집합만 대상으로 지정됩니다.

PLAY [Test Host Patterns] ******************************************************

TASK [Display the inventory hostname] ******************************************
ok: [web1.example.com] => {
    "msg": "This task is running on web1.example.com"
}

PLAY RECAP *********************************************************************
web1.example.com           : ok=1    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

출력은 webserversproduction 그룹 모두의 멤버인 유일한 호스트이기 때문에 web1.example.com만 대상으로 지정되었음을 올바르게 보여줍니다. 이러한 연산자를 통해 자동화가 영향을 미치는 호스트를 정확하게 제어할 수 있습니다.

include_tasksimport_tasks 를 사용한 플레이 모듈화

이 단계에서는 더 큰 Ansible 프로젝트를 더 작고 재사용 가능한 파일로 분리하여 구조화하는 방법을 배우게 됩니다. 플레이북이 커짐에 따라 모든 작업을 단일 파일에 유지하는 것은 관리하기 어려워집니다. Ansible 은 이를 위해 두 가지 주요 지시문인 import_tasksinclude_tasks를 제공합니다. 둘 다 다른 파일에서 작업을 가져올 수 있습니다.

  • import_tasks정적입니다. Ansible 이 플레이북을 처음 구문 분석할 때 처리됩니다. 이는 플레이의 조건부, 구조적 부분에 가장 적합합니다.
  • include_tasks동적입니다. 플레이 실행 중에 처리됩니다. 따라서 루프 및 조건문과 함께 사용하기에 적합합니다.

이제 두 가지 모두를 사용하도록 플레이북을 리팩토링하겠습니다. 먼저 프로젝트 디렉토리에 있는지 확인합니다.

cd ~/project/ansible_patterns

진행하기 전에 이 랩 환경의 호스트를 localhost 로 가리키도록 인벤토리 파일을 업데이트해 보겠습니다. 이렇게 하면 플레이북이 성공적으로 실행될 수 있습니다.

nano inventory

다음 구성을 사용하여 예제 호스트를 localhost 에 매핑하도록 파일 내용을 바꿉니다.

[webservers]
web1.example.com ansible_host=localhost ansible_connection=local
web2.example.com ansible_host=localhost ansible_connection=local

[dbservers]
db1.lab.net ansible_host=localhost ansible_connection=local
db2.lab.net ansible_host=localhost ansible_connection=local

편집기를 저장하고 종료합니다. 이 구성은 ansible_host=localhost를 사용하여 연결을 로컬 머신으로 리디렉션하고 ansible_connection=local을 사용하여 SSH 연결 시도를 방지합니다.

재사용 가능한 작업 파일을 전용 하위 디렉토리에 저장하는 것이 일반적인 관행입니다. tasks라는 이름의 디렉토리를 만들어 보겠습니다.

mkdir tasks

이제 여러 서버에 적용될 수 있는 일반적인 설정 작업을 위한 파일을 만들어 보겠습니다. 여기서는 httpd 웹 서버 패키지를 설치하는 작업을 배치합니다.

nano tasks/web_setup.yml

다음 내용을 추가합니다. 이 파일은 작업 목록일 뿐이며 전체 플레이 구조 (hosts: 또는 name:과 같은) 를 포함하지 않습니다.

- name: Install the httpd package
  ansible.builtin.dnf:
    name: httpd
    state: present
  become: true

nano를 저장하고 종료합니다. 다음으로 간단한 확인 단계를 위한 두 번째 작업 파일을 만듭니다.

nano tasks/verify_config.yml

이 파일에 다음 디버그 작업을 추가합니다.

- name: Display a verification message
  ansible.builtin.debug:
    msg: "Configuration tasks applied to {{ inventory_hostname }}"

편집기를 저장하고 종료합니다. 이제 이러한 새 작업 파일을 사용하도록 기본 playbook.yml을 수정해 보겠습니다. 정적 설정에는 import_tasks를 사용하고 동적 확인 메시지에는 include_tasks를 사용합니다.

nano playbook.yml

playbook.yml의 전체 내용을 다음으로 바꿉니다. 이 플레이북은 이제 webservers 그룹을 대상으로 하고 모듈식 작업 파일을 사용합니다.

---
- name: Configure Web Servers
  hosts: webservers
  gather_facts: false
  tasks:
    - name: Import web server setup tasks
      import_tasks: tasks/web_setup.yml

    - name: Include verification tasks
      include_tasks: tasks/verify_config.yml

파일을 저장하고 플레이북을 실행합니다.

ansible-playbook playbook.yml -i inventory

모듈식 작업이 실행되는 것을 볼 수 있습니다.

PLAY [Configure Web Servers] ***************************************************

TASK [Import web server setup tasks] *******************************************
imported: /home/labex/project/ansible_patterns/tasks/web_setup.yml

TASK [Install the httpd package] ***********************************************
changed: [web1.example.com]
changed: [web2.example.com]

TASK [Include verification tasks] **********************************************
included: /home/labex/project/ansible_patterns/tasks/verify_config.yml for web1.example.com, web2.example.com

TASK [Display a verification message] ******************************************
ok: [web1.example.com] => {
    "msg": "Configuration tasks applied to web1.example.com"
}
ok: [web2.example.com] => {
    "msg": "Configuration tasks applied to web2.example.com"
}

PLAY RECAP *********************************************************************
web1.example.com           : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
web2.example.com           : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

출력에서 작업이 해당 파일에서 언제 가져오고 포함되는지 명확하게 표시되는 방식을 관찰합니다. 이 모듈식 접근 방식은 자동화를 더 깔끔하고 유지 관리하기 쉽게 만듭니다.

import_playbook 를 사용한 워크플로우 구성

이 단계에서는 import_playbook을 사용하여 전체 플레이북을 오케스트레이션하여 복잡한 워크플로우를 형성하는 방법을 배우게 됩니다. import_tasksinclude_tasks는 단일 플레이 내에서 작업 목록을 재사용하기 위한 것이지만, import_playbook은 더 높은 수준에서 작동합니다. 이를 통해 특정 순서로 다른 독립적인 플레이북을 실행하는 마스터 플레이북을 만들 수 있습니다. 이는 전체 애플리케이션 스택 프로비저닝과 같은 대규모 자동화를 관리하는 표준 방법입니다.

먼저 올바른 디렉토리에 있는지 확인하고 이 새로운 구조를 위해 프로젝트를 구성해 보겠습니다.

cd ~/project/ansible_patterns

개별 구성 요소 플레이북을 전용 하위 디렉토리에 저장하는 것이 가장 좋습니다. playbooks라는 디렉토리를 만들어 보겠습니다.

mkdir playbooks

이제 마지막 단계에서 생성한 웹 서버를 구성하는 플레이북을 이 새 디렉토리로 이동합니다. 더 설명적인 이름으로 바꾸는 것도 좋은 생각입니다.

mv playbook.yml playbooks/web_configure.yml

하지만 플레이북을 하위 디렉토리로 이동했기 때문에 작업 파일에 대한 상대 경로를 업데이트해야 합니다. 작업 파일은 여전히 기본 프로젝트 디렉토리에 상대적인 tasks/ 디렉토리에 있으므로 경로를 조정해야 합니다.

nano playbooks/web_configure.yml

플레이북의 경로를 tasks/ 대신 ../tasks/를 사용하도록 업데이트합니다.

---
- name: Configure Web Servers
  hosts: webservers
  gather_facts: false
  tasks:
    - name: Import web server setup tasks
      import_tasks: ../tasks/web_setup.yml

    - name: Include verification tasks
      include_tasks: ../tasks/verify_config.yml

편집기를 저장하고 종료합니다.

이제 경로가 올바르게 작동하는지 확인하기 위해 수정된 플레이북을 테스트해 보겠습니다.

ansible-playbook playbooks/web_configure.yml -i inventory

수정된 경로로 플레이북이 성공적으로 실행되는 것을 볼 수 있습니다.

다음으로 데이터베이스 서버 구성을 위한 새롭고 별도의 플레이북을 만듭니다. 이 플레이북은 dbservers 그룹을 대상으로 하고 mariadb 패키지를 설치합니다.

nano playbooks/db_setup.yml

파일에 다음 내용을 추가합니다. 이것은 완전하고 독립적인 플레이입니다.

---
- name: Configure Database Servers
  hosts: dbservers
  gather_facts: false
  tasks:
    - name: Install mariadb package
      ansible.builtin.dnf:
        name: mariadb
        state: present
      become: true

    - name: Display a confirmation message
      ansible.builtin.debug:
        msg: "Database server {{ inventory_hostname }} configured."

편집기를 저장하고 종료합니다. 이제 웹 서버용 플레이북 하나와 데이터베이스 서버용 플레이북 하나, 총 두 개의 구성 요소 플레이북이 있습니다.

마지막으로 최상위 "메인" 플레이북을 만듭니다. 이 파일 자체에는 호스트나 작업이 포함되지 않습니다. 유일한 작업은 다른 플레이북을 올바른 순서로 가져와 전체 워크플로우를 정의하는 것입니다.

nano main.yml

다음 내용을 추가합니다. 이렇게 하면 먼저 웹 서버를 구성한 다음 데이터베이스 서버를 구성하는 워크플로우가 생성됩니다.

---
- name: Import the web server configuration play
  import_playbook: playbooks/web_configure.yml

- name: Import the database server configuration play
  import_playbook: playbooks/db_setup.yml

nano를 저장하고 종료합니다. 이제 main.yml 플레이북을 실행하여 전체 워크플로우를 실행할 준비가 되었습니다.

ansible-playbook main.yml -i inventory

출력에는 두 개의 별도 플레이가 순서대로 실행되는 것을 볼 수 있으며, 이는 import_playbook이 어떻게 더 큰 워크플로우를 작고 관리 가능한 부분으로 효과적으로 구성하는지 보여줍니다.

완전한 모듈식 플레이북 실행 및 검증

이 마지막 단계에서는 구축한 완전한 모듈식 워크플로우를 실행하고, 더 중요하게는 자동화가 대상 시스템에서 의도한 상태를 달성했는지 확인하는 방법을 배우게 됩니다. 플레이북 실행이 성공하는 것도 좋지만, 결과를 확인하는 것은 안정적인 자동화에 필수적입니다.

먼저 메인 프로젝트 디렉토리에 있는지 확인합니다.

cd ~/project/ansible_patterns

최종 플레이북을 실행하기 전에 생성한 전체 프로젝트 구조를 시각화해 보겠습니다. tree 명령은 이를 위해 훌륭합니다. 설치되어 있지 않다면 dnf로 추가할 수 있습니다.

sudo dnf install -y tree
tree .

다음과 유사한 구조를 볼 수 있습니다.

.
├── inventory
├── main.yml
├── playbooks
│   ├── db_setup.yml
│   └── web_configure.yml
└── tasks
    ├── verify_config.yml
    └── web_setup.yml

2 directories, 6 files

메인 진입점 (main.yml), 별도의 플레이북 파일, 재사용 가능한 작업 파일이 있는 이 구조는 Ansible 프로젝트를 관리하는 확장 가능하고 유지 관리 가능한 방법입니다.

이제 최상위 main.yml 플레이북을 실행하여 전체 워크플로우를 실행합니다.

ansible-playbook main.yml -i inventory

플레이북이 성공적으로 완료된 후 다음 중요한 단계는 검증입니다. 시스템이 의도한 상태인지 확인해야 합니다. 플레이북은 웹 서버에 httpd 패키지를, 데이터베이스 서버에 mariadb 패키지를 설치하도록 설계되었습니다. 이 랩의 모든 작업은 로컬 머신에서 실행되므로 rpm 명령을 사용하여 직접 설치를 확인할 수 있습니다.

먼저 웹 서버 구성의 일부로 httpd 패키지가 설치되었는지 확인합니다.

rpm -q httpd

패키지가 설치되었음을 확인하는 출력을 볼 수 있습니다.

httpd-2.4.xx-x.el9.x86_64

다음으로 데이터베이스 서버 구성에서 mariadb 패키지 설치를 확인합니다.

rpm -q mariadb

마찬가지로 mariadb 가 설치되었음을 확인하는 내용을 볼 수 있습니다.

mariadb-10.5.xx-x.el9.x86_64

패키지 이름을 출력에서 보는 것은 Ansible 플레이북이 시스템을 의도한 대로 성공적으로 구성했음을 확인합니다. 이제 처음부터 끝까지 모듈식 Ansible 프로젝트를 성공적으로 구축, 실행 및 검증했습니다.

요약

이 실습에서는 RHEL 에서 복잡한 Ansible 플레이북을 구조화하는 필수 기술을 배웠습니다. 인벤토리 파일에 정의된 노드를 정확하게 대상으로 지정하기 위해 기본 그룹 이름, 와일드카드, 제외 및 논리 연산자를 사용하는 호스트 선택의 기본부터 시작했습니다. 그런 다음 초점을 모듈화로 전환하여 동적 포함을 위한 include_tasks와 정적 포함을 위한 import_tasks를 모두 사용하여 대규모 플레이를 더 관리하기 쉽고 재사용 가능한 구성 요소로 분해하는 연습을 했습니다.

이러한 기술을 바탕으로 개별 플레이북을 import_playbook으로 연결하여 완전하고 다단계 워크플로우를 구성하는 방법을 배웠습니다. 실습 과정에는 Ansible 설치, 프로젝트 구조 생성, 간단한 플레이북을 정교한 다중 파일 구조로 점진적으로 리팩토링하는 작업이 포함되었습니다. 실습은 최종 복합 플레이북을 실행하고 전체 자동화 워크플로우가 올바르게 대상이 지정된 호스트에 대해 성공적으로 실행되었는지 확인하는 것으로 마무리되었으며, 이는 자동화에 대한 체계적이고 확장 가능한 접근 방식을 보여주었습니다.