해당 스터디는 90DaysOfDevOps
https://github.com/MichaelCade/90DaysOfDevOps
를 기반으로 진행한 내용입니다.
Day 27 - From Automated to Automatic - Event-Driven Infrastructure Management with Ansible
Ansible은 서버 구성, 애플리케이션 배포, 프로비저닝 등 IT 인프라 관리를 자동화하는 오픈 소스 도구 모음이다.
에이전트 설치 없이 SSH를 통해 작동하며, 사람이 이해하기 쉬운 YAML 형식의 '플레이북'을 사용해 작업을 정의하고 실행한다.

에이전트리스 (Agentless): Ansible은 관리할 노드에 별도의 에이전트를 설치할 필요 없이 SSH 프로토콜을 통해 작동한다. 중앙 Ansible 인스턴스 하나만 관리하면 되므로 전체 인프라의 관리 복잡성을 크게 줄여주는 장점이 있다.
Python 기반: Python으로 작성되어 필요시 사용자가 직접 모듈을 개발하여 기능을 쉽게 확장할 수 있다.
YAML 설정: 복잡한 프로그래밍 언어 대신, 사람이 읽고 쓰기 쉬운 YAML 형식의 파일을 사용하여 자동화 작업을 정의한다.
오픈소스: 완전히 오픈소스로, 누구나 자유롭게 사용하고 기여할 수 있다.
Ansible은 크게 4가지의 핵심적인 구성 요소를 통해 작동한다.

인벤토리 (Inventory) : 자동화 대상이 되는 서버 목록 정의
플레이북 (Playbook) : 수행할 작업들을 순서대로 정의한 YAML 파일
(여러 태스크를 묶어 하나의 플레이로 만들고, 여러 플레이를 모아 플레이북을 구성)
롤 (Roles) : 플레이북을 구조화하고 재사용 가능하게 만드는 방법
(특정 기능에 대한 태스크, 변수, 파일 등을 포함)
Ansible Galaxy : 커뮤니티에서 만들어진 역할과 콘텐츠를 공유하는 저장소
인벤토리는 Ansible이 관리할 호스트 (서버) 와 그룹의 목록을 담고 있는 파일 또는 동적 스크립트이다. 즉, 자동화 대상이 되는 서버 목록 정의한다.
어떤 Host와 Host Group을 관리할지 추적하는 역할을 하며, 각 시스템에는 Ansible이 기본으로 사용하는 /etc/ansible/hosts 경로가 존재한다.
YAML이나 INI 파일을 사용하여 정적 인벤토리를 정의할 수 있으며, 필요에 따라 다른 클라우드 제공자로부터 동적으로 생성할 수도 있다.
또한, 각 호스트나 그룹에 적용될 변수 (ex. 설치할 패키지 이름, 포트 번호 등) 를 정의할 수 있어, 유연한 관리가 가능하다.
# hosts.yaml
webservers:
hosts:
webshop.example.com:
ansible_host: 192.168.1.10
webserver: apache2 # webshop 호스트를 위한 변수
company.example.com:
ansible_host: 192.168.1.11
webserver: httpd # company 호스트를 위한 변수
위 예시 YAML 처럼 webservers라는 그룹을 만들고, 각 host에 webserver라는 변수를 다르게 할당하여 동일한 플레이북을 실행하더라도 각기 다른 웹 서버 패키지 를 설치하도록 할 수 있다.
(webshop -> apache2 설치, company -> httpd 설치)
플레이북은 자동화 작업을 지속 가능하고 반복 가능한 형태로 저장하는 YAML 파일이다.
일회성으로 실행하고 사라지는 애드혹 (Ad-hoc) 명령어와 달리, 플레이북은 복잡한 작업 절차를 체계적으로 정의하고, 언제든 다시 실행할 수 있게 해준다.
플레이북은 하나 이상의 플레이 (Play) 로 구성되며, 플레이는 태스크 (Task) 의 집합이다.
자동화의 최소 실행 단위로, "웹 서버 패키지를 설치하라" 와 같은 Ansible이 수행해야 할 하나의 구체적인 작업 정의한다.
- name: Install webserver # 태스크의 목적을 설명하는 이름
ansible.builtin.package: # 패키지를 관리하는 내장 모듈
name: "{{ webserver }}"
state: present # 패키지가 '설치된 상태'임을 보장
become: true # 관리자 권한으로 태스크를 실행
when: webserver is defined # 특정 조건이 충족될 때만 태스크를 실행
태스크의 묶음과 실행 범위 정의하며, 특정 호스트 그룹을 대상으로 실행되는 태스크들의 모음이다.
어떤 호스트에 어떤 작업을 할지를 연결하는 역할을 한다.
- name: Example role # 플레이의 목적을 설명하는 이름
hosts: webservers # 플레이를 적용할 인벤토리 내의 호스트 그룹을 지정
gather_facts: false
vars: # 해당 플레이에서 사용할 변수를 정의
greeting: "Hello World!"
pre_tasks: # 메인 작업 실행 전에 수행할 작업을 정의
- name: Say Hello
ansible.builtin.debug:
msg: "{{ greeting }}"
roles: # 롤 (Role) 실행
- role: example
post_tasks: # 메인 작업 실행 후에 수행할 작업을 정의
- name: Say goodbye
ansible.builtin.debug:
msg: "Goodbye"
'롤과 컬렉션'은 자동화 규모가 커지게 되면서 코드를 체계적으로 조직하고 재사용 하기 위해 사용되는 구성 요소이다.
롤 (Role) : 관련된 태스크, 변수, 파일, 템플릿, 플러그인 까지 재사용 가능한 단위로 구조화하는 방법
(ex. 'Docker 설치 및 설정' 이라는 롤을 만들어두면, 어떤 프로젝트에서든 이 롤을 가져와 Docker 환경을 쉽게 구성할 수 있음)
컬렉션 (Collection) : 하나 이상의 관련된 롤들을 함께 묶는 (bundle) 배포 단위
(ex. 커뮤니티에서 제공하는 Docker 컬렉션 안에는 도커 설치, 컨테이너 관리, 도커 스웜 관리 등 다양한 목적을 가진 여러 롤들이 포함되어 있을 수 있음)
Ansible Galaxy는 전 세계 사용자들이 만든 롤과 컬렉션을 위한 공개 저장소이다.
필요한 자동화 코드를 직접 처음부터 작성할 필요 없이, Galaxy에서 검증된 롤이나 컬렉션을 찾아 손쉽게 설치하고 사용할 수 있다.
ansible-galaxy collection install kubernetes.core
ansible-galaxy라는 CLI 도구를 사용하여 컬렉션을 설치할 수 있으며,
쿠버네티스 클러스터를 Ansible로 관리하고 싶다면, 해당 명령어를 통해 관련 컬렉션을 설치할 수 있다.
즉, 해당 명령어 하나로 쿠버네티스 관리에 필요한 다양한 Role과 모듈이 포함된 Collection을 사용할 수 있게 된다.
CI/CD 파이프라인을 통해 빌드, 테스트, 배포 자동화는 이미 현직에서 당연한 구조이다.
하지만 시스템이 운영에 들어간 후의 Day 2 Operations (유지보수, 장애 대응)는 여전히 수작업에 의존하는 경우가 많다.
이러한 문제점을 해결하기 위해 Event-Driven Ansible (EDA)가 등장하였다.
EDA는 외부에서 발생하는 이벤트 (Event)에 응답하여 자동으로 Ansible 플레이북을 실행하는 방식이다. 즉, 사람이 개입할 필요 없이 시스템이 스스로 문제를 감지하고 조치하게 만드는 방식이다.

이벤트 소스 (Event Source): Prometheus, Alertmanager, Kafka, 웹훅 등 다양한 소스로부터 이벤트를 수신
EDA 컨트롤러 (EDA Controller): 수신된 이벤트를 롤북(Rulebook)에 정의된 규칙과 비교하여 평가
롤북 (Rulebook): "만약 A라는 이벤트가 발생하면, B라는 플레이북을 실행하라" 와 같은 조건과 액션을 정의한 파일로, 하나 이상의 '룰셋 (Ruleset)'으로 구성함.
룰셋 (Ruleset): 어떤 Source에서 들어오는 이벤트를 어떤 Rule에 따라 평가하여 특정 Action을 실행할지 정의하는 하나의 묶음
- name: Greet the world # 룰셋의 이름
hosts: all # Action이 적용될 호스트 범위
sources: # 이벤트를 수신할 Source 정의
- ansible.eda.webhook:
host: 0.0.0.0
port: 5000 # 5000번 포트에서 웹훅 이벤트를 Waiting
rules: # 수신된 이벤트를 평가할 규칙 목록
- name: Hello World!
condition: 1 == 1 # 규칙의 조건 (항상 참)
action: # 조건이 참일 때 실행할 액션
debug:
msg: "Hello World!" # "Hello World!" 메시지를 출력
시나리오
모니터링 시스템 (Prometheus)이 MySQL 서비스 다운을 감지하면, 경고 시스템 (Alertmanager)이 경고를 발생시키고, EDA가 이 경고를 받아 자동으로 MySQL 서비스를 재시작해야되는 시나리오 제시
- name: Restart MySQL on alert
sources:
- name: alertmanager
ansible.eda.alertmanager:
host: 0.0.0.0
port: 5001
rules:
- name: Restart mysql server
condition: event.alert.labels.alertname == "mysql_not_running" and event.alert.status == "firing"
action:
run_playbook:
name: restart_mysql.yml
동작흐름:
MySQL 서비스가 중단
Prometheus가 이를 감지하고 Alertmanager가 'mysql_not_running' 경고를 'firing (발생 중)' 상태로 전달
Alertmanager는 이 경고를 EDA 컨트롤러의 웹훅 (Port 5001) 으로 전송
EDA 컨트롤러가 수신된 이벤트가 룰북의 조건과 일치함을 확인
restart_mysql.yml 플레이북이 자동으로 실행되어 MySQL 서비스를 재시작
서비스가 복구되고, Prometheus의 경고도 사라짐.
Ansible은 단순한 명령어 실행 자동화를 넘어, 플레이북을 통해 체계적인 인프라 관리를 가능하게 한다.
추가적으로, Event-Driven Ansible (EDA)은 장애 대응과 같은 Day 2 운영을 사람의 개입 없이 완전 자동화를 이뤄낼 수 있다.