IAC (Infrastructure As Code)
- Terraform 등이 대표적인 도구
구성 요소
제어 노드 (Rocky Linux1)
- 대량의 노드들을 코드로 제어 → 취약점 탐지 등에 유리
Ansible설치는 제어 노드에서만 이루어짐- 자기 자신도 관리 대상에 포함될 수 있으므로 python 설치 필요
관리 노드 (Rocky Linux2)
- python 설치 필요
제어 노드 기능
- 관리 노드 목록 →
Inventory - 코드 파일 →
Playbook (.yaml / .yml) - 설정 파일 →
ansible.cfg
환경 세팅
- 사용자 비밀번호 로그인 가능 설정
sudo vim /etc/ssh/sshd_config
- 터미널에서 rocky1(제어 노드) 연동

- 호스트네임 설정
-- 제어 노드
sudo hostnamectl set-hostname control
-- 관리 노드
sudo hostnamectl set-hostname managed
- 제어 노드 / 관리 노드 설정 완료 확인


- Ansible 설치
sudo dnf install -y epel-release sudo dnf install -y ansible
- sudo 비밀번호 없이 사용하도록 설정
sudo vim /etc/sudoers.d/user
user ALL=(ALL) NOPASSWD:ALL
7. 동일한 파일이 있을 때 Directory > File
```bash
[user@managed ~]$ sudo vim /etc/sudoers.d/user [user@managed ~]$ sudo getenforce Permissive [user@managed ~]$ sudo setenforce 1 [user@managed ~]$ ls /etc/sudoers /etc/sudoers
- 우선순위: 사용자 작업 디렉토리 > 사용자 홈 디렉토리 >
/etc디렉토리 >/etc설정 파일
Shell Script vs Ansible
Shell Script
- 리눅스 명령어의 집합 파일
- 기존 작업을 무시하고 모든 코드를 다 실행
Ansible
- 모듈의 형태로 테스크를 구성하여 playbook 파일 작성
- 변경 사항을 감지하고 변경 사항이 있다면 실행(멱등성)
Inventory
관리 노드 목록을 모아둔 파일. 추후 ansible.cfg에서 파일명을 지정해 사용.
단일 주소
- 관리 노드들을 모아 놓은 파일 형식
- 추후 ansible.cfg 파일 내
파일명을 명시
vim inventory_ex_01
# ip 주소, 도메인 주소
# /etc/hosts는 관여하지 않음
192.168.51.129
192.168.51.131
web01.example.com
[web02.example.com](http://web02.example.com)
그룹 단위 주소
#그룹 이름은 [] 대괄호로 묶음
[webservers]
web01.example.com
web02.example.com
192.168.63.134
192.168.63.128
[dbservers]
db01.example.com
db02.example.com
중첩 그룹 단위 주소
#중첩 그룹
#그룹을 한 번 더 묶기
#[중첩 그룹 이름 : children]
[webdevelopers]
192.168.51.1
192.168.51.2
[operators]
192.168.51.3
192.168.51.4
[security]
192.168.51.5
192.168.51.6
[company:children]
webdevelopers
operators
security
인벤토리 조회
[user@control 01_ansible_inventory]$ ansible 192.168.51.1 --list-hosts
[WARNING]: provided hosts list is empty, only localhost is available. Note that the implicit localhost does not match 'all' [WARNING]: Could not match supplied host pattern, ignoring: 192.168.51.1
[user@control 01_ansible_inventory]$ ansible 192.168.51.1 -i inventory_ex_04 --list-hosts hosts (1): 192.168.51.1
→ -i로 인벤토리 파일을 명시하지 않으면 대상 호스트를 찾지 못함.
ansible.cfg
설정 파일 탐색 우선순위:
- 작업 디렉토리의
ansible.cfg - 사용자 홈 디렉토리의
ansible.cfg /etc디렉토리의ansible.cfg
기본 설정 확인
[user@control 02_ansible_cfg]$ ansible --version
config file = /etc/ansible/ansible.cfg
configured module search path = ['/home/user/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
주요 옵션
[defaults]
inventory = /etc/ansible/hosts
remote_user = root
ask_pass = True
[privilege_escalation]
#become=True # 사용자 전환 허용
#become_method=sudo
#become_user=root
#become_ask_pass=False # sudo 사용 시 비밀번호 요청 여부
관리 노드 SSH 키를 제어 노드에 등록하기
제어 노드에서 키 생성
ssh-keygen -- 공개키 생성
공개키 생성 후 위치 확인
/home/user/.ssh/id_ed25519.pub
vim playbook.yaml
playbook 작성
---
- name: Public key is deployed to managed hosts for ansible
hosts: 192.168.51.131
tasks:
- name: Ensure key is in user's authorized_keys
authorized_keys:
user: user
state: present
key: '{{ item }}'
with_file:
- ~/.ssh/id_ed25519.pub
실행
--원격 접속
ansible-playbook playbook.yaml
ansible --help
Ad-hoc 명령
구조 : ansible host-pattern -m MODULE_NAME -a MODULE_ARGS -i INVENTORY
주요 옵션
| 옵션 | 설명 |
|---|---|
-i |
인벤토리 파일 지정 |
-u |
remote_user 지정 |
--ask-pass, -k |
비밀번호 인증 |
--become, -b |
권한 상승(sudo) 사용 |
--become-method |
권한 상승 방식 |
--become-user |
상승할 사용자 |
--ask-become-pass, -K |
권한 상승 시 비밀번호 요청 |
디렉토리 준비
mkdir 03_ansible_adhoc
cp ../02_ansible_cfg/inventory .
co ../02_ansible_cfg/ansible.cfg .
ansible.cfg 편집
inventory = inventory
ask_pass = False
ssh 타 통신 서버 icmp 확인
ansible [host-name] -m ping
SUCCESS => { "ansible_facts": { "discovered_interpreter_python": "/usr/bin/python3"}, "changed": false, "ping": "pong"
사용자 생성 (user 모듈)
ansible 192.168.51.131 -m user -a 'name=ansible_user uid=1111 192.168.63.134 | CHANGED => {
"ansible_facts": { "discovered_interpreter_python": "/usr/bin/python3" },
"changed": true,
"comment": "",
"create_home": true,
"group": 1111,
"home": "/home/ansible_user",
"name": "ansible_user",
"shell": "/bin/bash",
"state": "present",
"system": false,
"uid": 1111
}
동일 명령을 다른 uid로 재실행 시 멱등성 확인
ansible 192.168.51.131 -m user -a 'name=ansible_user uid=1122 state=present'
관리 노드 쪽 스크립트 준비
#!/bin/bash
echo "hello i am managed OS"
ls -l hello.sh
# -rw-r--r--. 1 user user 42 Aug 11 15:24 hello.sh
chmod a+x hello.sh
cp hello.sh /usr/bin/hello # Permission denied
sudo cp hello.sh /usr/bin/hello
hello
# hello i am managed OS
제어 노드에서 명령 실행 (command 모듈)
ansible 192.168.63.134 -m command -a /usr/bin/hello
# 192.168.63.134 | CHANGED | rc=0 >>
# h
Master -> Worker Adhoc 명령어로 권한 상승
Worker
ansible [대상 ip] -m authorized_key -a "user=ansible_user state=present key=\"{{ lookup('file', '/home/ansible_user/.ssh/id_ed25519.pub') }}\"" -i inventory -u ansible_user --ask-pass
Master
ansible 192.168.63.134 -m authorized_key -a 'user=ansible_user state=present key="ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIAljZEp0hrg+m6TWyMfkozB1I4dJuz4NjFhVL1L8ke6j ansible_user@master"' -i inventory -u ansible_user --ask-pass
command vs shell
- command : 단순 명령어 실행
- shell : 쉘 내장 변수, 함수 등을 사용하여 명령어 실행
아래 내용처럼 command를 명령어로 실행했을 때와 shell로 명령어를 실행하였을 때 출력 값이 달라진다는 것을 알 수 있다.
ansible 192.168.63.134 -m command -a set
# FAILED | rc=2 >>
# [Errno 2] No such file or directory: b'set'
ansible 192.168.63.134 -m shell -a set
# CHANGED | rc=0 >>
# BASH=/bin/sh ... (셸 환경 변수 전체 출력)
→ command는 set을 실행 파일로 찾으려다 실패, shell은 bash 내장 명령으로 정상 처리.
공개키 배포 트러블슈팅
앞서 작성한 playbook.yaml을 그대로 실행하면 아래 문제들이 순서대로 발생할 수 있다.
1. YAML 문법 오류
들여쓰기와 리스트 표시(-)가 빠지면 파싱 실패...
틀린 예
name: Public key is deployed to managed hosts for ansible
hosts: 192.168.51.131
tasks:
- name: Ensure key is in user's authorized_keys
authorized_keys:
user: user
state: present
key: '{{ item }}'
with_file:
- ~/.ssh/id_ed25519.pub
YAML 들여쓰기 규칙
- 플레이북 최상위는 play들의 리스트 →
- name:으로 시작 - play의 속성(
hosts,tasks)은- name:보다 한 단계 들여쓰기 tasks:아래 각 태스크도-로 시작, 한 단계 더 들여쓰기- 모듈(
authorized_key)과 태스크 키워드(with_file)는 같은 레벨 - 모듈의 파라미터(
user,state,key)는 모듈보다 한 단계 더 들여쓰기
2. SSH 인증 실패 (Permission denied)
UNREACHABLE! => {
"msg": "Failed to connect to the host via ssh: user@192.168.63.134:
Permission denied (publickey,gssapi-keyex,gssapi-with-mic,password).",
}
확인 순서
- 개인키 권한 확인 (control 노드)
ls -l ~/.ssh/id_ed25519
# -rw------- (600) 이어야 함
chmod 600 ~/.ssh/id_ed25519
ssh -v로 상세 로그 확인
ssh -v user@192.168.63.134
아래처럼 나오면 → 키를 제시했지만 서버가 거부한 것 (managed 노드에 공개키가 없음)
debug1: Offering public key: /home/user/.ssh/id_ed25519 ...
debug1: Authentications that can continue: publickey,gssapi-keyex,gssapi-with-mic,password
debug1: Next authentication method: password
- 비밀번호로 우선 접속해서 상태 확인
ssh user@192.168.63.134
# 비밀번호 입력 시 접속 성공 → password 인증
4. 공개키 배포 (ssh-copy-id)
ssh-copy-id로 직접 배포하는 것.
# control 노드에서 실행
ssh-copy-id -i ~/.ssh/id_ed25519.pub user@192.168.63.134
- 비밀번호 인증으로 로그인 후, 공개키를 managed 노드의
~/.ssh/authorized_keys에 자동 추가 ~/.ssh권한(700),authorized_keys권한(600) 부여
배포 후 비밀번호 없이 접속되는지 확인:
ssh user@192.168.63.134
playbook을 직접 실행하는 방법 (아직 키가 없는 최초 1회는 --ask-pass 필요):
ansible-playbook playbook.yaml -i inventory --ask-pass'Ansible' 카테고리의 다른 글
| Ansible Handler Ignore (0) | 2026.09.10 |
|---|---|
| Ansible Fact (0) | 2026.09.10 |
| Ansible Playbook (0) | 2026.08.16 |