Ansible 요약정리

Posted by Albert 67Day 9Hour 15Min 22Sec ago [2025-12-01]

Ansible은 Python 기반의 오픈소스 IT 자동화 도구로, 에이전트 없이 SSH를 통해 서버를 관리합니다.

1. 기본 구성 요소

1.1 인벤토리 (Inventory)

관리할 호스트 목록을 정의합니다.

기본 INI 형식:

' inventory.ini
[webservers]
web1.example.com
web2.example.com

[databases]
db1.example.com
db2.example.com

[production:children]
webservers
databases

[webservers:vars]
ansible_user=ubuntu
ansible_port=22

YAML 형식:

' inventory.yml
all:
  children:
    webservers:
      hosts:
        web1.example.com:
        web2.example.com:
      vars:
        ansible_user: ubuntu
        http_port: 80
    databases:
      hosts:
        db1.example.com:
          ansible_host: 192.168.1.10

동적 인벤토리 (AWS 예제):

' aws_ec2.yml
plugin: aws_ec2
regions:
  - us-east-1
  - ap-northeast-2
filters:
  tag:Environment: production
keyed_groups:
  - key: tags.Role
    prefix: role

1.2 애드혹 명령 (Ad-hoc Commands)

간단한 일회성 작업에 사용합니다.

' 모든 서버에 ping
ansible all -i inventory.ini -m ping

' 특정 그룹에 패키지 설치
ansible webservers -m apt -a "name=nginx state=present" --become

' 파일 복사
ansible all -m copy -a "src=/local/file dest=/remote/file mode=0644"

' 서비스 재시작
ansible webservers -m service -a "name=nginx state=restarted" --become

' 명령 실행
ansible all -m shell -a "df -h"

2. 플레이북 (Playbook)

2.1 기본 플레이북

' basic-playbook.yml
---
- name: 웹서버 설정
  hosts: webservers
  become: yes
  vars:
    http_port: 80
    max_clients: 200
  
  tasks:
    - name: Nginx 설치
      apt:
        name: nginx
        state: present
        update_cache: yes
    
    - name: Nginx 설정 파일 복사
      template:
        src: nginx.conf.j2
        dest: /etc/nginx/nginx.conf
      notify: Restart Nginx
    
    - name: Nginx 서비스 시작
      service:
        name: nginx
        state: started
        enabled: yes
  
  handlers:
    - name: Restart Nginx
      service:
        name: nginx
        state: restarted

2.2 다중 플레이 플레이북

' multi-play.yml
---
- name: 데이터베이스 서버 설정
  hosts: databases
  become: yes
  tasks:
    - name: PostgreSQL 설치
      apt:
        name: postgresql
        state: present

- name: 웹서버 설정
  hosts: webservers
  become: yes
  tasks:
    - name: Apache 설치
      apt:
        name: apache2
        state: present

- name: 로드밸런서 설정
  hosts: loadbalancers
  become: yes
  tasks:
    - name: HAProxy 설치
      apt:
        name: haproxy
        state: present

3. 변수 (Variables)

3.1 변수 정의 방법

' vars-example.yml
---
- name: 변수 사용 예제
  hosts: webservers
  vars:
    ' 직접 정의
    app_name: myapp
    app_port: 8080
    
    ' 리스트
    packages:
      - nginx
      - git
      - curl
    
    ' 딕셔너리
    database:
      host: localhost
      port: 5432
      name: mydb
  
  vars_files:
    - vars/common.yml
    - vars/{{ env }}.yml
  
  tasks:
    - name: 애플리케이션 디렉토리 생성
      file:
        path: "/opt/{{ app_name }}"
        state: directory
    
    - name: 패키지 설치
      apt:
        name: "{{ item }}"
        state: present
      loop: "{{ packages }}"
    
    - name: 데이터베이스 접속 정보 출력
      debug:
        msg: "DB: {{ database.host }}:{{ database.port }}/{{ database.name }}"

3.2 Facts 사용

' facts-example.yml
---
- name: Facts 수집 및 사용
  hosts: all
  tasks:
    - name: Facts 출력
      debug:
        msg: |
          OS: {{ ansible_distribution }} {{ ansible_distribution_version }}
          IP: {{ ansible_default_ipv4.address }}
          메모리: {{ ansible_memtotal_mb }}MB
          CPU: {{ ansible_processor_cores }}코어
    
    - name: OS별 분기 처리
      apt:
        name: apache2
        state: present
      when: ansible_distribution == "Ubuntu"
    
    - name: 커스텀 Facts 설정
      set_fact:
        app_env: "{{ 'production' if ansible_hostname.startswith('prod') else 'development' }}"

4. 조건문과 반복문

4.1 조건문 (When)

' conditionals.yml
---
- name: 조건문 예제
  hosts: all
  become: yes
  tasks:
    - name: Ubuntu에만 apt 업데이트
      apt:
        update_cache: yes
      when: ansible_distribution == "Ubuntu"
    
    - name: 메모리가 4GB 이상일 때만 실행
      debug:
        msg: "충분한 메모리가 있습니다"
      when: ansible_memtotal_mb >= 4096
    
    - name: 복합 조건
      service:
        name: nginx
        state: started
      when:
        - ansible_distribution == "Ubuntu"
        - ansible_distribution_version >= "20.04"
    
    - name: 변수 존재 확인
      debug:
        msg: "DB 호스트: {{ db_host }}"
      when: db_host is defined

4.2 반복문 (Loop)

' loops.yml
---
- name: 반복문 예제
  hosts: webservers
  become: yes
  tasks:
    ' 기본 리스트 반복
    - name: 여러 패키지 설치
      apt:
        name: "{{ item }}"
        state: present
      loop:
        - nginx
        - git
        - vim
    
    ' 딕셔너리 반복
    - name: 여러 사용자 생성
      user:
        name: "{{ item.name }}"
        groups: "{{ item.groups }}"
        state: present
      loop:
        - { name: 'john', groups: 'developers' }
        - { name: 'jane', groups: 'admins' }
        - { name: 'bob', groups: 'developers' }
    
    ' with_items (레거시)
    - name: 여러 디렉토리 생성
      file:
        path: "{{ item }}"
        state: directory
      with_items:
        - /opt/app1
        - /opt/app2
        - /opt/app3
    
    ' loop with index
    - name: 인덱스와 함께 반복
      debug:
        msg: "{{ index }}: {{ item }}"
      loop: "{{ packages }}"
      loop_control:
        index_var: index

5. 템플릿 (Jinja2)

5.1 템플릿 파일

{' templates/nginx.conf.j2 '}
user {{ nginx_user }};
worker_processes {{ ansible_processor_cores }};

events {
    worker_connections {{ worker_connections | default(1024) }};
}

http {
    server {
        listen {{ http_port }};
        server_name {{ server_name }};
        
        {% for location in locations %}
        location {{ location.path }} {
            proxy_pass {{ location.backend }};
        }
        {% endfor %}
        
        {% if enable_ssl %}
        ssl_certificate {{ ssl_cert_path }};
        ssl_certificate_key {{ ssl_key_path }};
        {% endif %}
    }
}

5.2 템플릿 사용 플레이북

' template-playbook.yml
---
- name: 템플릿 적용
  hosts: webservers
  become: yes
  vars:
    nginx_user: www-data
    http_port: 80
    server_name: example.com
    worker_connections: 2048
    enable_ssl: true
    ssl_cert_path: /etc/ssl/cert.pem
    ssl_key_path: /etc/ssl/key.pem
    locations:
      - { path: '/api', backend: 'http://localhost:8080' }
      - { path: '/static', backend: 'http://localhost:8081' }
  
  tasks:
    - name: Nginx 설정 파일 생성
      template:
        src: templates/nginx.conf.j2
        dest: /etc/nginx/nginx.conf
        owner: root
        group: root
        mode: '0644'
      notify: Reload Nginx
  
  handlers:
    - name: Reload Nginx
      service:
        name: nginx
        state: reloaded
```

'' 6. 롤 (Roles)

''' 6.1 롤 구조
```
roles/
  nginx/
    tasks/
      main.yml
    handlers/
      main.yml
    templates/
      nginx.conf.j2
    files/
      index.html
    vars/
      main.yml
    defaults/
      main.yml
    meta/
      main.yml

6.2 롤 파일들

defaults/main.yml:

---
' 기본값 (가장 낮은 우선순위)
nginx_port: 80
nginx_user: www-data
nginx_worker_processes: auto

vars/main.yml:

---
' 롤 변수 (높은 우선순위)
nginx_config_path: /etc/nginx/nginx.conf
nginx_log_path: /var/log/nginx

tasks/main.yml:

---
- name: Nginx 설치
  apt:
    name: nginx
    state: present
    update_cache: yes

- name: Nginx 설정 파일 복사
  template:
    src: nginx.conf.j2
    dest: "{{ nginx_config_path }}"
  notify: Restart Nginx

- name: Nginx 서비스 시작
  service:
    name: nginx
    state: started
    enabled: yes

handlers/main.yml:

---
- name: Restart Nginx
  service:
    name: nginx
    state: restarted

- name: Reload Nginx
  service:
    name: nginx
    state: reloaded

meta/main.yml:

---
dependencies:
  - role: common
  - role: firewall
    vars:
      firewall_allowed_ports:
        - 80
        - 443

6.3 롤 사용 플레이북

' site.yml
---
- name: 웹서버 설정
  hosts: webservers
  become: yes
  roles:
    - common
    - nginx
    - { role: database, db_type: postgresql }
    
- name: 롤에 변수 전달
  hosts: webservers
  become: yes
  roles:
    - role: nginx
      vars:
        nginx_port: 8080
        nginx_user: nginx

7. 핸들러 (Handlers)

' handlers-example.yml
---
- name: 핸들러 예제
  hosts: webservers
  become: yes
  tasks:
    - name: Nginx 설정 변경
      template:
        src: nginx.conf.j2
        dest: /etc/nginx/nginx.conf
      notify:
        - Validate Nginx Config
        - Restart Nginx
    
    - name: SSL 인증서 업데이트
      copy:
        src: cert.pem
        dest: /etc/ssl/cert.pem
      notify: Reload Nginx
  
  handlers:
    - name: Validate Nginx Config
      command: nginx -t
      
    - name: Restart Nginx
      service:
        name: nginx
        state: restarted
    
    - name: Reload Nginx
      service:
        name: nginx
        state: reloaded
      listen: "reload web server"

8. 모듈 활용 예제

8.1 파일 관리 모듈

' file-modules.yml
---
- name: 파일 관리
  hosts: all
  become: yes
  tasks:
    ' 파일 복사
    - name: 파일 복사
      copy:
        src: /local/file.txt
        dest: /remote/file.txt
        owner: root
        group: root
        mode: '0644'
        backup: yes
    
    ' 디렉토리 생성
    - name: 디렉토리 생성
      file:
        path: /opt/myapp
        state: directory
        mode: '0755'
        recurse: yes
    
    ' 심볼릭 링크 생성
    - name: 심볼릭 링크
      file:
        src: /opt/myapp/current
        dest: /opt/myapp/app
        state: link
    
    ' 파일 다운로드
    - name: URL에서 파일 다운로드
      get_url:
        url: https://example.com/file.tar.gz
        dest: /tmp/file.tar.gz
        checksum: sha256:xxxx
    
    ' 압축 해제
    - name: 압축 파일 해제
      unarchive:
        src: /tmp/file.tar.gz
        dest: /opt/myapp
        remote_src: yes

8.2 패키지 관리 모듈

' package-modules.yml
---
- name: 패키지 관리
  hosts: all
  become: yes
  tasks:
    ' APT (Ubuntu/Debian)
    - name: APT 패키지 설치
      apt:
        name:
          - nginx
          - postgresql
          - redis-server
        state: present
        update_cache: yes
      when: ansible_pkg_mgr == "apt"
    
    ' YUM (CentOS/RHEL)
    - name: YUM 패키지 설치
      yum:
        name: nginx
        state: latest
      when: ansible_pkg_mgr == "yum"
    
    ' PIP
    - name: Python 패키지 설치
      pip:
        name:
          - django
          - flask
          - requests
        state: present
        virtualenv: /opt/myapp/venv

8.3 사용자 및 그룹 관리

' user-management.yml
---
- name: 사용자 관리
  hosts: all
  become: yes
  tasks:
    - name: 그룹 생성
      group:
        name: developers
        gid: 1500
        state: present
    
    - name: 사용자 생성
      user:
        name: john
        uid: 1501
        groups: developers,sudo
        shell: /bin/bash
        create_home: yes
        password: "{{ 'mypassword' | password_hash('sha512') }}"
    
    - name: SSH 키 추가
      authorized_key:
        user: john
        key: "{{ lookup('file', '~/.ssh/id_rsa.pub') }}"
        state: present

8.4 데이터베이스 모듈

' database-modules.yml
---
- name: 데이터베이스 관리
  hosts: databases
  become: yes
  tasks:
    ' PostgreSQL
    - name: PostgreSQL 데이터베이스 생성
      postgresql_db:
        name: myapp_db
        encoding: UTF-8
        state: present
    
    - name: PostgreSQL 사용자 생성
      postgresql_user:
        name: myapp_user
        password: secure_password
        priv: "myapp_db:ALL"
        state: present
    
    ' MySQL
    - name: MySQL 데이터베이스 생성
      mysql_db:
        name: wordpress
        state: present
    
    - name: MySQL 사용자 생성
      mysql_user:
        name: wp_user
        password: wp_password
        priv: 'wordpress.*:ALL'
        host: localhost
        state: present

9. Vault (암호화)

9.1 Vault 사용

' Vault 파일 생성
ansible-vault create secrets.yml

' Vault 파일 편집
ansible-vault edit secrets.yml

' Vault 파일 암호화
ansible-vault encrypt vars.yml

' Vault 파일 복호화
ansible-vault decrypt vars.yml

' 플레이북 실행 시 Vault 비밀번호 입력
ansible-playbook playbook.yml --ask-vault-pass

' Vault 비밀번호 파일 사용
ansible-playbook playbook.yml --vault-password-file ~/.vault_pass

9.2 Vault 파일 예제

' secrets.yml (암호화된 파일)
---
db_password: super_secret_password
api_key: your_api_key_here
aws_access_key: AKIAXXXXXXXX
aws_secret_key: secret_key_here

9.3 Vault 사용 플레이북

' vault-playbook.yml
---
- name: Vault 사용 예제
  hosts: databases
  become: yes
  vars_files:
    - secrets.yml
  
  tasks:
    - name: 데이터베이스 사용자 생성
      postgresql_user:
        name: myapp
        password: "{{ db_password }}"
        state: present
    
    - name: API 설정 파일 생성
      template:
        src: config.j2
        dest: /etc/myapp/config.yml
      vars:
        api_key: "{{ api_key }}"

10. 태그 (Tags)

' tags-example.yml
---
- name: 태그 예제
  hosts: webservers
  become: yes
  tasks:
    - name: Nginx 설치
      apt:
        name: nginx
        state: present
      tags:
        - install
        - nginx
    
    - name: Nginx 설정
      template:
        src: nginx.conf.j2
        dest: /etc/nginx/nginx.conf
      tags:
        - config
        - nginx
    
    - name: Firewall 설정
      ufw:
        rule: allow
        port: '80'
      tags:
        - firewall
        - security


' 특정 태그만 실행
ansible-playbook playbook.yml --tags "install"

' 여러 태그 실행
ansible-playbook playbook.yml --tags "install,config"

' 특정 태그 제외
ansible-playbook playbook.yml --skip-tags "firewall"

11. 블록과 에러 처리

' error-handling.yml
---
- name: 에러 처리 예제
  hosts: webservers
  become: yes
  tasks:
    - name: 블록 사용
      block:
        - name: 위험한 작업
          command: /usr/bin/risky-command
        
        - name: 설정 파일 복사
          copy:
            src: config.txt
            dest: /etc/app/config.txt
      
      rescue:
        - name: 에러 발생 시 실행
          debug:
            msg: "에러가 발생했습니다. 롤백합니다."
        
        - name: 백업에서 복원
          copy:
            src: /backup/config.txt
            dest: /etc/app/config.txt
      
      always:
        - name: 항상 실행
          debug:
            msg: "작업 완료"
    
    - name: 에러 무시
      command: /bin/false
      ignore_errors: yes
    
    - name: 실패 조건 변경
      command: some-command
      register: result
      failed_when: "'ERROR' in result.stderr"

12. 딜리게이션과 로컬 실행

' delegation.yml
---
- name: 딜리게이션 예제
  hosts: webservers
  tasks:
    ' 로컬에서 실행
    - name: 로컬에서 스크립트 실행
      local_action:
        module: command
        args: /usr/local/bin/backup.sh
    
    ' 다른 호스트에서 실행
    - name: 로드밸런서에서 서버 제거
      command: remove-from-pool {{ inventory_hostname }}
      delegate_to: loadbalancer.example.com
    
    ' 한 번만 실행
    - name: 데이터베이스 마이그레이션
      command: /opt/app/migrate.sh
      run_once: true
    
    ' 첫 번째 호스트에서만 실행
    - name: 리더 선출
      debug:
        msg: "나는 리더입니다"
      when: inventory_hostname == groups['webservers'][0]

이 가이드는 Ansible의 주요 기능들을 망라하고 있습니다. 실제 사용 시에는 프로젝트의 요구사항에 맞게 이들을 조합하여 사용하면 됩니다.




LIST

Copyright © 2014 visionboy.me All Right Reserved.