가시다님의 주관하시는 앤서블 스터디(a101)의 내용 정리입니다.
앤서블로 시작하는 인프라 자동화 책의 내용이 포함되어 있습니다.
Ansible이란?
테라폼과 함께 가장 인기 있는 오픈소스 IT자동화 도구로, IT업무를 코드 기반으로 작성하여 환경이 다르더라도 동일하게 적용될 수 있도록 돕는 역할을 합니다. 2015년 10월 레드햇이 인수하여 개발하고 관리하고 있습니다.
실습을 위해 제어노드(Control Node) 1대와 관리노드(Manged Node) 3대를 구성하고, Ansible 설정과 기본 사용을 해봅니다.
Ansible의 다음과 같은 특징이 있습니다.
- No 에이전트(Agentless)
- 기존 자동화 도구(Puppet, Chef)와 같이 자동화 관리 대상 서버(Manged Node)에 별도의 에이전트를 설치하지 않습니다
- 에이전트 설치 없이 SSH로 접속하여 쉽게 대상 서버들을 관리할 수 있습니다.
- 멱등성(Idempotent)
- 동일한 연산을 여러 번 적용하더라도 결과가 달라지지 않는 성질입니다.
- Ansible은 시스템을 원하는 상태로 유지하도록 설계되어 있어, 작업을 여러 번 실행하여도 같은 결과를 냅니다.
- Ansible의 모듈과 같이 명확하게 정의된 상태가 아닌, Shell을 통해 수행한 작업 등은 상태를 유지하지 않으니 주의해야 합니다.
- 쉬운 사용법 및 다양한 모듈 제공
- Yaml 문법을 사용하여 쉽게 작성하고 읽을 수 있습니다.
- 리눅스 기본 명령어들과 같은 시스템 관리 모듈부터 퍼블릭 클라우드, 쿠버네티스 등 수많은 모듈과 컬렉션을 제공합니다.
- 공식문서에 다양한 플레이북 예제를 제공합니다.
Ansible 설치
Ansible 설치할 패키지 버전 정보입니다. 앤서블 사용을 위해서는 python,ansible 패키지가 필수적을 설치되어야 합니다.
python: 3.10.12
ansible-core: 2.15.8
jinja version: 3.0.3
# 작업 기본 디렉터리 확인
whoami
pwd
/root/my-ansible
# 파이썬 버전 확인
python3 --version
Python 3.10.12
# 설치
apt install software-properties-common -y
add-apt-repository --yes --update ppa:ansible/ansible
apt install ansible -y
# 확인 :(파이썬 3.11.2, jinja 진자 3.1.2)
ansible --version
ansible [core 2.15.8]
config file = /etc/ansible/ansible.cfg
configured module search path = ['/root/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
ansible python module location = /usr/lib/python3/dist-packages/ansible
ansible collection location = /root/.ansible/collections:/usr/share/ansible/collections
executable location = /usr/bin/ansible
python version = 3.10.12 (main, Nov 20 2023, 15:14:05) [GCC 11.4.0] (/usr/bin/python3)
jinja version = 3.0.3
libyaml = True
Inventory(인벤토리)
인벤토리는 Ansible이 자동화를 대상으로 하는 관리 호스트를 지정해논 파일입니다.
- . ini 파일 형식을 기본으로 사용하고, Yaml을 포함한 다양한 파일 형식도 사용할 수 있습니다.
- 인벤토리 파일은 다양한 종류의 형식과 그룹을 지원합니다.
1. 호스트명/IP
가장 일반적인 방식으로 호스트명 또는 IP 주소가 한 줄에 하나씩 있는 목록 형태입니다.
# 1.IP를 이용한 방식
10.10.1.11
10.10.1.12
10.10.1.13
# 2.호스트명을 이용한 방식
tnode1
tnode2
# inventory 검증 : -i 특정 인벤토리 지정
ansible-inventory -i ./inventory --list | jq
2. 그룹
그룹을 지어 사용하는 목적에 따라 작업을 처리할 수도 있습니다.
:children이라는를 추가하여 호스트 그룹에 기존에 정의한 호스트 그룹을 포함할 수도 있습니다.
[webservers]
web1.example.com
web2.example.com
[db-servers]
db01.example.com
db02.example.com
[datacenter:children]
webservers
dbservers
3. 범위를 사용한 호스트 사양 간소화
쿠버네티스 워커노드나 성질이 같은 여러 대의 노드일 경우 [start:end] 범위를 지정하여 인벤토리를 간소화할 수 있습니다.
숫자 또는 영문자로 범위를 지정할 수 있으며, 대괄호 사이에 시작 구문과 종료 구문을 포함합니다.
[webservers]
web[1:2].example.com
[db-servers]
db[01:02].example.com
# inventory 검증 : -i 특정 인벤토리 지정
ansible-inventory -i ./inventory --list | jq
[WARNING]: Invalid characters were found in group names but not replaced, use
-vvvv to see details
{
"_meta": {
"hostvars": {}
},
"all": {
"children": [
"ungrouped",
"webservers",
"db-servers"
]
},
"db-servers": {
"hosts": [
"db01.example.com",
"db02.example.com"
]
},
"webservers": {
"hosts": [
"web1.example.com",
"web2.example.com"
]
}
}
💡 Ansible 인벤토리 default 설정
Ansible 명령어 시, 인벤토리 파일을 지정하려면 -i 옵션을 사용해야 하지만 ansible.cfg파일에 기본 인벤토리를 지정하여 생략할 수 있습니다. 하지만, ansible config 파일은 우선순위가 있어 주의해야 합니다.
ansible.cfg
[defaults]
inventory =./inventory
ansible config 적용 우선순위
1. `ANSIBLE_CONFIG` (environment variable if set)
2. `ansible.cfg` (in the current directory)
3. `~/. ansible.cfg` (in the home directory)
4. `/etc/ansible/ansible.cfg`
Playbook(플레이북)
플레이북 환경 설정
- ansible.cfg 파일을 통해 다양한 앤서블 설정을 할 수 있습니다.
- ansible.cfg 파일은 여러 개의 섹션과 키/값 쌍으로 정의되어 있습니다.
- 실습을 위한 기본 설정을 저장합니다.
[defaults]
inventory = ./inventory
remote_user = root
ask_pass = false
[privilege_escalation]
become = true
become_method = sudo
become_user = root
become_ask_pass = false
[ default ] 섹션: Ansible 작업을 위한 기본값 설정
매개 변수 | 설명 |
inventory | 인벤토리 파일의 경로를 지정함. |
remote_user | 앤서블이 관리 호스트에 연결할 때 사용하는 사용자 이름을 지정함. 이때, 사용자 이름을 지정하지 않으면 현재 사용자 이름으로 지정됨. |
ask_pass | SSH 암호를 묻는 메시지 표시 여부를 지정함. SSH 공개 키 인증을 사용하는 경우 기본값은 false임. |
[privilege_escalation] 섹션 : 보안/감사로 인해 원격 호스트에 권한 없는 사용자 연결 후 관리 액세스 권한을 에스컬레이션
매개 변수 | 설명 |
become | 기본적으로 권한 에스컬레이션을 활성화할 때 사용하며, 연결 후 관리 호스트에서 자동으로 사용자를 전환할지 여부를 지정함. 일반적으로 root로 전환되며, 플레이북에서도 지정할 수 있음. |
become_method | 권한을 에스컬레이션하는 사용자 전환 방식을 의미함. 일반적으로 기본값은 sudo를 사용하며, su는 옵션으로 설정할 수 있음. |
become_user | 관리 호스트에서 전환할 사용자를 지정함. 일반적으로 기본값은 root임. |
become_ask_pass | become_method 매개 변수에 대한 암호를 묻는 메시지 표시 여부를 지정함. 기본값은 false임. 권한을 에스컬레이션하기 위해 사용자가 암호를 입력해야 하는 경우, 구성 파일에 become_ask_pass = true 매개 변수를 설정하면 됨. |
SSH 인증 설정
ansible은 ssh 프로토콜을 이용하여 동작하기 때문에 ssh 인증이 되어야 합니다.
간단한 실습을 위해 root계정과 비밀번호를 이용한 인증 방식을 사용하겠습니다. 운영환경이라면 root 계정 사용을 지양하고 패스워드 방식보다는 pem키 인증방식을 추천드립니다.
# ssh key 등록
# 제어노드서버에서 ssh키 발급
ssh-keygen -t rsa
ls .ssh
# managed node에 비밀번호 설정이 안되어 있을시에!
# Root 계정 비밀번호 설정
passwwd root
# Root 로그인 허용
vi /etc/ssh/sshd_config
- PermitRootLogin Yes
- passwordAuthentication yes
systemctl restart sshd
# 관리대상 서버에 퍼블릭 키 복사
ssh-copy-id root@tnode1
ssh-copy-id root@tnode2
ssh-copy-id root@tnode3
💡 HostKeyChecking
대상 서버가 많아지게 되면 중간에 관리 대상서버가 추가되거나 변경된다면 ssh의 hostkeychecking(known_hosts) 인증에 의해 앤서블이 해결하지 못하고 에러가 발생할 것이다. 이런 상황을 피하고 싶다면 ansible.cfg 파일에 hostKeyChecking 옵션을 꺼주도록 하자.
~/.ansible.cfg
[defaults]
host_key_checking = False
ad-hoc
ansible의 모듈을 command로 입력하고 결과를 반환할 수 있도록 도와주는 기능이다.
주로 ping, shell 모듈을 이용하여 연결을 테스트하거나 간단한 명령 작업 등에 주로 이용된다.
ansible -m <모듈> <호스트대상>
# ping 모듈
ansible -m ping web
# shell 모듈
ansible -m shell -a uptime all
플레이북 작성하기
- 플레이북은 Yaml 포맷으로 작성된 텍스트 파일이며 확장자는. yml이라는 확장자를 사용합니다.
- 플레이북은 대상 호스트나(host) 호스트 집합에 수행할 작업(task)을 정의하고 이를 실행합니다. 이때 특정 작업 단위를 수행하기 위해 모듈을 적용합니다.
Case 1 : debug 모듈을 이용하여 문자열을 출력
- debug 모듈을 통해 문자열을 출력합니다.
- --syntax-check 옵션으로 문법을 체크하고 성공/실패 케이스를 확인합니다.
# [ 플레이북 작성 ]
# first-playbook.yml
---
- hosts: all
tasks:
- name: Print message
debug:
msg: Hello CloudNet@ Ansible Study
# first-playbook-with-error.yml
---
- hosts: all
tasks:
- name: Print message
debug:
msg: Hello CloudNet@ Ansible Study
# 플레이북 문법 체크하기
root@server:~/my-ansible# ansible-playbook --syntax-check first-playbook.yml
playbook: first-playbook.yml
root@server:~/my-ansible# ansible-playbook --syntax-check first-playbook-error.yml
ERROR! conflicting action statements: debug, msg
The error appears to be in '/root/my-ansible/first-playbook-error.yml': line 4, column 7, but may
be elsewhere in the file depending on the exact syntax problem.
The offending line appears to be:
tasks:
- name: print
^ here
Case 2 : lineinfile 모듈을 이용하여 호스트 정보 추가
- 관리 대상서버의 /etc/hosts 파일에 제어노드의 호스트 정보를 추가합니다.
- 플레이북을 재실행하여 멱등성을 확인합니다.
# 1. 관리 대상 서버의 /etc/hosts 파일 내용 조회
ansible -m shell -a "cat /etc/hosts | grep -v :" all
root@server:~/my-ansible# ansible -m shell -a "cat /etc/hosts | grep -v :" all
tnode1 | CHANGED | rc=0 >>
127.0.0.1 localhost
# The following lines are desirable for IPv6 capable hosts
tnode3 | CHANGED | rc=0 >>
127.0.0.1 localhost
# The following lines are desirable for IPv6 capable hosts
tnode2 | CHANGED | rc=0 >>
127.0.0.1 localhost
# The following lines are desirable for IPv6 capable hosts
# 2. 플레이북 작성
vi add-hosts-playbook.yml
---
- hosts: all
tasks:
- name: 호스트 파일에 내용 추가하기
lineinfile:
path: "/etc/hosts" # 내용을 추가할 파일
line: "10.10.1.10 ansible-server" # 추가할 내용
insertafter: EOF # 맨 끝에 추가
# 3. 플레이북 실행
ansible-playbook add-hosts-playbook.yml
# 4.관리 대상 서버의 /etc/hosts 파일 내용 재조회
root@server:~/my-ansible# ansible -m shell -a "cat /etc/hosts | grep -v :" all
tnode3 | CHANGED | rc=0 >>
127.0.0.1 localhost
# The following lines are desirable for IPv6 capable hosts
10.10.1.10 ansible-server
tnode2 | CHANGED | rc=0 >>
127.0.0.1 localhost
# The following lines are desirable for IPv6 capable hosts
10.10.1.10 ansible-server
tnode1 | CHANGED | rc=0 >>
127.0.0.1 localhost
# The following lines are desirable for IPv6 capable hosts
10.10.1.10 ansible-server
플레이북 결과에서 초록색은 성공하였을 때, 노란색은 변경된 사항이 있을 때, 빨간색은 실패하였을 때를 나타내는데,
동일한 플레이북을 재실행하였을 때 수행결과는 성공이지만 changed가 0인 것을 확인할 수 있다.
Ansible Variasbles(변수)
앤서블은 변수를 사용하여, 설치하고자 하는 사용자, 패키지, 서버, 파일명 등 작업 시, 사용되는 다양한 값들을 저장할 수 있습니다.
앤서블에서 사용되는 변수는 그룹 변수, 호스트 변수, 플레이 변수, 추가 변수, 작업 변수 등이 있습니다.
1. 그룹 변수
- 인벤토리에 정의된 호스트 그룹에 적용하는 변수
- 인벤토리에 정의된 호스트 그룹에 적용하는 변수를 의미합니다.
- 인벤토리에 선언하고자 하는 그룹명과 함께 :vars라는 문자열을 추가해 변수를 선언합니다.
# inventory-group-var.ini
[web]
tnode1
tnode2
[db]
tnode3
[all:children]
web
db
# 그룹 변수 추가
[all:vars]
user=ansible
2. 호스트 변수
- 해당 호스트에서만 사용할 수 있습니다.
# inventory-host-var.ini
[web]
tnode1
tnode2
[db]
tnode3 user=ansible1
[all:children]
web
db
3. 플레이 변수
- 플레이북 내에서 선언되는 변수입니다.
- hosts와 같은 뎁스에 위치하며 vars: 필드를 통해 생성합니다.
---
- hosts: all
vars:
user: ansible2
tasks:
- name: Create User {{ user }}
ansible.builtin.user:
name: "{{ user }}"
state: present
4. 추가 변수
- ansible-playbook 명령어를 실행할 때 파라미터로 함께 넘겨주는 변수를 의미합니다.
- -e(extra_vars) 옵션으로 추가 변수를 선언합니다.
ansible-playbook -e user=ansible playbook.yaml
5. 작업 변수
- 플레이북의 태스크 수행 결과를 저장합니다.
- 특정 작업 수행 후 그 결과를 가지고 후속 작업에서 사용할 때 주로 사용됩니다.
- 예를 들어 가상머신을 조회하고, 조회된 결과를 가지고 가상머신을 생성할 때 작업 변수를 사용하면 좋습니다.
- 로그와 같이 수행된 결과의 목록을 출력하고 싶을 때도 사용됩니다.
---
- hosts: db
tasks:
- name: Create User {{ user }}
ansible.builtin.user:
name: "{{ user }}"
state: present
register: result
- ansible.builtin.debug:
var: result
변수의 우선순위
추가변수(실행 시 파라미터) > 플레이 변수 > 호스트 변수 > 그룹 변수
수정, 변화? 가 빈번하게 일어나는 위치의 변수일 경우 우선순위가 높은 것 같습니다.
상식적으로 생각하였을 때, 추가변수와 같이 명령어 단계에서 변수를 주면 당연히 우선순위가 가장 높을 것입니다.
플레이북에서 변수 사용
그럼 위에서 선언한 변수를 활용하여 플레이북을 작성해 보고 실행해 봅니다.
- {{ 변수명 }} 형식으로 변수를 사용합니다.
- {{ }} 사이에 반드시 개행이 있어야 합니다.
- 안전하게 문자열을 다루기 위해 항상 따옴표를 사용하는 것이 좋습니다.
# 플레이북 작성(create-user-playbook.yml)
---
- hosts: db
tasks:
- name: Create User {{ user }}
ansible.builtin.user:
name: "{{ user }}"
state: present
register: result
- ansible.builtin.debug:
var: result
# 플레이북 실행
root@server:~/my-ansible/vars# ansible-playbook create-user-playbook.yml
PLAY [db] *****************************************************************************************************************************************
TASK [Gathering Facts] ****************************************************************************************************************************
ok: [tnode3]
TASK [Create User ansible] ************************************************************************************************************************
changed: [tnode3]
TASK [ansible.builtin.debug] **********************************************************************************************************************
ok: [tnode3] => {
"result": {
"changed": true,
"comment": "",
"create_home": true,
"failed": false,
"group": 1001,
"home": "/home/ansible",
"name": "ansible",
"shell": "/bin/sh",
"state": "present",
"system": false,
"uid": 1001
}
}
PLAY RECAP ****************************************************************************************************************************************
tnode3 : ok=3 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
# 생성된 유저 확인
root@server:~/my-ansible/vars# ansible -m shell -a "cat /etc/passwd | grep ansible"
tnode3 | CHANGED | rc=0 >>
ansible:x:1001:1001::/home/ansible:/bin/sh
Facts(팩트)
팩트(Facts)는 앤서블이 관리 호스트에서 자동으로 검색한 변수입니다.
아래와 같이 메타 데이터들을 정보들을 자동으로 수집하여, OS 별로 분기처리해야 하거나, 호스트 이름을 사용한다던지 다양한 곳에 활용될 수 있습니다.
- 호스트 이름
- 커널 버전
- 네트워크 인터페이스 이름
- 운영체제 버전
- CPU 개수
- 사용 가능한 메모리
- 스토리지 장치의 크기 및 여유 공간
- 등등..
팩트 사용하기
팩트는 기본적으로 수집되도록 설정되어 있습니다. debug 모듈을 이용해서 수집된 호스트의 팩트를 확인합니다.
# 플레이북 작성(facts.yml)
---
- hosts: db
tasks:
- name: Print all facts
ansible.builtin.debug:
var: ansible_facts
# 플레이북 실헹
ansible-playbook facts.yml
아래와 같이 [ Gattering Facts ]라는 출력창이 표시되며 수집된 수많은 팩트들을 확인할 수 있습니다.
활용하고 싶은 팩트들을 찾아보고 싶다면 ad-hoc 기능을 이용해서 파일로 추출해 볼 수도 있습니다.
ansible -m setup -i inventory db >> facts.txt
팩트 수집 끄기
다음과 같은 이유로 팩트 수집을 원치 않을 때, 팩트 수집 기능을 비활성할 수 있습니다.
- 특정 호스트에 팩트를 수집하기 위한 특정 패키지를 설치할 수 없는 경우
- 사용자가 팩트 수집으로 인해 호스트에 부하가 걸리는 것을 원치 않을 때
---
- hosts: db
gather_facts: no # 팩트 수집을 비활성화합니다.
Ansible Vault
앤서블을 사용할 때, 패스워드나 API키 등 중요한 데이터들이 인벤토리나, 플레이북에 텍스트로 저장되기 때문에 보안상 위험을 야기합니다. 따라서, 앤서블에서는 사용되는 모든 데이터파일을 암/복호화할 수 있도록 하는 Ansible Vault라는 기능을 제공합니다.
파일 암/복호화하기
1. 암호화된 파일 생성
ansible-vault create 명령어로 암호화된 내용의 파일을 생성할 수 있습니다.
# 1.패스워드로 암호화
ansible-vault create mysecret.yml
New Vault password: P@ssw0rd!
Confirm New Vault password: P@ssw0rd!
# 아래 내용 입력 후 저장하고 빠져나오기
user: ansible
password: P@ssword!
: wq
# 2.파일로 암호화
# ansible-vault create 로 생성하려는 플레이북 파일 생성
ansible-vault create --vault-pass-file ./vault-pass mysecret1.yml
# 아래 내용 입력 후 저장하고 빠져나오기
user: ansible
password: P@ssword!
:wq
# 3. 암호화된 파일 확인
$ANSIBLE_VAULT;1.1;AES256
34363834353637303633366630653765363432373136353337656533363865616666616264386438
3665623935666162353230616135336535373565643335380a366561613838383366313633653332
64353538366235306561633431323337613537626465636232366137373561343639303332393561
3238633261636533310a653537306437373231316663393733653733396461356231333365626130
37323064373337383166663034613766326366333539343064396366363965613932663532626631
3039346432623334356531626665303762623032363561663837
2. 기존 파일 암호화
기존에 이미 만들어 놓은 파일도 암/복호화가 가능합니다.
# 1. 기존파일 복호화
ansible-vault decrypt mysecret.yml
Vault password:
Decryption successful
# 복호화 확인
cat mysecret.yml
user: ansible
password: cloud1234
# 2.기존파일 암호화
ansible-vault encrypt mysecret.yml
New Vault password:
Confirm New Vault password:
Encryption successful
# 암호화 확인
cat mysecret.yml
$ANSIBLE_VAULT;1.1;AES256
30323138663966623638343233343832326264653039366434323839323630623265613032623735
3235326166383864333763616561393334393366323465610a616133393439363162613133306562
33303061346231363265333533303037633034626432353164326137626665396133646433653265
3738626632633235320a643736326632336632623335643936313533363635383232363932346537
36386161333664393532316236346662626536326134636231336336303662336135343235616638
3532356266663966363064313465383266396230343766363262
암호화된 플레이북 실행
암호화된 플레이북을 실행할 때는 vault-id @prompt 옵션을 사용합니다.
# 암호화된 플레이북을 실행시켰을때 - 오류발생
ansible-playbook -i inventory facts.yaml
ERROR! Attempting to decrypt but no vault secrets found
# 암호화된 플레이북을 실행 - vault-id 옵션
ansible-playbook --vault-id @prompt -i inventory facts.yaml
Vault password: # 패스워드 입력
# 암호화된 플레이북을 실행 - 패스워드 입력 없이 실행
ansible-playbook --vault-password-file=./vault-pass facts.yml
'Automation > Ansible' 카테고리의 다른 글
앤서블(Ansible) 세마포어(Semaphore UI) - 4주차_2 (3) | 2024.02.08 |
---|---|
앤서블(Ansible) 보안설정 및 모니터링 자동화 - 4주차 (0) | 2024.02.08 |
앤서블(Ansible) 롤과 인프라 구성 자동화 - 3주차 (0) | 2024.02.04 |
앤서블(Ansible) 반복문, 조건문, 핸들러 및 작업 실패 처리 - 2주차 (0) | 2024.01.21 |