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의 주요 기능들을 망라하고 있습니다. 실제 사용 시에는 프로젝트의 요구사항에 맞게 이들을 조합하여 사용하면 됩니다.