
1. Ansible 핵심 구성요소 개념과 역할
1) 제어 노드 (Control Node)
정의: Ansible이 설치되어 있고, 실제로 플레이북을 실행하는 서버.
역할:
- 인벤토리 파일 관리
- 플레이북 실행
- 모듈 실행
- 원격 노드(Managed Node)에 명령 전달
특징:
- Ansible은 여기 설치됨
- SSH 등을 통해 관리 대상 장비에 접근
2) 관리 노드 (Managed Node)
정의: Ansible이 제어하는 대상 장비(서버, 네트워크 장비 등).
역할:
- 제어 노드에서 내려오는 명령 수행
- 별도의 Ansible 설치 필요 없음
특징:
- SSH 접근 가능해야 함 (리눅스 서버)
- 네트워크 장비라면 network_cli, httpapi, netconf 같은 연결 방식 사용
3) 인벤토리(Inventory)
- 자동화할 호스트(네트워크 장비, 서버 등)의 목록과 변수 정보를 담은 파일.
- INI, YAML 형식으로 작성 가능.
- 각 장비의 IP, 사용자 계정, 접속 방법, 장비 OS 타입 등을 정의.
INI(Initialization) 형식은 간단하고 직관적인 텍스트 기반 구성 파일 형식으로,
Ansible에서 자동화 대상 호스트(서버, 네트워크 장비 등)를 정의할 때 자주 사용됩니다.
4) 플레이북(Playbook)
- YAML 형식의 실행 시나리오.
- 어떤 호스트에, 어떤 모듈을, 어떤 순서와 조건으로 적용할지 기술.
- 태스크(Task) 집합으로 구성.
5) 모듈(Module)
- 특정 작업 단위를 수행하는 실행체.
- 예: ios_config(Cisco 설정), junos_config(Juniper 설정), copy, command.
- 멱등성을 보장해 이미 원하는 상태면 변경 없이 통과.
6) 플러그인(Plugin)
Ansible 기능을 확장하는 코드 조각.
종류:
- Connection Plugin: 네트워크 장비에 SSH, NETCONF, HTTP API 등으로 연결.
- Action Plugin: 모듈 호출 전후의 데이터 가공.
- Lookup Plugin: 외부 데이터 소스 조회.
- Filter Plugin: 변수 값 가공.
Ansible의 유연성을 높이는 확장 포인트.
2. Ansible에서 모듈과 플레이북의 역할 관계
1) 전체 실행 흐름
- 컨트롤러가 인벤토리에서 호스트를 선택
- Connection 플러그인이 세션을 열어 연결 확보 (SSH, NETCONF, HTTP API 등)
- 플레이북 내 각 태스크가 특정 모듈과 인자를 호출
- 모듈이 장비와 통신해 상태를 읽거나 변경
- 모듈이 JSON 결과(changed, failed, msg, diff 등)를 반환
- 플레이북 로직(조건, 루프, 핸들러, 예외 처리)에 따라 다음 태스크로 진행
2) 모듈(Module) = "무엇을 할지"
- 한 가지 작업 단위를 수행하는 실행체
- 네트워크 자동화 예시: ios_config, ios_facts, junos_config, eos_vlans
- 멱등성 보장: 이미 원하는 상태면 변경 없이 통과
- 입력: 인자(원하는 상태), 출력: 표준화된 JSON 결과
- 리소스 모듈, 정보 수집 모듈, 구성 모듈로 구분
3) 커넥션 플러그인(Connection) = "어떻게 연결할지"
장비에 접속하는 전송 방식 담당
대표 예시:
- network_cli: SSH CLI
- netconf: NETCONF (YANG 기반 XML/RPC)
- httpapi: RESTCONF, NX-API, eAPI
- local: 로컬 실행(API 클라이언트형)
연결 실패는 주로 모듈 문제가 아니라 커넥션 설정(계정, 타임아웃, 프롬프트 패턴 등) 문제
4. 플레이북(Playbook) = "언제·어떤 순서로·누구에게"
- YAML로 작성된 실행 시나리오
- 구성 요소: hosts, vars, tasks, handlers, roles, when, loop, tags, strategy
- 여러 모듈 호출을 오케스트레이션하고 조건·예외·롤백 제어
5. 네트워크 장비별 전형적 패턴
A) Cisco IOS (SSH-CLI)
인벤토리: ansible_connection=network_cli, ansible_network_os=cisco.ios.ios
태스크 흐름:
- ios_facts 수집
- ios_l3_interfaces로 SVI IP 설정
- 필요 시 ios_config로 보완
- ios_config save_when=changed로 저장
B) Juniper (NETCONF)
인벤토리: ansible_connection=netconf, ansible_network_os=junipernetworks.junos.junos
태스크 흐름:
- junos_facts 수집
- junos_config로 candidate에 머지
- commit으로 확정, diff 검증
C) Cisco IOS-XE (RESTCONF)
인벤토리: ansible_connection=httpapi, ansible_network_os=cisco.ios.ios
태스크 흐름:
- 표준 YANG 경로 조회
- 인터페이스/VRF/ACL 상태 선언
6. 현업 포인트
- 연결 문제는 모듈이 아니라 커넥션 변수·프롬프트 매칭·타임아웃 등 원인
- 멱등성 유지: 리소스 모듈 우선, 필요 시 CLI 스니펫 보완
- check_mode, diff 활용으로 사전 검증 습관화
- 네트워크 장비는 파이썬 미지원 → gather_facts 대신 네트워크 전용 facts 모듈 사용
- 변경 저장은 OS마다 다름(NVRAM write, commit 등)
한 줄 정리
- 모듈 = 무엇을 할지 (작업자)
- 커넥션 플러그인 = 어떻게 연결할지 (운송수단)
- 플레이북 = 언제·어떤 순서·누구에게 적용할지 (감독)
- 인벤토리 = 누구에게 적용할지 (대상 목록)
- 관리/제어 노드 = 전체 실행을 총괄하는 지휘소
- 플러그인 = 세부 기능을 확장하는 도우미
3. Ansible Automation Platform (AAP) 구성 요소와 역할
Red Hat이 제공하는 상용 배포판으로, 커뮤니티 Ansible을 확장·강화한 형태.
1) Automation Controller (옛 AWX / Ansible Tower)
- 웹 UI와 API 기반의 중앙 관리 시스템.
- 플레이북 실행을 스케줄링, 모니터링, RBAC(역할 기반 접근 제어) 제공.
- 다수 사용자가 협업하며 자동화 실행을 통제 가능.
2) Automation Hub
- 공인된 Ansible Collection(벤더 모듈, 롤, 플러그인)을 저장하고 배포하는 저장소.
- Red Hat 인증 콘텐츠 제공 → 보안 및 신뢰성 보장.
3) Execution Environments (EE)
- 컨테이너 기반 실행 환경.
- 필요한 파이썬 라이브러리, 모듈, 컬렉션을 패키징해 일관된 실행 보장.
- “내 PC에서는 되는데 서버에선 안 돼” 문제를 줄임.
4) Event-Driven Ansible (EDA)
- 이벤트 기반 자동화 실행.
- 예: 네트워크 장애 알람이 발생하면 자동으로 플레이북 실행.
5) Automation Mesh
- 여러 지역·노드에 분산된 자동화 실행을 가능하게 하는 메시 네트워크.
- 원격 사이트, 클라우드, 데이터센터 등 다양한 환경을 하나로 연결.
6) Analytics & Insights
- 자동화 작업 결과, 사용 통계, 보안 리스크 등을 분석.
- 운영 최적화와 거버넌스 강화.
커뮤니티 Ansible vs Ansible Automation Platform 비교
| 구분 | 커뮤니티 Ansible | Ansible Automation Platform |
| 배포 형태 | 오픈소스 CLI 툴 | 상용 + 지원, 엔터프라이즈 강화 |
| 실행 관리 | CLI 중심 | Web UI, API, RBAC, 중앙 통제 |
| 콘텐츠 | 커뮤니티 컬렉션 | Red Hat 인증 콘텐츠 (Automation Hub) |
| 실행 환경 | 로컬 파이썬, 모듈 설치 필요 | 컨테이너 기반 Execution Environment |
| 확장성 | 개별 관리 노드 중심 | Automation Mesh로 분산 실행 |
| 운영/보안 | 개별 사용자 관리 | RBAC, 감사 로그, Analytics/Insights |
한 줄 정리
- 커뮤니티 Ansible: CLI 중심의 오픈소스 자동화 툴.
- Ansible Automation Platform: 기업 환경을 위한 중앙 관리, 보안, 거버넌스 기능까지 포함한 상용 플랫폼.
인벤토리를 이용한 자동화 대상 호스트 설정
4. 역할에 따른 호스트 그룹 설정
예: 웹 서버, DB 서버, 네트워크 장비 등 그룹별로 묶어 관리
[web]
web1 ansible_host=192.168.1.10
web2 ansible_host=192.168.1.11
[db]
db1 ansible_host=192.168.1.20
그룹별 호스트 설정
- 그룹마다 공통 변수를 부여 가능
[web:vars]
ansible_user=ec2-user
ansible_ssh_private_key_file=~/.ssh/web.pem
중첩 그룹 정의
- 여러 그룹을 상위 그룹으로 묶을 수 있음
[app:children]
web
db
범위를 사용한 호스트 사양 간소화
- 연속된 호스트 이름을 단순화 가능
[web]
web[1:5].example.com # web1 ~ web5 자동 확장
인벤토리 확인
- 인벤토리 그룹 구성을 확인하는 명령
ansible-inventory -i inventory.ini --list
ansible-inventory -i inventory.ini --graph
- --list: 모든 호스트와 변수 출력
- --graph: 그룹 간 관계를 트리 형태로 표시
5. Ansible 환경 설정 파일(ansible.cfg) 정리
플레이북 작성 전에 Ansible이 동작하는 기본 환경을 정의하는 설정 파일.
보통 /etc/ansible/ansible.cfg, ~/.ansible.cfg, 또는 프로젝트 디렉토리 내 ansible.cfg에서 사용.
주요 섹션
1. [defaults]
- 인벤토리 경로, 기본 사용자, 출력 포맷 등 기본값을 정의.
[defaults]
inventory = ./inventory.ini # 인벤토리 파일 경로
remote_user = admin # 원격 접속 기본 계정
host_key_checking = False # SSH 호스트 키 검증 비활성화
forks = 10 # 병렬 실행할 호스트 수
timeout = 30 # SSH 연결 타임아웃
retry_files_enabled = False # 실패 시 *.retry 파일 생성 여부
2. [privilege_escalation]
- sudo 등 권한 상승 관련 설정.
[privilege_escalation]
become=True
become_method=sudo
become_user=root
become_ask_pass=False
3. [ssh_connection]
- SSH 접속 방식 및 성능 최적화 옵션.
[ssh_connection]
ssh_args = -o ControlMaster=auto -o ControlPersist=60s
control_path = %(directory)s/%%h-%%r
pipelining = True
4. [inventory] (선택)
- 인벤토리 플러그인 옵션 관리.
[inventory]
enable_plugins = host_list, ini, yaml
5. [colors] (선택)
- 출력 색상 커스터마이징.
[colors]
changed = yellow
ok = green
error = red
초보자 예시 ansible.cfg
[defaults]
inventory = ./inventory.ini
remote_user = cisco
host_key_checking = False
forks = 20
timeout = 60
retry_files_enabled = False
[privilege_escalation]
become=True
become_method=sudo
become_user=root
become_ask_pass=False
[ssh_connection]
pipelining=True
정리
- [defaults], [privilege_escalation], [ssh_connection] → 필수적으로 많이 사용.
- [inventory], [colors] → 필요 시 확장.
- cfg를 잘 설정해두면 플레이북 실행 시 옵션을 매번 주지 않아도 됨.
→ 인벤토리 → cfg 환경 설정 → 플레이북 실행 순으로 흐름이 이어진다.
6. Ansible 변수와 팩트 사용하기
- 네트워크 자동화에서 플레이북 로직은 최대한 단순하게, 환경 차이는 “변수”로 분리하는 것이 유지보수의 핵심이다.
- 이 문서는 예시 코드를 바꾸지 않고, 각 항목의 쓰임과 배경, 흔한 함정, 실무 팁을 더 자세히 설명한다.
왜 변수를 쓰나?
- 재사용성: 같은 플레이북을 테스트/운영, 지역/사이트, 장비 모델이 달라도 변수 파일만 바꿔서 돌릴 수 있다.
- 표준화: 공통 정책(NTP, Syslog, 보안 배너, 관리 VRF 등)을 한 곳(group_vars)에 모아 일관되게 배포한다.
- 멱등성 강화: “원하는 상태”를 변수로 선언하면 리소스 모듈이 차이를 계산해 필요한 변경만 적용한다.
- 변경 추적: 변수 파일은 텍스트(YAML)이므로 Git으로 버전 관리가 쉽다. 누가 무엇을 바꿨는지 이력 확인 가능.
- 온보딩 용이: 새 팀원이 플레이북 로직을 뜯어보지 않아도 변수 파일만 읽어도 환경 구성을 이해할 수 있다. • 주의: 값이 자주 바뀌는 운영 스위치포트 상태 같은 항목은 변수화 대상이 아니다. “정책·설계의 의도”를 변수로 담는 것이 좋다.
변수 종류와 특징
(1) 그룹 변수(group_vars)
- 적용 범위: 특정 그룹 전체. 역할(Access/Dist/Core), OS 타입(IOS/NXOS/JunOS), 환경(Dev/Prod)별 공통값 저장.
- 저장 위치: project/group_vars/.yml 또는 group_vars/all.yml(모든 호스트 공통).
- 쓰임: 공통 NTP/Syslog, 접속 방식(ansible_connection), 네트워크 정책 기본값 등.
(2) 호스트 변수(host_vars)
- 적용 범위: 특정 장비 하나. 장비의 고유 식별자·포트·IP·우선순위 등.
- 저장 위치: project/host_vars/.yml
- 쓰임: VRRP 우선순위, 업링크 인터페이스명, Loopback 주소 등.
(3) 플레이 변수(play vars)
- 적용 범위: 플레이 실행 동안. 실행 컨텍스트성 값(배너 문구, 저장 정책 토글 등)에 적합.
- 장점: 변수의 “가시성”이 좋아져 해당 플레이의 의도를 바로 파악 가능.
(4) 태스크 변수(task vars)
- 적용 범위: 특정 태스크·루프 내부. loop_var, register 변수, with_items 등과 함께 국소적으로 사용.
(5) 파일 변수(vars_files)
- 외부 YAML로 변수를 분리. 민감정보/환경 변수를 파일로 나눠서 관리할 때 유용.
(6)추가 변수(extra vars, -e)
- 실행 시점에 커맨드라인로 주입. 우선순위 최상위. 긴급 오버라이드, 단발성 배포에 사용.
- 남용하면 “숨은 의존성”이 생긴다. 반복되는 값은 파일에 정착.
- set_fact 실행 중 계산해 만드는 동적 변수. 탐색 결과를 다음 태스크에서 재사용할 때 편리. 범위는 “현재 호스트/현재 플레이”에 한정. 영구 저장이 아니다.
(6) 매직 변수(magic vars)
Ansible이 항상 제공하는 특수 변수. inventory_hostname, hostvars, groups, group_names 등.
크고 복잡한 구조이므로 debug 출력 시에는 필요한 필드만 보거나 필터(to_nice_json)로 보기 좋게 출력.
보안 팁: 패스워드/토큰/프리셰어드키는 ansible-vault로 암호화해 저장. 예: ansible-vault encrypt group_vars/ios.yml
타입 팁: 08 같은 값은 문자열로 취급되어야 한다. 따옴표로 감싸 타입 오류·8진수 해석을 방지.
프로젝트 디렉토리 구조 예시
project/
inventory.ini # 대상 장비/서버 목록
group_vars/ # 그룹 단위 변수 저장
all.yml # 모든 장비 공통값
ios.yml # IOS 장비 전용값
dist.yml # Distribution 스위치 전용값
host_vars/ # 호스트별 변수 저장
dist-1.yml
dist-2.yml
playbooks/
site.yml # 메인 플레이북
- group_vars/all.yml은 “전 사내 표준” 같은 초공통값. ios.yml, dist.yml은 역할·OS별 표준.
- host_vars/는 개별 장비의 차이를 담는다. 폴더 구조가 “무엇이 공통이고 무엇이 고유인지”를 드러내게 설계.
인벤토리 예시 (inventory.ini)
[dist]
dist-1 ansible_host=192.168.100.11
dist-2 ansible_host=192.168.100.12
[ios]
dist-1
dist-2
- ansible_host는 실제 접속 IP/도메인. inventory_hostname(키)은 dist-1, dist-2로 유지되어 가독성과 변수 파일 매핑이 쉬워진다.
- 호스트는 여러 그룹에 중복 소속될 수 있다. ios 그룹은 접속 방식 등 OS 공통값을 적용하는 데 유용하다.
- 대규모 환경에서는 상위/하위 그룹(children)을 활용해 “역할 × 환경” 매트릭스를 만든다.(예: [prod:children] dist)
그룹 변수 (group_vars)
그룹 단위 공통 설정을 정의한다. 동일 설정을 여러 파일에 반복 기입하는 실수를 줄인다.
모든 호스트 공통값 (all.yml)
ntp_servers:
- 192.168.99.10
- 192.168.99.11
syslog_server: 192.168.99.20
mgmt_vrf: MGMT
- ntp_servers는 리스트 형태로 관리해 사이트 추가가 쉽다. 템플릿/루프에서 상위 n개만 쓰는 등 응용 가능.
- mgmt_vrf는 이후 태스크에서 관리 VRF로 통일적으로 참조되어, 장비마다 명령이 달라지는 위험을 줄인다.
IOS 장비 공통값 (ios.yml)
ansible_connection: network_cli
ansible_network_os: cisco.ios.ios
ansible_user: admin
ansible_password: "C!sco123"
logging_buffer_size: 16384
- ansible_connection은 network_cli(SSH/CLI), netconf(XML/RPC), httpapi(RESTCONF/NX-API/eAPI) 중 선택.
- ansible_network_os는 컬렉션 네임스페이스를 포함(cisco.ios.ios)해야 Ansible이 올바른 플러그인/모듈을 로딩한다.
- logging_buffer_size 같은 정책성 값은 한 곳에서 바꾸면 전체에 반영된다.
Distribution 스위치 공통값 (dist.yml)
vlan_list:
- { id: 10, name: USERS }
- { id: 20, name: SERVERS }
- { id: 99, name: MGMT }
- 리소스 모듈(ios_vlans)은 이렇게 “상태”를 구조화된 데이터로 받는다. state: merged와 함께 쓰면 기존과의 차이만 반영한다.
- 선언형 데이터는 코드 리뷰가 쉽다. 숫자/이름만 보고 의도를 이해할 수 있다.
호스트 변수 (host_vars)
특정 장비에만 다른 값이 필요한 항목을 담는다. 파일명이 inventory_hostname과 1:1로 매칭되어 직관적이다.
dist-1.yml
loopback0: 10.255.0.1/32
uplink_intf: GigabitEthernet1/0/1
vrrp_priority:
vlan10: 110
vlan20: 90
dist-2.yml
loopback0: 10.255.0.2/32
uplink_intf: GigabitEthernet1/0/2
vrrp_priority:
vlan10: 90
vlan20: 110
- vrrp_priority처럼 “같은 키 구조를 유지하고 값만 다른” 패턴을 쓰면 템플릿/태스크를 재사용하기 좋다.
- 네이밍은 일관되게: vlan10처럼 공백/특수문자를 피하고 소문자+언더스코어를 권장.
플레이 변수 (play vars)
플레이 안에서만 의미가 있는 임시값을 둔다. 실행 컨텍스트가 눈에 잘 보인다.
site.yml
- name: Dist 스위치 공통 구성
hosts: dist
gather_facts: false
vars:
login_banner: |
Authorized access only. Violators will be prosecuted.
save_when: changed
tasks:
- name: NTP 서버 설정
ios_config:
lines: "ntp server {{ item }} vrf {{ mgmt_vrf }}"
loop: "{{ ntp_servers }}"
- name: 로깅 버퍼 크기 설정
ios_config:
lines: "logging buffered {{ logging_buffer_size }}"
- name: VLAN 생성
ios_vlans:
config: "{{ vlan_list }}"
state: merged
- login_banner처럼 텍스트 블록은 YAML 멀티라인(|)을 써야 줄바꿈이 보존된다.
- save_when은 저장 정책을 중앙에서 토글할 때 유용하다(예: 운영은 changed, 개발은 never).
- loop와 변수 조합으로 ntp_servers 리스트를 깔끔히 순회한다.
변수 우선순위 (간단 버전) 낮음 → 높음 (높은 쪽이 우선 적용)
- group_vars/all
- 다른 group_vars (ios, dist 등)
- host_vars/호스트
- 플레이 변수 (vars)
- vars_files 불러온 값
- extra-vars (-e) 설명
- 충돌 시 아래쪽이 위쪽 값을 덮어쓴다. 긴급 변경은 -e를 쓰되, 반복되면 파일에 영구 반영.
- 역할(roles)을 쓰는 큰 프로젝트에서는 role defaults/vars가 추가된다. 여기서는 초보자 흐름에 맞춰 단순화했다.
팩트(Facts) 개념
- 대상 호스트의 “실제 상태”를 Ansible이 수집해 ansible_facts 딕셔너리에 담는다. 조건 분기, 검증, 보고에 활용한다.
- 서버는 기본 gather_facts: true로 setup 모듈이 광범위한 정보를 수집한다. 네트워크 장비는 전용 facts 모듈을 사용한다.
예시: Cisco IOS facts 수집
- name: IOS facts 수집
hosts: ios
gather_facts: false
tasks:
- ios_facts:
gather_subset: min
- debug:
msg: "{{ ansible_facts.ansible_net_model }} {{ ansible_facts.ansible_net_version }}"
- gather_subset: min은 최소한의 키만 수집해 실행을 빠르게 한다.
- ansible_facts는 중첩 구조다. 필요한 키만 골라 쓰고, 전체를 볼 때는 debug: var=ansible_facts로 점검한다.
자주 쓰는 IOS facts 키
- ansible_facts.ansible_net_hostname (호스트 이름)
- ansible_facts.ansible_net_model (장비 모델)
- ansible_facts.ansible_net_version (OS 버전)
- ansible_facts.ansible_net_serialnum (시리얼 번호)
- ansible_facts.ansible_net_interfaces (인터페이스 목록)
조건/분기에서 facts 활용
- name: 17.x 이상에서만 기능 A 적용
when: ansible_facts.ansible_net_version is search('^17\.')
ios_config:
lines: feature a-foo
- 정규식으로 메이저 버전을 판별하는 간단한 패턴이다. 복잡한 비교는 버전 비교용 테스트(version, version_compare)를 고려한다.
set_fact 활용
- name: VRRP 우선순위 선택
set_fact:
vrrp10_prio: "{{ vrrp_priority.vlan10 | default(100) }}"
- name: 우선순위 적용
ios_config:
lines:
- interface Vlan10
- vrrp 10 priority {{ vrrp10_prio }}
- default 필터로 값이 없을 때의 안전한 기본값(100)을 준다. 런타임 계산 결과를 다음 태스크에서 재사용한다.
- set_fact는 “현재 플레이/호스트 범위”에만 유효하며 다른 호스트나 다음 플레이로 자동 전파되지 않는다.
매직 변수 (핵심)
- inventory_hostname: 인벤토리에 정의된 현재 호스트 키. host_vars/<이름>.yml과 1:1 매칭된다.
- hostvars: 모든 호스트의 변수 사전. 교차 참조가 필요할 때 쓴다(예: hostvars['dist-1'].loopback0).
- group_names: 현재 호스트가 소속된 그룹 리스트. 조건에 따라 그룹별 분기 처리 가능.
- groups: 그룹명 → 호스트 리스트 매핑. 특정 그룹의 모든 호스트를 순회할 때 유용.
템플릿 예시 templates/ntp.j2
ntp server {{ ntp_servers[0] }} vrf {{ mgmt_vrf }}
ntp server {{ ntp_servers[1] }} vrf {{ mgmt_vrf }}
태스크에서 템플릿 적용
- name: NTP 템플릿 배포
ios_config:
src: templates/ntp.j2
- ios_config의 src는 컨트롤러에 있는 템플릿 파일을 읽어 Jinja2로 렌더링한 결과를 장비로 보낸다.
- 템플릿 파일 경로는 프로젝트 루트 기준 상대 경로로 관리하면 이식성이 좋다.
디버깅 팁
- name: 현재 호스트 변수 전체 보기
debug:
var: hostvars[inventory_hostname]
- name: 실제 적용될 값 확인
debug:
msg: "syslog={{ syslog_server }} buffer={{ logging_buffer_size }}"
- var:는 딕셔너리를 그대로 출력한다. 큰 출력은 로그 가독성을 해칠 수 있으니 필요한 순간에만 쓰자.
- msg:는 사람이 읽기 쉬운 요약을 만들 때 유용하다. to_nice_json, to_yaml 필터로 가독성을 높일 수 있다.
7. Ansible 네트워크 자동화 핵심 정리
1) Ansible 변수 종류와 사용법
변수는 “같은 의도를 여러 장비에 일관되게 적용”하기 위한 핵심 도구다. 수백 대 장비를 운영할수록 변수 설계가 곧 유지보수성이다. 네트워크 자동화에서는 사이트별 표준값(AAA, NTP, SYSLOG, SNMP), 장비별 개별값(관리 IP, 호스트명, 인터페이스 매핑), 역할별 정책값(ACL 세트, 라우팅 정책)을 분리해 담는다.
핵심 분류와 용도
- 인벤토리 변수: host_vars(장비 단위), group_vars(그룹 단위)에 저장한다. 그룹은 벤더별, 모델별, 지역/사이트별, 역할별(ACCESS/DIST/CORE)로 나누는 것이 일반적이다. 한 변수명이 여러 곳에 존재하면 더 구체적 범위(호스트)가 우선된다.
- 플레이 변수: 특정 Play에서만 일시적으로 쓰는 값. vars, vars_files, vars_prompt가 있다. 재사용을 고려하면 역할/인벤토리 쪽으로 이동하는 것이 좋다.
- 롤 변수: defaults는 우선순위가 가장 낮아 “안전한 기본값”을 넣는 곳, vars는 높은 우선순위로 “역할 내부 강제값”이 필요할 때 사용한다. 외부에서 덮어써야 한다면 defaults에 두는 편이 좋다.
- 명령행 변수(--extra-vars): 가장 강력한 오버라이드 수단이다. 배포 파이프라인에서 배포 창구, 변경 티켓 번호, 긴급 플래그 등을 주입할 때 활용한다.
- 동적 변수: set_fact(런타임 계산값), register(Task 결과 캡처). 예를 들어 ios_facts 결과를 register해서 조건 분기를 할 수 있다.
- 팩트/매직 변수: ansible_facts, inventory_hostname, groups, hostvars 등. 매직 변수는 인벤토리 구조를 탐색하거나 교차 참조할 때 유용하다.
우선순위 실무 감각
- 같은 이름의 변수가 여러 위치에 있으면 보통 extra-vars > role vars > play vars > host_vars > group_vars > role defaults 순으로 생각하면 된다. 혼동을 줄이려면 “동일 변수는 한 곳에만 둔다”는 규칙과 네이밍 컨벤션(예: site_, global_, device_)을 정해두자.
템플릿과 변수
- 네트워크 자동화는 Jinja2 템플릿과 변수가 결합해 힘을 발휘한다. 예를 들어 ntp_servers 리스트를 루프 돌려 ios_config lines로 변환한다. 공백·인덴트·개행에 따라 네트워크 장비 CLI가 민감하므로 템플릿에서 여분의 스페이스, 탭, 줄바꿈을 엄격히 관리하자.
예시 (인벤토리):
[ios]
dist-1 ansible_host=192.168.100.3
dist-2 ansible_host=192.168.100.4
[ios:vars]
ansible_connection=ansible.netcommon.network_cli
ansible_network_os=cisco.ios.ios
ansible_user=netops
ansible_password={{ vault_ios_ssh_pw }}
ansible_become=true
ansible_become_method=enable
ansible_become_password={{ vault_ios_enable_pw }}
- 그룹 설계는 “벤더/OS 버전/사이트/역할” 축으로 겹칠 수 있다. 중복을 줄이려 그룹별 설정을 최소화하고, 공통값은 group_vars/all, 사이트 특화는 group_vars/site_x처럼 계층화하자.
- 비밀 값은 반드시 Vault 변수 참조로만 소비하고, 평문 변수와 섞지 않는다.
2) Ansible Vault
Vault는 비밀정보(SSH 비밀번호, enable 비밀번호, API 토큰 등)를 암호화해 Git에 안전하게 보관하게 해준다. 팀 협업에서 필수이며, 보안 감사를 통과하기 위한 기본 요건이기도 하다.
핵심 개념
- 암호화 단위: 파일 전체, 문자열 한 줄, YAML의 값 단위까지 가능하지만, 운영 관점에서는 파일 단위로 다루는 것이 일관적이다.
- 접근 방식: --vault-id를 쓰면 실행 시 암호를 묻거나, 사내 비밀관리 도구와 스크립트로 연동해 자동 주입도 가능하다.
- 키 롤오버: 재발급(rekey) 기능으로 팀 변경 시 키 교체가 쉽다.
명령 예 ansible-vault create group_vars/all/vault.yml ansible-playbook play.yml --vault-id @prompt
운영 사례
- vault 파일 분리: 글로벌 비밀값(all), 사이트별 비밀값(site_x), 벤더별 비밀값(ios)처럼 역할에 맞게 쪼갠다.
- 변수 접두어: vault_ 접두어를 붙여 가독성·검색성을 높인다.
- 금기 사항: Vault 암호 파일 자체를 저장소에 커밋하지 않는다. CI/CD에서는 조직 표준 비밀 저장소와 vault-id 스크립트로 연동한다.
3) 자동 예약 변수와 팩트 (ansible_facts)
네트워크 플레이는 보통 gather_facts: no로 시작하고, 플랫폼 전용 facts 모듈(예: cisco.ios.ios_facts)로 필요한 정보만 가져온다. 수집된 값은 ansible_facts 사전에 구조화되어 들어오고, 모델/버전/시리얼/인터페이스 상태 등 운영 의사결정에 사용된다.
활용 시나리오
- 조건부 배포: 특정 OS 버전 이상에서만 새로운 리소스 모듈을 적용하거나, 모델별 인터페이스 네이밍 차이를 흡수한다.
- 변경 영향 최소화: 베타 펌웨어가 탐지되면 해당 장비는 제외한다.
- 리포팅/감사: facts를 파일로 떨어뜨려 CMDB/재고관리와 동기화한다.
성능·정확도 팁
- 서브셋 옵션으로 필요한 항목만 수집하면 속도가 빨라진다.
- facts 캐시를 켜면 대규모 환경에서 중복 수집을 줄일 수 있다.
Cisco IOS 예시:
- name: IOS facts 수집
cisco.ios.ios_facts:
register: f
- debug:
msg: "{{ f.ansible_facts.ansible_net_model }} / {{ f.ansible_facts.ansible_net_version }}"
4) 핸들러 (Handler)
핸들러는 특정 Task가 실제 변경(changed)을 일으켰을 때만 실행되는 후속 조치다. 네트워크에서는 재시작, 세션 플러시 같은 위험 동작을 핸들러에 묶어 “변경이 확인된 경우에만” 수행하도록 만드는 안전장치다.
동작 원리
- notify에 의해 큐에 쌓이고, Play의 일반 Task가 끝난 뒤 한 번만 실행된다(동일 이름의 핸들러는 dedup된다).
- 즉시 실행이 필요하면 meta: flush_handlers를 사용한다.
- 여러 Task가 한 핸들러를 호출할 수 있고, listen 키워드로 핸들러 그룹을 만들 수도 있다.
안전 운영 팁
- “저장(write memory)”는 save_when: modified로 처리하면 불필요한 저장을 줄일 수 있다.
- clear 명령(예: BGP/OSPF 리셋)은 서비스 영향이 크므로 핸들러로 조건부 실행하고, 배포 창구·변경관리와 연계해 통제하자.
예시:
- name: OSPF 네트워크 선언
cisco.ios.ios_config:
lines:
- router ospf 10
- network 10.10.0.0 0.0.255.255 area 0
notify: OSPF 재시작
handlers:
- name: OSPF 재시작
cisco.ios.ios_command:
commands:
- clear ip ospf process
5) 롤(Role) 구조와 사용법
Roles는 “정책·구성·템플릿·핸들러”를 패키징해 재사용성과 테스트 용이성을 높이는 단위다. 팀 표준 설정을 역할화하면 프로젝트 간 복제가 쉬워지고, 버전 관리와 코드 리뷰가 가능해진다.
디렉터리 의미
- defaults: 외부에서 덮어쓸 수 있는 안전한 기본값. 사이트/장비 특화값은 여기를 override한다.
- vars: 역할 내부에서 강제해야 하는 값. 외부 override를 기대하지 않을 때 사용한다.
- tasks: ios_config·리소스 모듈 호출 등의 본문. 파일을 나눠 include/import로 구성하면 가독성이 좋아진다.
- handlers: 변경 시에만 돌려야 하는 후속 조치.
- templates: Jinja2 템플릿. 줄바꿈·들여쓰기로 CLI가 민감하니 유효성 검사를 습관화하자.
- meta: 역할 의존성 명시(예: ios_base 전에 netcommon 설치 확인).
리소스 모듈 vs CLI 모듈
- 리소스 모듈(예: ios_acls, ios_interfaces)은 선언적·idempotent하게 상태를 맞춘다.
- CLI 기반 ios_config는 유연하지만 텍스트 일치에 의존하므로 템플릿·정규식 관리가 중요하다.
표준 구조:
roles/
ios_base/
defaults/main.yml
tasks/main.yml
handlers/main.yml
templates/banner.j2
예시:
- name: NTP 서버 설정
cisco.ios.ios_config:
lines: "ntp server {{ item }}"
loop: "{{ ntp_servers }}"
notify: 저장
handlers/main.yml:
- name: 저장
cisco.ios.ios_config:
save_when: modified
운영 팁
- 역할 단위로 분리 테스트를 수행하고, check mode 지원 여부를 문서화하자.
- 역할 버전을 태깅하고, requirements 파일이나 컬렉션으로 배포하면 재현성이 올라간다.
6) Ansible Galaxy
Galaxy는 커뮤니티·벤더가 배포한 Roles/Collections를 검색·설치하는 허브다. 바퀴를 다시 만들지 말고, 공신력 있는 컬렉션을 가져와 표준화된 모듈을 쓰는 것이 시간·리스크를 줄인다.
활용
- 공식 네임스페이스와 최근 업데이트, 문서 품질, 이슈 응답성을 확인한다.
- requirements.yml로 버전 고정하고, 사내 미러/프록시를 통해 오프라인 환경에서도 일관성 있게 설치한다.
- AWX/Automation Controller를 쓰면 프로젝트 동기화 시 컬렉션 자동 설치를 걸어둘 수 있다.
설치: ansible-galaxy collection install cisco.ios
7) 콘텐츠 컬렉션(Collections)
Collection은 모듈, 플러그인, 롤, 필터, 콜백 등을 네임스페이스로 묶은 배포 단위다.
호출은 FQCN으로 한다(예: cisco.ios.ios_config).
네트워크에서는 ansible.netcommon(연결 플러그인: network_cli, httpapi, netconf)이 토대가 되고,
벤더 컬렉션을 그 위에 올린다.
주요 네트워크 컬렉션
- ansible.netcommon: 공통 연결·유틸리티. network_cli, httpapi, netconf 제공.
- cisco.ios, cisco.nxos, cisco.iosxr: Cisco IOS/NX-OS/IOS-XR용 모듈.
- arista.eos, junipernetworks.junos, frr.frr, paloaltonetworks.panos 등 환경에 맞게 채택.
버전·호환성 팁
- 컬렉션 버전과 네트워크 OS 버전을 매핑해 호환성을 문서화한다.
- FQCN을 사용하면 네임 충돌을 피하고, 린터/IDE에서 자동완성이 잘 동작한다.
예시 플레이북:
- name: IOS VLAN 생성
cisco.ios.ios_config:
lines:
- vlan 30
- name USERS_30
notify: 저장
handlers:
- name: 저장
cisco.ios.ios_config:
save_when: modified
9. Ansible 실습
Ansible을 활용해서 실제 네트워크 장비들(S1~S5)을 자동화 관리하는 실습.
Ansible의 인벤토리와 플레이북을 구성해 네트워크 장비들에 일괄적으로 접근하고 결과를 저장하는 과정이다.
0) 토폴로지 구성

실습 토폴로지는 Linux 서버(NetworkAutomation-1)에서 Ansible을 실행하고, 이 서버가 스위치들을 관리하는 구조다.
- Ansible 서버 → Core 스위치(S1, S2)
- Core 스위치 → Access 스위치(S3, S4, S5)
즉, 중앙 관리 서버 → Core → Access 계층형 구조를 가상 환경에 구현했다.
1) 인벤토리 설정 (hosts)

/etc/ansible/hosts 파일에 관리할 장비들을 그룹으로 나누어 정리했다.
- Core 스위치 그룹: S1, S2
- Access 스위치 그룹: S3, S4, S5
- 공통 변수: IOS 장비이므로 network_cli, ansible_network_os=ios, ansible_user, ansible_password를 정의
이렇게 설정해두면, 플레이북에서 hosts: all만 지정해도 전체 장비에 접속할 수 있다.
2) Ansible 환경 설정 (ansible.cfg)
/etc/ansible/ansible.cfg 에 기본 환경을 지정했다.
- 인벤토리 위치 지정
- SSH Key Checking 비활성화 (비밀번호 기반 로그인 위해)
- Timeout 값 설정
.cfg 파일에매번 옵션을 붙이지 않아도 된다.
3) 플레이북 작성 (getversion.yml)

플레이북에서는 세 가지 주요 작업을 구성했다.
- ios_command 모듈을 사용해 show version 실행
- 결과를 debug로 출력하여 확인
- 결과를 /etc/ansible/outputs 디렉토리에 장비별 텍스트 파일로 저장
이 과정을 통해 CLI에서 개별 장비에 들어가지 않고도, 여러 장비의 OS 버전 정보를 한 번에 수집할 수 있다.
4) 실습 결과



- 단순 반복 명령을 Ansible로 자동화하면 시간과 노력이 크게 절약된다.
- 결과를 텍스트 파일로 저장하면, 장비별 버전/상태를 기록으로 남길 수 있어 트러블슈팅이나 자산 관리에 유용하다.