이번에는 변수에 대해 알아본다.
다른 개발 언어들 처럼 ansible도 변수를 사용할 수 있다. 각 항목에 대해서 서로 다른 값을 지정할 수도 있고, 이를 통해 플레이북을 더 간결하고 읽기 쉽게 만들 수도 있다.
TL;DR
수백 대의 서버에 패치를 적용해야 한다고 가정 해보자.
모든 서버에 적용할 수 있는 변수 몇 개만 있다면 단 하나의 플레이북으로도 수백 대의 패치를 적용할 수 있다.
이때 변수에는 각 서버의 IP 주소, 호스트 이름, 사용자 이름/비밀번호와 같은 상세 정보들을 담을 수 있다.
만약 각 서버별로 모두 Playbook을 만든다면, 내가 관리해야되는 200대의 서버들에 대해 플레이북만 200대가 나오는 것이다.
변수 정의
ansible 프로젝트에서 변수는 다양한 위치에서 정의할 수 있고, 3가지 범위 수준(level)로 나뉜다.
전역 범위(global) : 명령줄(-e), 구성 파일 ← 가장 넓음
플레이 범위(play) : vars, vars_files
호스트 범위(host) : 인벤토리, facts, group_vars, host_vars ← 가장 좁게도 가능
1번의 경우 아 전체 설정인가보다... 라고 받아들일 수 있는데, 아래 2개는 조금 더 상세히 설명을 하면
[호스트 범위]: inventort.txt
변수가 특정 호스트(서버)에 속한다. 라는 의미로
- blotter_1라는 호스트는 http_port가 8080! 라는 예시를 가질 수 있다.
- 위의 사례처럼 호스트마다 다른 값을 가질 수도 있다.
[플레이 범위]: vars/vars_files
변수가 플레이(작업 실행)에 속한다. 라는 의미로
- 이 플레이를 실행할 때는 http_port를 8080으로 쓴다!라는 예시를 가질 수 있다.
- 플레이가 실행되는 모든 호스트에 동일하게 적용된다.
대부분의 개발 내 환경 설정에서는 시스템 최상단에서 default 값을 정의하고, 각 세부 항목에서 재정의를 통해 관리한다.
이처럼 ansible에서도 변수를 관리하는데
- 범위가 좁은 변수가 범위가 넓은 변수보다 우선순위가 높다.
- 인벤토리에서 정의된 변수는 플레이북에서 정의된 변수에 의해, 플레이북에서 정의된 변수는 명령줄에서 정의된 변수에 의해 재정의된다.
role defaults ← 후순위 (기본값, 아무나 덮어씀)
group_vars/all
group_vars/특정그룹
host_vars/특정호스트
facts
play vars / vars_files
--extra-vars (-e) ← 1순위 (전부 덮어씀)
각각의 레벨별 변수 예시를 보자.
[1] 호스트 범위: Inventory Scope
인벤토리 파일에 변수를 정의하는 방식으로, 코드는 그대로 두고 설정값만 바꾼다.
예를 들어 여러 방화벽 구성을 설정하는 플레이북을 봐보자.
- 다른 삼이 포트를 변경할 수 있도록 재사용 가능하게 하려면 변수를 인벤토리 파일로 옮겨야 한다.
# 인벤토리 파일 (inventory.ini)
# 변수가 포함된 샘플 인벤토리
centos http_port=8080 snmp_port=161-162 internal_ip_range=192.168.100.0
# 플레이북 (firewall-playbook.yaml)
---
- name: Set Firewall Configurations
hosts: centos
become: true
tasks:
- firewalld:
service: https
permanent: true
state: enabled
- firewalld:
port: "{{ http_port }}/tcp"
permanent: true
state: disabled
- firewalld:
port: "{{ snmp_port }}/udp"
permanent: true
state: disabled
- firewalld:
source: "{{ internal_ip_range }}/24"
permanent: true
zone: internal
state: enabled
너무 어렵게 생각하지 말고, 변수가 정의된 파일을 playbook으로 주입해준다고 생각하면 될듯?
Playbook은 "방화벽을 설정한다"는 로직만 갖고, 실제 포트 숫자는 인벤토리가 갖는다. 다른 팀이 포트만 바꾸고 싶으면 인벤토리 한 줄만 고치면 된다.
[2] 플레이 범위: Play Scope
플레이북 자체에 변수를 포함시키는 방식이다. 여기에는 인라인(vars) 방식과 파일 분리(vars_file) 방식이 있다.
A. 인라인 변수 정의 (vars)
플레이북 내부에 직접 변수를 선언한다.
- name: Set Firewall Configurations
hosts: centos
become: true
vars: # 플레이북 내에서 변수 정의
http_port: 8080
snmp_port: 161-162
internal_ip_range: 192.168.100.0
tasks:
# ... (이하 동일 태스크)
B. 외부 변수 파일 가져오기 (vars_files)
변수만 따로 모은 파일을 참조한다.
변수 전용 파일 (vars.yaml)
http_port: 8080
snmp_port: 161-162
internal_ip_range: 192.168.100.0
플레이북
- name: Set Firewall Configurations
hosts: centos
become: true
vars_files: # 변수 파일 리스트 지정
- vars.yaml
tasks:
# ... (이하 동일 태스크)
- 차이점: vars는 작은 작업에 편리하고, vars_files는 관리해야 할 변수가 수십 개일 때 파일을 깔끔하게 유지하기 위해 사용합니다.
- 순서: 플레이북에 정의된 변수는 인벤토리에 정의된 변수보다 우선순위가 높습니다. 즉, 두 곳에 값이 다를 경우 플레이북의 값이 적용됩니다.
근데 inventory.txt로 관리를 하거나 vars_files를 사용하거나 둘다 외부 파일에서 가져오는 거 아닌가?
우리 회사 구조에서는 inventory/(dev.ini, prd.ini)와 vars/global_vars.yaml이 나뉘어 있었다.
둘 다 외부 파일을 읽어온다는 점에서 동일하지만, ‘정보의 성격’, ‘누구에게 귀속되느냐’에 따라 이 둘을 엄격히 구분한다.
- inventory.ini: 인프라 정보 (어떤 서버들이 있고, 각각 어떤 특성인지)
- vars_files: 작업 설정 (이 작업을 실행할 때 쓸 값들)
ansible_host, http_port 같은 서버의 정체성은 인벤토리로. 배포 경로, 앱 버전 같은 작업이 쓸 값은 vars_files로.
추가로 런타임에 —extras-vars 또는 -e 옵션을 사용해 변수를 플레이북에 전달할 수 있다.
ansible-playbook release.yaml --extra-vars "version=1.23.45 other_variable=foo"
그런데 우리 회사의 ansible 구조를 보면 아래와 같이 사용하고 있다.
playbooks
- group_vars: 각 그룹에 맞는 var 목록
- vars
- global_vars.yaml
# deploy_st_apps.yaml
- hosts: snet_apps
vars_files:
- vars/global_vars.yaml
roles:
- common
- deploy
그러면 어떻게 반영이 될까?
파일 이름이 "global"이라고 범위가 큰 게 아니다. 우선순위는 파일 이름이 아니라 "어떤 방법으로 로드됐냐"로 정해진다.
- group_vars/ 폴더에 넣기 → "host 범위" 방식으로 로드 → 약함
- vars_files:로 로드하기 → "play 범위" 방식으로 로드 → 셈
위에서는 범위 별로 우선순위가 나뉜다고 사용되었는데, 결국 범위가 적용되는 방식!에 따라 우선순위가 결정된다고 볼 수 있다.
global_vars.yaml은 이름만 global일 뿐, 실제로는 vars_files:로 로드되니까 play 범위로 취급돼서 group_vars를 이기는 거다.
조회
파일, API 키값 저장소 등 외부에서 데이터를 읽어 변수로 만들 수도 있다.
vars:
auth_key: "{{ lookup('file', '/home/devops/.ssh/id_rsa.pub') }}"
tasks:
- name: set authorized key
authorized_key:
user: devops
state: present
key: "{{ auth_key }}"
ansible-doc -t lookup -l을 통해 사용가능한 lookup 목록을 알 수 있다.
vars_prompt
민감하거나 매번 바뀌는 값을 Playbook에 저장하지 않고, 실행할 때 입력받는다.
- hosts: all
vars_prompt:
- name: username
prompt: Enter username
private: no # 입력 화면에 보임
default: admin
- name: hashed_password
prompt: Enter password
private: yes # 입력 안 보임 (비밀번호)
encrypt: sha512_crypt
facts
OS 정보, IP, 메모리 등 대상 노드의 정보를 수집할 수도 있다. (ansible_로 시작하는 변수로 접근)
이전 Playbook을 실행시켰을 때 출력문에 적힌 'TASK [Gathering Facts]'를 볼 수 있었다.
플레이북의 첫 작업으로 자동으로 수집하는 것이다.
{{ ansible_hostname }} # 호스트 이름
{{ ansible_memtotal_mb }} # 총 메모리
{{ ansible_all_ipv4_addresses }} # IPv4 주소들
{{ ansible_facts['distribution'] }} # OS 정보
{{ ansible_facts['distribution_major_version'] }} # "7" / "9"
수집할 필요가 없다면
- hosts: webservers
gather_facts: no'Infra > Ansible' 카테고리의 다른 글
| Ansible(5)- Role (0) | 2026.07.06 |
|---|---|
| Ansible(3) - Playbook (0) | 2026.07.05 |
| Ansible(2): Inventory (0) | 2026.07.05 |
| Ansible(1)- Ansible이란? (1) | 2026.07.05 |