1. Ansible 개요 및 개념 이해
Ansible은 에이전트가 필요 없는(OpenSSH 기반) 오픈 소스 구성 관리(Configuration Management), 애플리케이션 배포(Application Deployment), 태스크 자동화(Task Automation) 도구이다. 시스템 관리자와 DevOps 엔지니어가 반복적인 작업을 자동화하거나 대규모 인프라 환경을 선언적으로 관리할 수 있도록 설계되었다.
2. Ansible의 동작 원리
- Agentless 구조: Ansible은 원격 시스템에 별도 Agent를 설치하지 않고, SSH를 통해 명령을 전달하고 실행 결과를 수집한다.
- Push 기반: 중앙 제어 노드에서 원격 노드로 명령을 Push한다.
- Idempotency 보장: 동일한 플레이북을 여러 번 실행해도 시스템 상태가 불안정해지지 않음.
- YAML 기반의 Playbook: 사람이 읽기 쉬운 YAML 형식으로 자동화 워크플로우를 정의.
3. Ansible의 주요 구성 요소
- Inventory: 관리 대상 호스트 그룹 정보 (INI, YAML, 또는 동적 스크립트로 정의 가능)
- Module: Ansible이 실제로 실행하는 작업 단위 (e.g., yum, copy, user 등)
- Playbook: 여러 작업을 하나의 시나리오로 엮은 YAML 스크립트
- Task: Playbook 내 개별 작업 단위
- Role: Playbook을 모듈화 및 재사용 가능하게 만드는 구조화된 디렉터리 집합
- ansible.cfg: Ansible의 전역 설정 파일로서, 인벤토리 경로, 사용자, 로그, 콜백 플러그인 등 다양한 동작 방식을 설정 가능
4. Ansible 설치 및 사전 준비 (CentOS 7 기준)
# EPEL 저장소 설치 (CentOS 7)
sudo yum install -y epel-release
# Ansible 설치
sudo yum install -y ansible
# 설치 확인
ansible --version
(사전 준비 사항)
- SSH 키 생성 및 배포
ssh-keygen -t rsa ssh-copy-id user@remote-host
- 원격 서버 Python 설치 여부 확인 (대부분 기본 설치되어 있음)
- 방화벽 포트 열기 (예: SSH 22번 포트)
- SELinux 설정 검토 (비활성화 권장 아님, 필요 시 정책 조정)
- /etc/ansible/ansible.cfg 주요 설정 항목
[defaults] inventory = /etc/ansible/hosts remote_user = root host_key_checking = False retry_files_enabled = False roles_path = /etc/ansible/roles
5. 모의 환경 구성 예시
역할 | 호스트명 | IP 주소 | 설명 |
---|---|---|---|
Control Node | ansible-master | 192.168.56.10 | Ansible 설치 및 실행 |
Target Node 1 | web01.example.com | 192.168.56.101 | 웹 서버 역할 |
Target Node 2 | db01.example.com | 192.168.56.102 | DB 서버 역할 |
- 모든 노드는 같은 내부 네트워크에 있어야 하며, Control Node에서 SSH로 접근 가능해야 함
6. 기본 사용 예제
(1) Inventory 파일 작성 (/etc/ansible/hosts)
[webservers] web01.example.com # SSH 포트가 기본값(22)이 아닐 경우 192.168.100.101 ansible_port=22115 # 기본 root가 아니라 다른 사용자로 접속해야 할 경우 192.168.100.101 ansible_user=alpha # IP를 지정해야할 경우 web01 ansible_host=192.168.100.101
# 비밀번호 없이 키 파일로 로그인할 경우 192.168.100.101 ansible_ssh_private_key_file=/root/.ssh/id_rsa [dbservers]db01.example.com
(2) Ping 테스트
ansible all -m ping
(3) 모듈 사용 예제 (패키지 설치)
ansible webservers -m yum -a "name=httpd state=present"
(4) 다양한 Playbook 예제
# 0. 전역 변수 정의
- name: Example with global vars
hosts: all
become: true
vars:
my_message: "Hello from Ansible!"
tasks:
- name: Show variable message
debug:
msg: "{{ my_message }}"
---
# 1. 방화벽 포트 열기 (firewalld)
- name: Open HTTP port 80
hosts: webservers
become: true
tasks:
- name: Ensure firewalld is running
service:
name: firewalld
state: started
enabled: true
- name: Open port 80/tcp
firewalld:
port: 80/tcp
permanent: true
state: enabled
immediate: yes
---
# 2. SELinux 설정 변경
- name: Set SELinux to permissive
hosts: all
become: true
tasks:
- name: Change SELinux mode
selinux:
state: permissive
---
# 3. YUM 저장소 등록
- name: Add custom YUM repo
hosts: all
become: true
tasks:
- name: Create custom repo file
copy:
dest: /etc/yum.repos.d/custom.repo
content: |
[custom-repo]
name=Custom Repository
baseurl=http://192.168.0.1/repo/
enabled=1
gpgcheck=0
---
# 4. 패키지 설치 (YUM)
- name: Install packages via YUM
hosts: all
become: true
tasks:
- name: Install git and wget
yum:
name:
- git
- wget
state: present
---
# 5. 커널 파라미터 설정 (sysctl)
- name: Configure sysctl parameters
hosts: all
become: true
tasks:
- name: Set vm.swappiness to 10
sysctl:
name: vm.swappiness
value: '10'
state: present
reload: yes
---
# 6. 호스트 파일 등록 (/etc/hosts)
- name: Update /etc/hosts with app server
hosts: all
become: true
tasks:
- name: Add host entry
lineinfile:
path: /etc/hosts
line: "192.168.1.100 app-server"
state: present
---
# 7. SSH 공개키 배포
- name: Deploy SSH public key
hosts: all
become: true
vars:
ssh_user: devuser
ssh_pubkey: "{{ lookup('file', 'id_rsa.pub') }}"
tasks:
- name: Ensure .ssh directory exists
file:
path: "/home/{{ ssh_user }}/.ssh"
state: directory
owner: "{{ ssh_user }}"
group: "{{ ssh_user }}"
mode: '0700'
- name: Add authorized key
authorized_key:
user: "{{ ssh_user }}"
key: "{{ ssh_pubkey }}"
---
# 8. 호스트 시간 동기화 설정 (chrony)
- name: Install and configure chrony
hosts: all
become: true
tasks:
- name: Install chrony
yum:
name: chrony
state: present
- name: Enable and start chronyd
service:
name: chronyd
state: started
enabled: yes
- name: Force time sync
command: chronyc -a makestep
---
# 9. 디스크 마운트 자동화
- name: Mount /dev/sdb1 to /mnt/data
hosts: all
become: true
tasks:
- name: Ensure mount directory exists
file:
path: /mnt/data
state: directory
- name: Mount the disk
mount:
path: /mnt/data
src: /dev/sdb1
fstype: ext4
opts: defaults
state: mounted
---
# 10. 디렉토리 tar.gz로 압축
- name: Archive a directory with tar
hosts: all
become: true
tasks:
- name: Compress /var/log into /tmp/log_backup.tar.gz
archive:
path: /var/log
dest: /tmp/log_backup.tar.gz
format: gz
---
# 11. 반복 항목 처리 (loop)
- name: Create multiple users
hosts: all
become: true
tasks:
- name: Add users with loop
user:
name: "{{ item }}"
state: present
loop:
- alice
- bob
- charlie
---
# 12. 쉘 기능 포함 명령 실행
- name: Run shell command with pipe and redirection
hosts: all
become: true
tasks:
- name: List processes and save to file
shell: "ps aux | grep sshd > /tmp/sshd_processes.txt"
args:
executable: /bin/bash
(5) 실행 방법
ansible-playbook install_apache.yml
7. 고급 기능 및 실무 활용 기술
(1) Role 구조 사용 예시
ansible-galaxy init webserver
# site.yml
- hosts: webservers
roles:
- webserver
- 디렉토리 구조
webserver/ ├── tasks/ │ └── main.yml ├── handlers/ ├── templates/ ├── files/ └── defaults/
(2) 변수 및 템플릿 활용
vars:
port: 8080
- name: config 복사
template:
src: config.j2
dest: /etc/myapp/config.conf
# config.j2 템플릿 예시
server.port = {{ port }}
(3) 디버깅과 오류 대응
--check
옵션
“이 플레이북을 실행하면 어떤 일이 생길까?”를 실제로 변경하지 않고 미리 확인할 수 있는 옵션입니다.
-
실제 변경 없이, 변경될 작업이 무엇인지 미리 알려줍니다.
-
시스템에 영향을 주지 않기 때문에 검증 단계에서 매우 유용합니다.
-
단, 모든 모듈이 완벽하게 지원하는 것은 아닙니다.
# 설치하거나 설정을 바꾸지는 않지만, 무엇이 변경될지 출력합니다.
ansible-playbook client-setup.yml --check
--diff
옵션
설정 파일 등의 변경 시, 어떤 부분이 어떻게 바뀌는지 비교(diff) 를 보여줍니다.
-
lineinfile
,template
,copy
같은 텍스트 기반 작업에서 유용합니다. -
변경 전후의 내용을 Git diff 스타일로 보여줍니다.
# 파일이 바뀌는 경우, 어떤 줄이 추가되고 삭제되는지 시각적으로 보여줍니다.
ansible-playbook client-setup.yml --diff
-vvv
옵션
-
모듈 오류 발생 시
Traceback
경로와 원인을 파악하고 싶을 때 -
특정 호스트에서만 안 되는 문제를 분석할 때
-
파일이 복사 안되거나 조건문이 작동하지 않을 때
# 예를 들어 다음과 같은 메시지를 볼 수 있습니다
ansible-playbook client-setup.yml -i hosts -vvv
TASK [Install vim] ***
<192.168.100.5> ESTABLISH SSH CONNECTION FOR USER: root
<192.168.100.5> EXEC /bin/sh -c 'yum -y install vim'
fatal: [alpha-003]: FAILED! => {"changed": false, "msg": "Cannot find valid baseurl"}
(4) Vault로 민감 정보 관리
ansible-vault create secrets.yml
ansible-vault edit secrets.yml
ansible-playbook site.yml --ask-vault-pass
(5) Jenkins 또는 GitOps 통합
- Jenkins에서 shell 단계로
ansible-playbook
실행 스크립트 작성 - GitHub Actions에서
ansible
워크플로로 통합 가능
8. 구축 후 확인 사항
- SSH 키 기반 인증이 구성되어 있어야 함 (서버 무인 접속을 위해)
- 방화벽 또는 SELinux 설정으로 인해 통신이 차단되지 않아야 함
- Ansible 실행 노드는 Python 2.7+/3.5+ 설치 필요
9. 실무에서의 활용 사례
- 대규모 서버 패치 자동화
- 사용자 계정 및 접근 권한 자동화 관리
- 서비스 구성 배포 (Nginx, Tomcat, MySQL 등)
- AWS, Azure 등 클라우드 리소스 관리 (Ansible Cloud Modules)
- GitOps 및 CI/CD 파이프라인 연동
10. 요약
- Ansible은 SSH 기반의 Agentless 구성 관리 자동화 도구로, YAML을 사용한 사람이 읽기 쉬운 형식의 Playbook으로 시스템 구성을 선언적으로 정의한다.
- 설치가 간단하며, 수십~수천 대의 서버 환경을 일관된 방식으로 관리할 수 있도록 지원한다.
- 보안, 확장성, 유지보수 측면에서도 탁월하여 기업에서 널리 채택되고 있다.