devops2023-09-10·8 min·339/348

Ansible Playbook 실행 에러 해결

Ansible playbook 실행 시 발생하는 에러를 진단하고 해결하는 방법을 알아봅니다.

Ansible Playbook 실행 에러 해결

Ansible은 강력한 설정 자동화 도구이지만, playbook 작성 및 실행에서 various 에러가 발생할 수 있습니다.

Environment

$ ansible --version
ansible [core 2.16.2]
  config file = /etc/ansible/ansible.cfg
  configured module search path = ['/home/user/.ansible/plugins/modules']
  ansible python module location = /usr/lib/python3.11/site-packages/ansible
  python version = 3.11.6

$ ansible-inventory --list
{
    "_meta": {
        "hostvars": {}
    },
    "webservers": {
        "hosts": ["web1", "web2"]
    },
    "dbservers": {
        "hosts": ["db1"]
    }
}

Problem: Playbook 실행 실패

$ ansible-playbook deploy.yml
PLAY [webservers] *************************************************************

TASK [Gathering Facts] *******************************************************
fatal: [web1]: FAILED! => {"changed": false, "msg": "Failed to connect to the host via ssh: ssh: connect to host web1 port 22: Connection refused"}

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

또는:

$ ansible-playbook deploy.yml
PLAY [webservers] *************************************************************

TASK [Install packages] ******************************************************
fatal: [web1]: FAILED! => {"changed": false, "msg": "Failure talking to puppet: Error: Could not retrieve catalog from remote server"}

Analysis: 에러 유형 분석

# SSH 연결 문제
$ ansible all -m ping -vvv

# Permission 확인
$ ansible all -m shell -a "whoami" --become

# Python 확인
$ ansible all -m shell -a "python3 --version"

# Module 실행 테스트
$ ansible web1 -m apt -a "name=nginx state=present" --check

Solution: Playbook 에러 해결

방법 1: SSH 연결 문제 해결

# playbook.yml
- hosts: webservers
  gather_facts: yes
  
  vars:
    ansible_user: deploy
    ansible_port: 22
    ansible_ssh_private_key_file: ~/.ssh/deploy_key
    ansible_python_interpreter: /usr/bin/python3
  
  tasks:
    - name: Test connection
      ping:
# SSH 테스트
$ ansible all -m ping -u deploy --private-key ~/.ssh/deploy_key

# SSH 연결 디버깅
$ ansible all -m shell -a "echo hello" -vvv

방법 2: privilege escalation

- hosts: webservers
  become: yes
  become_method: sudo
  become_user: root
  
  tasks:
    - name: Install packages
      apt:
        name:
          - nginx
          - python3-pip
        state: present
        update_cache: yes
# sudo 테스트
$ ansible all -m shell -a "sudo whoami" --become

# 또는 inventory에서 설정
[webservers]
web1 ansible_become=yes ansible_become_method=sudo

방법 3: 핸들러 사용

- hosts: webservers
  become: yes
  
  handlers:
    - name: restart nginx
      service:
        name: nginx
        state: restarted
    
    - name: reload nginx
      service:
        name: nginx
        state: reloaded
  
  tasks:
    - name: Install nginx
      apt:
        name: nginx
        state: present
      notify: restart nginx
    
    - name: Copy nginx config
      template:
        src: nginx.conf.j2
        dest: /etc/nginx/nginx.conf
      notify: reload nginx

방법 4: 롤백 및 에러 핸들링

- hosts: webservers
  become: yes
  
  tasks:
    - name: Deploy application
      block:
        - name: Copy new version
          copy:
            src: app.tar.gz
            dest: /opt/app/
        
        - name: Extract archive
          unarchive:
            src: /opt/app/app.tar.gz
            dest: /opt/app/
            remote_src: yes
        
        - name: Restart service
          service:
            name: myapp
            state: restarted
      
      rescue:
        - name: Restore previous version
          copy:
            src: /opt/app/backup/
            dest: /opt/app/
        
        - name: Restart service
          service:
            name: myapp
            state: restarted
      
      always:
        - name: Log deployment
          lineinfile:
            path: /var/log/deploy.log
            line: "Deployment completed at {{ ansible_date_time.iso8601 }}"

방법 5: 로컬 실행

# playbook.yml
- hosts: localhost
  connection: local
  gather_facts: yes
  
  tasks:
    - name: Run local commands
      shell: echo "Running locally"
    
    - name: Run on remote hosts
      hosts: webservers
      tasks:
        - name: Remote task
          shell: echo "Running remotely"

Troubleshooting Commands

# 1. Connectivity test
$ ansible all -m ping

# 2. Verbose output
$ ansible-playbook deploy.yml -vvv

# 3. Syntax check
$ ansible-playbook deploy.yml --syntax-check

# 4. Dry run
$ ansible-playbook deploy.yml --check

# 5. Limit to specific host
$ ansible-playbook deploy.yml --limit web1

# 6. Step by step
$ ansible-playbook deploy.yml --step

# 7. List tasks
$ ansible-playbook deploy.yml --list-tasks

Lessons Learned

  1. SSH 사전 테스트: playbook 실행 전 ansible all -m ping으로 SSH 연결을 확인하세요.

  2. become 설정: root 권한이 필요하면 become: yes를 명시적으로 설정하세요.

  3. 변수 관리: inventory 파일이나 group_vars에서 변수를 관리하면 playbook이 깔끔해집니다.

  4. 에러 핸들링: block/rescue/always를 사용하여 배포 실패 시 롤백 로직을 구현하세요.

  5. Verbose 모드: 문제가 발생하면 -vvv 플래그로 상세 로그를 확인하세요.


This blog does not accept any external sponsorships, affiliate marketing, or ad revenue.