RHEL에서 Ansible을 사용하여 변수 및 팩트 관리하기

AnsibleBeginner
지금 연습하기

소개

이 실습에서는 Red Hat Enterprise Linux (RHEL) 시스템에서 Ansible 플레이북 내의 변수, 팩트, 시크릿을 관리하는 핵심 기술을 배웁니다. 플레이북 변수를 사용하여 자동화를 더욱 유연하고 강력하게 만드는 방법, 내장 및 사용자 지정 Ansible 팩트를 통해 시스템 정보를 수집하는 방법, 그리고 Ansible Vault를 사용하여 비밀번호와 같은 민감한 데이터를 보호하는 방법을 살펴봅니다.

일련의 실습 단계를 통해 Apache 웹 서버를 배포하고 구성하는 플레이북을 작성하게 됩니다. 먼저 패키지 이름과 웹 콘텐츠에 대한 간단한 변수를 정의하고, 사용자 지정 팩트를 활용하여 웹 서버 구성을 동적으로 업데이트합니다. 마지막으로 Ansible Vault를 사용하여 암호화된 비밀번호로 새로운 시스템 사용자를 안전하게 생성하고, 전체 플레이북을 실행하여 모든 구성이 성공적으로 적용되었는지 확인합니다.

플레이북 변수를 정의하고 사용하여 Apache 웹 서버 배포하기

이 단계에서는 Ansible 플레이북에서 변수를 사용하는 방법을 배웁니다. 변수는 자동화를 유연하고 재사용 가능하며 읽기 및 유지 관리가 쉽게 만드는 데 필수적입니다. 패키지 이름이나 파일 경로와 같은 값을 작업에 직접 하드코딩하는 대신, 변수로 정의하고 플레이북 전체에서 참조할 수 있습니다. 변수를 사용하여 Apache 웹 서버(httpd)를 설치하고 기본적인 웹 페이지를 배포하는 간단한 플레이북을 만들어 보겠습니다.

  1. 프로젝트 디렉토리로 이동

    먼저 올바른 작업 디렉토리에 있는지 확인하십시오. 이 실습의 모든 작업은 생성된 ~/project 디렉토리 내에서 수행됩니다.

    cd ~/project
    

    ansible-core 패키지를 설치합니다.

    sudo dnf install -y ansible-core
    
  2. Ansible 플레이북 생성

    이제 플레이북 파일을 생성하겠습니다. 이름은 playbook.yml로 지정합니다. nano와 같은 명령줄 텍스트 편집기를 사용하여 파일을 생성하고 편집할 수 있습니다.

    nano playbook.yml
    

    이 명령은 nano 편집기에서 빈 파일을 엽니다. 이제 플레이북의 초기 부분을 추가합니다. 이 섹션에서는 플레이의 이름, 대상 호스트(localhost, 동일한 머신에서 실행하므로), 그리고 변수를 정의할 vars 섹션을 설정합니다.

    ---
    - name: Deploy Apache using variables
      hosts: localhost
      become: true
      vars:
        web_pkg: httpd
        web_content: "Hello from Ansible Variables"
    

    플레이북 구조에 대한 설명은 다음과 같습니다.

    • hosts: localhost: 플레이북이 로컬 머신에서 실행되어야 함을 지정합니다.
    • become: true: Ansible에 작업 수행 시 권한 상승(sudo와 동일)을 사용하도록 지시하며, 소프트웨어 설치 시 필요합니다.
    • vars: 변수에 대한 키-값 쌍을 정의하는 딕셔너리입니다. 패키지 이름을 위해 web_pkg를, 테스트 웹 페이지의 내용을 위해 web_content를 정의했습니다.
  3. 플레이북에 작업 추가

    다음으로 vars 섹션 아래에 이 변수들을 사용할 tasks를 추가합니다. 첫 번째 작업은 Apache 패키지를 설치하고, 두 번째 작업은 index.html 파일을 생성합니다. nano 편집기 상태에서 playbook.yml 파일에 다음 tasks 블록을 추가하십시오.

    tasks:
      - name: Install the latest version of Apache
        ansible.builtin.dnf:
          name: "{{ web_pkg }}"
          state: latest
    
      - name: Create a basic index.html file
        ansible.builtin.copy:
          content: "{{ web_content }}"
          dest: /var/www/html/index.html
    

    앞서 정의한 변수를 참조하기 위해 {{ variable_name }}을 어떻게 사용하는지 확인하십시오. 이는 Ansible이 변수에 사용하는 Jinja2 템플릿입니다. 이를 통해 작업 정의가 일반화됩니다. 예를 들어 Nginx를 설치하려면 작업 자체를 수정할 필요 없이 web_pkg 변수만 변경하면 됩니다.

  4. 플레이북 검토 및 저장

    완성된 playbook.yml 파일은 다음과 같아야 합니다. YAML은 공백에 매우 민감하므로 내용과 들여쓰기를 다시 한번 확인하십시오.

    ---
    - name: Deploy Apache using variables
      hosts: localhost
      become: true
      vars:
        web_pkg: httpd
        web_content: "Hello from Ansible Variables"
      tasks:
        - name: Install the latest version of Apache
          ansible.builtin.dnf:
            name: "{{ web_pkg }}"
            state: latest
    
        - name: Create a basic index.html file
          ansible.builtin.copy:
            content: "{{ web_content }}"
            dest: /var/www/html/index.html
    

    nano에서 파일을 저장하려면 Ctrl+X를 누른 다음 Y를 눌러 변경 사항을 확인하고, 마지막으로 Enter를 눌러 playbook.yml 이름으로 저장합니다.

  5. 플레이북 구문 확인

    플레이북을 실행하기 전에 구문에 오류가 없는지 확인하는 것이 좋습니다.

    ansible-playbook --syntax-check playbook.yml
    

    구문이 올바르면 다음과 같이 플레이북 파일 경로가 출력되어 유효함을 확인해 줍니다.

    playbook: playbook.yml
    

    오류가 발생하면 nano playbook.yml로 파일을 다시 열어 수정하십시오. 올바른 들여쓰기(보통 공백 2칸)에 주의하십시오.

  6. 플레이북 실행

    이제 플레이북을 실행합니다. Ansible은 localhost에 연결하여 변수를 읽고 작업을 수행합니다.

    ansible-playbook playbook.yml
    

    각 작업이 성공적으로 실행되었음을 나타내는 출력이 표시됩니다. changed 상태는 Ansible이 패키지 설치나 파일 생성과 같은 시스템 변경을 수행했음을 의미합니다.

    PLAY [Deploy Apache using variables] *******************************************
    
    TASK [Gathering Facts] *********************************************************
    ok: [localhost]
    
    TASK [Install the latest version of Apache] ************************************
    changed: [localhost]
    
    TASK [Create a basic index.html file] ******************************************
    changed: [localhost]
    
    PLAY RECAP *********************************************************************
    localhost                  : ok=3    changed=2    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
    

    플레이북을 두 번째로 실행하면 패키지가 이미 설치되어 있고 파일 내용이 올바르기 때문에 changed 대신 ok가 표시됩니다. 이는 Ansible의 멱등성(idempotency)을 보여줍니다.

  7. 수동으로 구성 확인

    플레이북이 완료되었지만, 작업이 예상대로 수행되었는지 수동으로 확인할 수 있습니다. 먼저 httpd 패키지가 설치되었는지 확인합니다.

    rpm -q httpd
    

    출력에 패키지 이름과 버전이 표시되어야 합니다.

    httpd-2.4.57-7.el9.x86_64
    

    다음으로 index.html 파일의 내용을 확인합니다.

    cat /var/www/html/index.html
    

    출력은 web_content 변수의 값과 일치해야 합니다.

    Hello from Ansible Variables
    

    Ansible 플레이북에서 변수를 사용하여 시스템을 성공적으로 구성했습니다.

Ansible 팩트를 사용하여 시스템 정보 표시하기

이 단계에서는 Ansible 팩트를 살펴봅니다. 팩트는 Ansible이 관리하는 시스템(여기서는 localhost)에 대해 수집하는 정보 조각입니다. 이 정보에는 운영 체제, 네트워크 인터페이스, 메모리 등에 대한 세부 정보가 포함됩니다. 기본적으로 Ansible은 모든 플레이 시작 시 팩트를 수집하며, 이를 ansible_facts라는 특수 변수에서 사용할 수 있습니다. 팩트를 사용하면 실행 중인 환경에 적응하는 동적인 플레이북을 만들 수 있습니다.

  1. 프로젝트 디렉토리로 이동

    먼저 새 플레이북을 생성할 ~/project 디렉토리에 있는지 확인하십시오.

    cd ~/project
    
  2. 모든 팩트를 표시하는 플레이북 생성

    먼저 Ansible이 시스템에 대해 수집할 수 있는 모든 팩트를 표시하는 플레이북을 만들어 보겠습니다. 이를 통해 얼마나 많은 정보를 사용할 수 있는지 알 수 있습니다. nano를 사용하여 display_facts.yml이라는 새 파일을 생성합니다.

    nano display_facts.yml
    

    nano 편집기 내에 다음 내용을 추가합니다. 이 플레이북은 localhost를 대상으로 하며 ansible.builtin.debug 모듈을 사용하여 ansible_facts 변수의 내용을 출력합니다.

    ---
    - name: Display all Ansible facts
      hosts: localhost
      tasks:
        - name: Print all available facts
          ansible.builtin.debug:
            var: ansible_facts
    

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

  3. 플레이북 실행

    이제 플레이북을 실행하여 결과를 확인합니다.

    ansible-playbook display_facts.yml
    

    Ansible이 많은 데이터를 수집하므로 출력 내용이 매우 깁니다. 모든 시스템 세부 정보가 포함된 거대한 JSON 구조가 출력될 것입니다. 이는 정상입니다.

    PLAY [Display all Ansible facts] ***********************************************
    
    TASK [Gathering Facts] *********************************************************
    ok: [localhost]
    
    TASK [Print all available facts] ***********************************************
    ok: [localhost] => {
        "ansible_facts": {
            "ansible_all_ipv4_addresses": [
                "172.17.0.2"
            ],
            ...
            "ansible_distribution": "RedHat",
            "ansible_distribution_major_version": "9",
            ...
        }
    }
    
    PLAY RECAP *********************************************************************
    localhost                  : ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
    
  4. 특정 팩트를 표시하는 플레이북 생성

    모든 팩트를 표시하는 것은 탐색에 유용하지만, 대부분의 경우 특정 정보만 필요합니다. display_specific_facts.yml이라는 또 다른 플레이북을 만들어 몇 가지 핵심 팩트만 포함된 형식화된 메시지를 표시해 보겠습니다.

    nano display_specific_facts.yml
    

    다음 내용을 추가합니다. 이 플레이북은 debug 모듈의 msg 매개변수를 사용하여 사용자 지정 문자열을 출력합니다. ansible_facts['distribution']과 같이 대괄호 표기법을 사용하여 개별 팩트에 액세스합니다.

    ---
    - name: Display specific Ansible facts
      hosts: localhost
      tasks:
        - name: Print a summary of system facts
          ansible.builtin.debug:
            msg: >
              The operating system is {{ ansible_facts['distribution'] }}
              version {{ ansible_facts['distribution_major_version'] }}.
              It has {{ ansible_facts['processor_cores'] }} processor cores and
              {{ ansible_facts['memtotal_mb'] }} MB of total memory.
    

    msg: >에서 > 문자는 다중 행 문자열을 더 깔끔하게 작성할 수 있게 해주는 YAML 기능입니다. 파일을 저장하고 nano를 종료합니다.

  5. 특정 팩트에 대한 플레이북 실행

    이제 이 새 플레이북을 실행합니다.

    ansible-playbook display_specific_facts.yml
    

    출력은 훨씬 깔끔하고 읽기 쉬우며, 요청한 정보만 표시됩니다.

    PLAY [Display specific Ansible facts] ******************************************
    
    TASK [Gathering Facts] *********************************************************
    ok: [localhost]
    
    TASK [Print a summary of system facts] *****************************************
    ok: [localhost] => {
        "msg": "The operating system is RedHat version 9. It has 2 processor cores and 3925 MB of total memory."
    }
    
    PLAY RECAP *********************************************************************
    localhost                  : ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
    

    이는 Ansible 팩트를 활용하여 플레이북이 실행 중인 환경을 인식하게 함으로써 더 지능적이고 조건부인 자동화를 구현하는 방법을 보여줍니다.

관리 호스트의 사용자 지정 팩트를 사용하여 웹 서버 구성하기

이 단계에서는 사용자 지정 팩트를 사용하는 방법을 배웁니다. Ansible은 광범위한 표준 팩트를 자동으로 수집하지만, 직접 정의할 수도 있습니다. 이를 "로컬 팩트" 또는 "사용자 지정 팩트"라고 합니다. 이는 애플리케이션 설정이나 Ansible이 기본적으로 수집하지 않는 하드웨어별 데이터와 같은 특정 정보를 관리 호스트에서 플레이북으로 제공할 수 있게 해주는 강력한 기능입니다.

Ansible은 관리 호스트의 /etc/ansible/facts.d 디렉토리에서 사용자 지정 팩트를 찾습니다. 이 디렉토리에 있는 .fact 확장자를 가진 모든 파일이 처리됩니다. 이러한 파일은 간단한 INI 스타일 텍스트 파일이나 JSON 파일일 수 있습니다.

  1. 사용자 지정 팩트 디렉토리 생성

    먼저 Ansible이 사용자 지정 팩트 파일을 찾을 디렉토리를 생성해야 합니다. 시스템 디렉토리이므로 sudo를 사용하여 생성해야 합니다.

    sudo mkdir -p /etc/ansible/facts.d
    

    -p 플래그는 디렉토리가 이미 존재하더라도 오류를 반환하지 않도록 합니다.

  2. 사용자 지정 팩트 파일 생성

    이제 웹 서버에 대한 환영 메시지를 정의하는 사용자 지정 팩트 파일을 생성해 보겠습니다. /etc/ansible/facts.d 디렉토리에 web_config.fact라는 INI 형식 파일을 생성합니다.

    sudo nano /etc/ansible/facts.d/web_config.fact
    

    파일에 다음 내용을 추가합니다. 이는 welcome_message 키를 가진 [webserver] 섹션을 정의합니다.

    [webserver]
    welcome_message = Welcome to the server configured by Custom Facts!
    

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

  3. 사용자 지정 팩트를 사용하는 플레이북 생성

    사용자 지정 팩트가 준비되었으므로, 이제 이 팩트를 읽어 웹 서버의 홈 페이지를 구성하는 플레이북을 만들 수 있습니다. ~/project 디렉토리에 configure_web.yml이라는 새 플레이북을 생성합니다.

    cd ~/project
    nano configure_web.yml
    

    플레이북에 다음 내용을 추가합니다. 이 플레이북은 사용자 지정 팩트에 정의된 메시지로 /var/www/html/index.html 파일을 업데이트합니다.

    ---
    - name: Configure web server using custom facts
      hosts: localhost
      become: true
      tasks:
        - name: Update index.html with custom message
          ansible.builtin.copy:
            content: "{{ ansible_facts.ansible_local.web_config.webserver.welcome_message }}"
            dest: /var/www/html/index.html
    

    변수 {{ ansible_facts.ansible_local.web_config.webserver.welcome_message }}를 분석해 보겠습니다.

    • ansible_facts: 모든 팩트의 루트 딕셔너리입니다.
    • ansible_local: 모든 사용자 지정 팩트가 저장되는 키입니다.
    • web_config: 확장자를 제외한 팩트 파일 이름(web_config.fact)입니다.
    • webserver: INI 파일의 섹션 이름 [webserver]입니다.
    • welcome_message: 사용하려는 값의 키입니다.

    파일을 저장하고 nano를 종료합니다.

  4. 구성 플레이북 실행

    이제 플레이북을 실행하여 구성을 적용합니다.

    ansible-playbook configure_web.yml
    

    출력에서 copy 작업이 index.html 파일을 changed했음을 보여주어야 합니다.

    PLAY [Configure web server using custom facts] *********************************
    
    TASK [Gathering Facts] *********************************************************
    ok: [localhost]
    
    TASK [Update index.html with custom message] ***********************************
    changed: [localhost]
    
    PLAY RECAP *********************************************************************
    localhost                  : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
    
  5. 결과 확인

    마지막으로 웹 페이지가 올바르게 업데이트되었는지 확인합니다. cat 명령을 사용하여 index.html 파일의 내용을 확인합니다.

    cat /var/www/html/index.html
    

    출력에 사용자 지정 팩트 파일의 메시지가 표시되어야 합니다.

    Welcome to the server configured by Custom Facts!
    

    관리 호스트에 사용자 지정 팩트를 성공적으로 생성하고 이를 플레이북 내에서 사용하여 서비스를 동적으로 구성했습니다. 이 기술은 자동화를 더욱 유연하고 데이터 기반으로 만드는 데 매우 유용합니다.

Ansible Vault를 사용하여 암호화된 변수로 시스템 사용자 생성하기

이 단계에서는 Ansible Vault를 사용하여 비밀번호나 API 키와 같은 민감한 데이터를 관리하는 방법을 배웁니다. 플레이북 내에 민감한 정보를 일반 텍스트로 저장하는 것은 심각한 보안 위험입니다. Ansible Vault는 파일이나 개별 변수를 암호화하여 시크릿을 안전하게 유지하는 방법을 제공합니다. 그런 다음 플레이북에서 이러한 암호화된 파일을 사용할 수 있으며, 올바른 비밀번호를 제공하면 Ansible이 런타임에 이를 복호화합니다.

사용자 이름과 해시된 비밀번호가 포함된 암호화된 파일을 생성하고, 플레이북을 사용하여 이 자격 증명으로 새로운 시스템 사용자를 생성해 보겠습니다.

  1. 프로젝트 디렉토리로 이동

    이 작업을 위해 ~/project 디렉토리에 있는지 확인하십시오.

    cd ~/project
    
  2. 암호화된 Vault 파일 생성

    ansible-vault create 명령을 사용하여 secrets.yml이라는 새로운 암호화된 YAML 파일을 생성합니다. 이 명령은 Vault에 대한 비밀번호를 생성하라는 메시지를 표시합니다. 이 비밀번호는 나중에 파일을 열거나 편집하거나 사용할 때 필요합니다.

    먼저 작업하기 쉽도록 편집기를 nano로 설정합니다.

    export EDITOR=nano
    

    이제 Vault 파일을 생성합니다.

    ansible-vault create secrets.yml
    

    메시지가 표시되면 Vault 비밀번호를 입력합니다. 이 실습에서는 간단하게 labex를 Vault 비밀번호로 사용하겠습니다. 두 번 입력해야 합니다.

    New Vault password:
    Confirm New Vault password:
    

    비밀번호를 확인하면 명령이 nano 텍스트 편집기에서 secrets.yml 파일을 엽니다.

  3. Vault 파일에 시크릿 변수 추가

    이제 암호화된 secrets.yml 파일을 편집 중인 nano 편집기 내에 다음 변수를 추가합니다. 새 사용자에 대한 사용자 이름과 미리 해시된 비밀번호를 정의합니다. 해시된 비밀번호를 사용하는 것이 일반 텍스트 비밀번호를 저장하는 것보다 훨씬 안전합니다.

    username: myappuser
    pwhash: $6$mysalt$QwMzWSEyCAGmz7tzVrAi5o.8k4d05i2QsfGGwmPtlJsWhGjSjCW6yFCH/OEqEsHk7GMSxqYNXu5sshxPmWyxo0
    
    • username: 생성하려는 시스템 사용자의 이름입니다.
    • pwhash: 안전하게 해시된 비밀번호입니다. 이 특정 해시는 AnsibleUserP@ssw0rd 비밀번호에 해당하며 ansible.builtin.user 모듈이 이해할 수 있는 형식입니다.

    파일을 저장하고 nano를 종료합니다(Ctrl+X, Y, Enter). 이제 ~/project 디렉토리의 secrets.yml 파일이 암호화되었습니다. cat secrets.yml로 보려고 하면 암호화된 텍스트만 보입니다.

  4. Vault 파일을 사용하는 플레이북 생성

    이제 암호화된 secrets.yml 파일의 변수를 사용할 create_user.yml이라는 새 플레이북을 생성합니다.

    nano create_user.yml
    

    다음 내용을 추가합니다. vars_files 지시문은 Ansible에 지정된 파일에서 변수를 로드하도록 지시합니다.

    ---
    - name: Create a user from secret variables
      hosts: localhost
      become: true
      vars_files:
        - secrets.yml
      tasks:
        - name: Create the {{ username }} user
          ansible.builtin.user:
            name: "{{ username }}"
            password: "{{ pwhash }}"
            state: present
    

    이 플레이북은 secrets.yml에 정의된 이름과 비밀번호 해시로 사용자를 생성합니다. 파일을 저장하고 nano를 종료합니다.

  5. Vault 비밀번호로 플레이북 실행

    Vault 파일을 사용하는 플레이북을 실행하려면 Vault 비밀번호를 제공해야 합니다. --ask-vault-pass 플래그를 사용하여 대화식으로 수행할 수 있습니다.

    ansible-playbook --ask-vault-pass create_user.yml
    

    Ansible이 Vault 비밀번호를 묻습니다. labex(2단계에서 설정한 비밀번호)를 입력합니다.

    Vault password:
    

    올바른 비밀번호를 제공하면 Ansible이 메모리에서 파일을 복호화하고 플레이북을 실행합니다. 사용자가 생성되었음을 나타내는 다음 출력이 표시되어야 합니다.

    PLAY [Create a user from secret variables] *************************************
    
    TASK [Gathering Facts] *********************************************************
    ok: [localhost]
    
    TASK [Create the myappuser user] ***********************************************
    changed: [localhost]
    
    PLAY RECAP *********************************************************************
    localhost                  : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
    
  6. 사용자 생성 확인

    id 명령을 사용하여 myappuser가 시스템에 성공적으로 생성되었는지 확인할 수 있습니다.

    id myappuser
    

    사용자가 존재하면 사용자 ID(uid) 및 그룹 ID(gid) 정보가 표시됩니다.

    uid=1002(myappuser) gid=1002(myappuser) groups=1002(myappuser)
    

    이로써 Ansible Vault를 사용하여 자동화 작업을 위한 민감한 데이터를 성공적으로 관리했음을 확인했습니다.

Vault 비밀번호 파일로 플레이북을 실행하여 구성 적용하기

이 단계에서는 Ansible에 Vault 비밀번호를 제공하는 더 자동화된 방법을 배웁니다. 이전 단계에서는 --ask-vault-pass를 사용하여 대화식으로 비밀번호를 입력했습니다. 이는 안전하지만 비밀번호를 입력할 사용자가 없는 CI/CD 파이프라인과 같은 자동화된 환경에는 적합하지 않습니다.

해결책은 Vault 비밀번호 파일을 사용하는 것입니다. 이는 Vault 비밀번호가 포함된 간단한 텍스트 파일입니다. 플레이북을 실행할 때 이 파일을 참조하면 Ansible이 자동으로 비밀번호를 읽어옵니다. 보안을 위해 이 비밀번호 파일의 권한을 제한하여 승인된 사용자만 읽을 수 있도록 하는 것이 중요합니다.

  1. 프로젝트 디렉토리로 이동

    플레이북과 Vault 파일이 있는 ~/project 디렉토리에 있는지 확인하십시오.

    cd ~/project
    
  2. Vault 비밀번호 파일 생성

    Vault 비밀번호를 저장할 파일을 생성해 보겠습니다. 이름은 vault_pass.txt로 지정합니다. echo 명령을 사용하여 파일을 생성하고 한 단계로 비밀번호(labex)를 기록할 수 있습니다.

    echo "labex" > vault_pass.txt
    

    cat으로 파일 내용을 확인할 수 있습니다.

    cat vault_pass.txt
    

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

    labex
    
  3. 비밀번호 파일 보안

    일반 텍스트 파일에 비밀번호를 저장하는 것은 위험합니다. 보호를 위해 파일 권한을 제한해야 합니다. chmod 명령을 사용하면 파일 권한을 변경할 수 있습니다. 권한을 600으로 설정하여 파일 소유자(이 경우 labex 사용자)만 읽기 및 쓰기 권한을 갖도록 합니다. 시스템의 다른 사용자는 액세스할 수 없습니다.

    chmod 600 vault_pass.txt
    

    ls -l 명령을 사용하여 새 권한을 확인할 수 있습니다.

    ls -l vault_pass.txt
    

    출력은 -rw-------로 시작하여 제한된 권한을 확인해 줍니다.

    -rw-------. 1 labex labex 6 May 21 14:30 vault_pass.txt
    
  4. 사용자를 그룹에 추가하도록 플레이북 수정

    create_user.yml 플레이북을 수정하여 추가 작업을 수행해 보겠습니다. myappuserwheel 그룹에 추가합니다. 많은 시스템에서 이 그룹은 관리자(sudo) 권한을 부여합니다. 이는 기존 구성을 변경하는 플레이북 실행을 보여줍니다.

    먼저 편집을 위해 create_user.yml 플레이북을 엽니다.

    nano create_user.yml
    

    ansible.builtin.user 작업을 수정하여 groupsappend 매개변수를 포함합니다.

    ---
    - name: Create a user from secret variables
      hosts: localhost
      become: true
      vars_files:
        - secrets.yml
      tasks:
        - name: Create the {{ username }} user and add to wheel group
          ansible.builtin.user:
            name: "{{ username }}"
            password: "{{ pwhash }}"
            state: present
            groups: wheel
            append: true
    
    • groups: wheel: 사용자를 추가할 그룹을 지정합니다.
    • append: true: 사용자가 속할 수 있는 다른 그룹에서 제거하지 않고 이 그룹에 추가되도록 합니다.

    파일을 저장하고 nano를 종료합니다.

  5. Vault 비밀번호 파일로 플레이북 실행

    이제 플레이북을 다시 실행합니다. 이번에는 --ask-vault-pass 대신 --vault-password-file 옵션(또는 더 짧은 별칭 --vault-pass-file)을 사용하여 비밀번호 파일 경로를 지정합니다.

    ansible-playbook --vault-password-file vault_pass.txt create_user.yml
    

    이제 Ansible은 vault_pass.txt에서 직접 비밀번호를 읽기 때문에 비밀번호를 묻지 않고 실행됩니다. 사용자 구성이 변경되었음을 나타내는 출력이 표시되어야 합니다.

    PLAY [Create a user from secret variables] *************************************
    
    TASK [Gathering Facts] *********************************************************
    ok: [localhost]
    
    TASK [Create the myappuser user and add to wheel group] ************************
    changed: [localhost]
    
    PLAY RECAP *********************************************************************
    localhost                  : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
    

    changed 상태는 Ansible이 사용자를 wheel 그룹에 추가하여 수정했음을 확인해 줍니다.

  6. 사용자의 그룹 멤버십 확인

    마지막으로 myappuser가 이제 wheel 그룹의 구성원인지 확인합니다. groups 명령으로 확인할 수 있습니다.

    groups myappuser
    

    출력에 사용자의 기본 그룹(myappuser)과 wheel 그룹이 모두 표시되어야 합니다.

    myappuser : myappuser wheel
    

    Vault 비밀번호 파일을 사용하여 비대화식으로 플레이북을 성공적으로 실행했습니다. 이는 안전한 워크플로우를 자동화하는 핵심 기술입니다.

웹 서버 및 사용자 구성 확인하기

이 마지막 단계에서는 전용 확인 플레이북을 생성하여 학습 내용을 통합합니다. 지금까지는 cat, id, groups와 같은 표준 Linux 명령을 사용하여 플레이북 결과를 수동으로 확인했습니다. 더 강력하고 반복 가능한 접근 방식은 Ansible 자체를 사용하여 시스템 상태를 감사하고 검증하는 것입니다.

이 플레이북은 테스트 스위트 역할을 하여 웹 서버가 설치되었는지, 웹 페이지에 올바른 내용이 있는지, 시스템 사용자가 적절한 그룹 멤버십으로 존재하는지 프로그래밍 방식으로 확인합니다. 이는 Ansible이 구성 관리뿐만 아니라 규정 준수 및 상태 검증에도 어떻게 사용될 수 있는지 보여줍니다.

  1. 프로젝트 디렉토리로 이동

    먼저 ~/project 디렉토리에 있는지 확인하십시오.

    cd ~/project
    
  2. 확인 플레이북 생성

    verify_config.yml이라는 새 플레이북을 생성합니다. 이 플레이북에는 이전 단계에서 적용한 구성을 확인하는 일련의 작업이 포함됩니다.

    nano verify_config.yml
    
  3. 구성을 확인하는 작업 추가

    nano 편집기 내에 다음 내용을 추가합니다. 각 작업은 특정 조건이 참임을 주장(assert)하도록 설계되었습니다. 주장 중 하나라도 실패하면 플레이북이 중지되고 오류를 보고하여 무엇이 잘못되었는지 즉시 알려줍니다.

    ---
    - name: Verify system configuration
      hosts: localhost
      become: true
      tasks:
        - name: Check if httpd package is installed
          ansible.builtin.dnf:
            list: httpd
          register: httpd_pkg_info
    
        - name: Assert that httpd is installed
          ansible.builtin.assert:
            that:
              - httpd_pkg_info.results | length > 0
            fail_msg: "Apache (httpd) package is not installed."
            success_msg: "Apache (httpd) package is installed."
    
        - name: Read the content of the index.html file
          ansible.builtin.slurp:
            src: /var/www/html/index.html
          register: index_file
    
        - name: Assert that the web page content is correct
          ansible.builtin.assert:
            that:
              - "'Custom Facts' in (index_file.content | b64decode)"
            fail_msg: "Web page content is incorrect."
            success_msg: "Web page content is correct."
    
        - name: Check if myappuser exists
          ansible.builtin.getent:
            database: passwd
            key: myappuser
          register: user_info
    
        - name: Assert that myappuser exists
          ansible.builtin.assert:
            that:
              - user_info.ansible_facts.getent_passwd['myappuser'] is defined
            fail_msg: "User 'myappuser' does not exist."
            success_msg: "User 'myappuser' exists."
    
        - name: Query the wheel group members
          ansible.builtin.getent:
            database: group
            key: wheel
          register: wheel_group_info
    
        - name: Assert that myappuser is in the wheel group
          ansible.builtin.assert:
            that:
              - "'myappuser' in (wheel_group_info.ansible_facts.getent_group['wheel'][2] | default('') | split(','))"
            fail_msg: "User 'myappuser' is not in the wheel group."
            success_msg: "User 'myappuser' is in the wheel group."
    

    여기서 사용된 핵심 모듈을 검토해 보겠습니다.

    • ansible.builtin.dnf (list 포함): 패키지를 확인하고 결과를 register합니다.
    • ansible.builtin.slurp: 원격 호스트에서 파일의 전체 내용을 "slurp"합니다. 내용은 안전한 전송을 위해 base64로 인코딩됩니다.
    • ansible.builtin.getent: passwdgroup과 같은 시스템 데이터베이스를 안전하게 쿼리하는 방법입니다. 결과는 ansible_facts 아래에 저장되므로 user_info.ansible_facts.getent_passwd와 같은 키를 통해 반환된 데이터에 액세스합니다.
    • ansible.builtin.assert: 검증의 핵심입니다. 주어진 조건이 참인지 확인합니다. 그렇지 않으면 플레이가 실패합니다. 사용자 지정 성공 및 실패 메시지를 제공합니다.
    • b64decode: slurp 모듈에서 가져온 base64 콘텐츠를 디코딩하는 데 사용되는 Jinja2 필터입니다.

    passwdgroup 데이터베이스를 별도로 쿼리한다는 점에 유의하십시오. 이렇게 하면 사용자 존재 확인과 wheel 그룹 멤버십 확인이 getent가 반환한 실제 데이터와 일치하게 유지됩니다.

    파일을 저장하고 nano를 종료합니다(Ctrl+X, Y, Enter).

  4. 확인 플레이북 실행

    이제 확인 플레이북을 실행합니다. Vault 파일을 사용하지 않으므로 비밀번호를 제공할 필요가 없습니다.

    ansible-playbook verify_config.yml
    

    이전 단계가 모두 올바르게 완료되었다면 플레이북이 성공적으로 실행되고 각 주장에 대한 사용자 지정 성공 메시지가 표시됩니다.

    PLAY [Verify system configuration] *********************************************
    
    TASK [Gathering Facts] *********************************************************
    ok: [localhost]
    
    TASK [Check if httpd package is installed] *************************************
    ok: [localhost]
    
    TASK [Assert that httpd is installed] ******************************************
    ok: [localhost] => {
        "changed": false,
        "msg": "Apache (httpd) package is installed."
    }
    
    TASK [Read the content of the index.html file] *********************************
    ok: [localhost]
    
    TASK [Assert that the web page content is correct] *****************************
    ok: [localhost] => {
        "changed": false,
        "msg": "Web page content is correct."
    }
    
    TASK [Check if myappuser exists] ***********************************************
    ok: [localhost]
    
    TASK [Assert that myappuser exists] ********************************************
    ok: [localhost] => {
        "changed": false,
        "msg": "User 'myappuser' exists."
    }
    
    TASK [Query the wheel group members] *******************************************
    ok: [localhost]
    
    TASK [Assert that myappuser is in the wheel group] *****************************
    ok: [localhost] => {
        "changed": false,
        "msg": "User 'myappuser' is in the wheel group."
    }
    
    PLAY RECAP *********************************************************************
    localhost                  : ok=9    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
    

    축하합니다! Ansible을 사용하여 변수를 정의하고, 시스템 팩트를 수집하고, Vault로 시크릿을 관리하고, 마지막으로 시스템 상태를 자동화된 방식으로 검증하는 데 성공했습니다.

요약

이 실습에서는 RHEL 시스템을 구성하기 위해 Ansible 플레이북 내에서 다양한 유형의 데이터를 관리하는 방법을 배웠습니다. 먼저 표준 플레이북 변수를 정의하고 사용하여 Apache 웹 서버를 유연하게 설치하고 구성했습니다. 그 후, Ansible의 내장 팩트를 활용하여 시스템 정보를 표시하는 방법을 살펴보고, 동적이고 호스트를 인식하는 자동화 작업을 생성하기 위한 기반을 마련했습니다.

이를 바탕으로 관리 호스트에서 사용자 지정 팩트를 생성하고 활용하여 웹 서버를 추가로 구성했습니다. 민감한 정보를 안전하게 처리하기 위해 Ansible Vault를 사용하여 사용자 비밀번호를 암호화하고, 이 암호화된 변수로 새 시스템 사용자를 생성했으며, Vault 비밀번호 파일로 플레이북을 비대화식으로 실행했습니다. 실습은 웹 서버와 새 시스템 사용자가 모두 올바르게 구성되었는지 확인하는 것으로 마무리되었으며, 학습한 모든 개념이 성공적으로 적용되었음을 확인했습니다.