"Ansible"
저도 사실상 ansible을 사용하지만 실제로 자세하게 파악해보는 건 처음인 것 같습니다.
항상 쓰던 명령어만 쓰면서, 이건 왜 이렇게 되어있을까? 이런 생각을 해보았습니다.
그렇기 때문에 자세하게 파헤쳐보고자 글을 쓰게되었습니다.
ansible이란, 복잡성을 줄이고 어디에서나 실행되는 오픈 소스 자동화를 제공
ansible을 사용하면 거의 모든 작업을 자동화할 수 있습니다.
참고문서: Introduction to Ansible
ansible문서에서 언급하는 사용사례는 아래와 같습니다.
즉 ansible의 장점은 ansible소개와 동일하게 손쉬운 자동화 배포 툴로 보입니다.
ansible을 연습하기에 앞서 연습할 Testbed는 rocky linux 9.3에서 연습해보겠습니다.
Ansible을 시작하기 위해선 아래와 같이 ansible을 설치해야합니다.
[beomjin@testbed-01 ~]$ pip install ansible
bash: pip: command not found와 같이 pip라는 command가 없다고 나타난다.
이는, 현재 OS에 pip pakage가 없어서 나타나는 것입니다.
[beomjin@testbed-01 ~]$ sudo dnf install pip
로 pip를 설치해준다.
pip란?) pip는 파이썬으로 작성된 패키지 소프트웨어를 설치 · 관리하는 패키지 관리 시스템이다.
pip패키지를 정상적으로 설치하고 난 뒤, 아래와 같이 pip를 통하여 ansible을 설치하면 정상적으로 설치가 됩니다.
[beomjin@testbed-01 ~]$ pip install ansible
Defaulting to user installation because normal site-packages is not writeable
Collecting ansible
Downloading ansible-8.7.0-py3-none-any.whl (48.4 MB)
|████████████████████████████████| 48.4 MB 241 kB/s
Collecting ansible-core~=2.15.7
Downloading ansible_core-2.15.10-py3-none-any.whl (2.3 MB)
|████████████████████████████████| 2.3 MB 37.2 MB/s
Collecting resolvelib<1.1.0,>=0.5.3
Downloading resolvelib-1.0.1-py2.py3-none-any.whl (17 kB)
Collecting packaging
Downloading packaging-24.0-py3-none-any.whl (53 kB)
|████████████████████████████████| 53 kB 2.7 MB/s
Collecting PyYAML>=5.1
Downloading PyYAML-6.0.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (738 kB)
|████████████████████████████████| 738 kB 35.6 MB/s
Collecting cryptography
Downloading cryptography-42.0.5-cp39-abi3-manylinux_2_28_x86_64.whl (4.6 MB)
|████████████████████████████████| 4.6 MB 46.9 MB/s
Collecting importlib-resources<5.1,>=5.0
Downloading importlib_resources-5.0.7-py3-none-any.whl (24 kB)
Collecting jinja2>=3.0.0
Downloading Jinja2-3.1.3-py3-none-any.whl (133 kB)
|████████████████████████████████| 133 kB 42.7 MB/s
Collecting MarkupSafe>=2.0
Downloading MarkupSafe-2.1.5-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (25 kB)
Collecting cffi>=1.12
Downloading cffi-1.16.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (443 kB)
|████████████████████████████████| 443 kB 37.7 MB/s
Collecting pycparser
Downloading pycparser-2.22-py3-none-any.whl (117 kB)
|████████████████████████████████| 117 kB 31.5 MB/s
Installing collected packages: pycparser, MarkupSafe, cffi, resolvelib, PyYAML, packaging, jinja2, importlib-resources, cryptography, ansible-core, ansible
WARNING: Value for scheme.platlib does not match. Please report this to <https://github.com/pypa/pip/issues/10151>
distutils: /home/beomjin/.local/lib/python3.9/site-packages
sysconfig: /home/beomjin/.local/lib64/python3.9/site-packages
WARNING: Additional context:
user = True
home = None
root = None
prefix = None
Successfully installed MarkupSafe-2.1.5 PyYAML-6.0.1 ansible-8.7.0 ansible-core-2.15.10 cffi-1.16.0 cryptography-42.0.5 importlib-resources-5.0.7 jinja2-3.1.3 packaging-24.0 pycparser-2.22 resolvelib-1.0.1
[beomjin@testbed-01 ~]$ mkdir ansible_quickstart && cd ansible_quickstartproject dir에서는 무슨 작업을 할까?
project dir은 ansible 수행할 때, role이나 inventory 파일 등을 모아두는 project dir이라고 생각하면 될 것 같다.
참고문서: Ansible Inventory
Ansible에서 말하는 inventory란 무엇일까?
문서를 읽고 생각해 본 바 관리할 node의 집합 이라고 보고있습니다.
마치 /etc/hosts 에 대한 내용을 ansible에서 사용하기 쉽게하기위하여 role을 나누어 정의한 것 이라고 생각이 듭니다.
/etc/hosts
[beomjin@testbed-01 ansible_quickstart]$ cat /etc/hosts
127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
10.3.1.140 testbed-01
inventory (hosts.ini 혹은 inventory.ini)
[beomjin@testbed-01 ansible_quickstart]$ cat hosts.ini
[mynodes]
10.3.1.140
위와같이 잘 설정이 되었는지 확인하기 위하여 inventory 파일을 ansible-inventory를 이용하여 확인해보겠습니다.
[beomjin@testbed-01 ansible_quickstart]$ ansible-inventory -i hosts.ini --list
{
"_meta": {
"hostvars": {}
},
"all": {
"children": [
"ungrouped",
"mynodes"
]
},
"mynodes": {
"hosts": [
"10.3.1.140"
]
}
}
정상적으로 inventory에 들어간 것은 확인하였습니다.
그렇다면 ping을 날려 mynodes에 들어간 10.3.1.140과 통신을 진행해보겠습니다.
[beomjin@testbed-01 ansible_quickstart]$ ansible mynodes -m ping -b -i hosts.ini
10.3.1.140 | UNREACHABLE! => {
"changed": false,
"msg": "Failed to connect to the host via ssh: beomjin@10.3.1.140: Permission denied (publickey,gssapi-keyex,gssapi-with-mic,password).",
"unreachable": true
}
oh... ssh를 통하여 해당 vm을 확인할 때, 권한문제가 발생 하였습니다.
위 이슈를 아래와 같이 조치 하였습니다.
[beomjin@testbed-01 ansible_quickstart]$ ssh-keygen -t rsa -b 2048
[beomjin@testbed-01 ansible_quickstart]$ ssh-copy-id -i ~/.ssh/id_rsa.pub beomjin@10.3.1.140
[beomjin@testbed-01 ansible_quickstart]$ ansible-inventory -i hosts.ini --list
{
"_meta": {
"hostvars": {}
},
"all": {
"children": [
"ungrouped",
"mynodes"
]
},
"mynodes": {
"hosts": [
"10.3.1.140"
]
}
}
정상적으로 ping이 수행되었습니다.
다만 ssh-keypair가 아닌 ansible의 기능을 이용해서 해보고자 한다면 아래와 같은 방법을 추천합니다.
참고문서: ansible vault
Ansible Vault는 password와 key같은 보안에 민감한 파일들을 암복호화해주는 기능입니다.
ansible을 설치하게 되면 같이 설치가 됩니다.
[beomjin@testbed-01 ansible_quickstart]$ ansible-vault create vault.yml
New Vault password:
Confirm New Vault password:
[beomjin@testbed-01 ansible_quickstart]$ cat vault.yml
$ANSIBLE_VAULT;1.1;AES256
32366262393666356263666230663837613738336337...
[beomjin@testbed-01 ansible_quickstart]$ ansible mynodes -m ping -b -i hosts.yaml
my_node_01 | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python3"
},
"changed": false,
"ping": "pong"
}
ansible-vault 라는 명령어를 통하여 create 를 하며 뒤에 vault.yml은 vault 파일의 파일명입니다.
따라서 vault.yml파일에 사용할 password를 2회 입력 후 ping테스트를 진행하게되면 ansble을 수행할 때, vault password를 이용하여 진행하게 됩니다.
inventory의 형식은 크게 ini와 yaml 형식으로 나뉘게 됩니다.
공식 문서에서 이야기하는 바에 의하면,
로 나뉘게 된다고 합니다.
mynodes:
hosts:
my_node_01:
ansible_host: 10.3.1.140
[beomjin@testbed-01 ansible_quickstart]$ ansible mynodes -m ping -b -i hosts.yaml
my_node_01 | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python3"
},
"changed": false,
"ping": "pong"
}
[beomjin@testbed-01 ansible_quickstart]$ cat hosts.ini
testbed-01 ip=10.3.1.140
[mynodes]
#10.3.1.140
testbed-01
[beomjin@testbed-01 ansible_quickstart]$ ansible mynodes -m ping -b -i hosts.ini
testbed-01 | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python3"
},
"changed": false,
"ping": "pong"
}
hosts.ini의 상단에 hosts와 같이 정의를 하게된다면, 아래 섹션에 대해서는 ip가 아닌 hostname으로 기재를 해도 정상적으로 동작하게 됩니다.
참고문서:Ansible inventroy 팁
해당 변수를 보게되면, 좀 더 다양한 Inventory를 작성할 수 있다고 합니다.
향후 시도할 일이 있다면 사용을 해봐야 겠습니다.
참고문서: Ansible Playbook
Ansible playbook이란?
"Playbook에서의 yaml을 통하여 Ansible이 관리형 노드를 배포하고 구성하는 데 사용하는 자동화 청사진(아키텍처)"
Playbook
"전반적인 목표를 달성하기 위해 Ansible이 위에서 아래로 작업을 수행하는 순서를 정의하는 목록"
Play
"인벤토리의 관리 노드에 매핑되는 정렬된 작업 목록."
Task
"Ansible이 수행하는 작업을 정의하는 단일 모듈에 대한 참조"
Module
"Ansible이 관리형 노드에서 실행되는 코드 또는 바이너리 단위, Ansible 모듈은 각 모듈에 대한 FQCN(정규화된 컬렉션 이름)을 사용하여 컬렉션으로 그룹화"
단순한 playbook을 만들어보겠습니다.
hostname을 변경하는 단순한 palybook입니다.
[beomjin@testbed-01 ansible_quickstart]$ cat playbook.yml
---
- name: Configure hostname
hosts: all
become: yes
tasks:
- name: Set hostname
ansible.builtin.hostname:
name: testbed
해당 playbook.yml이 정상적으로 구동되는지 확인하려면 아래와 같이 --check (-c)를 통하여 시스템에 적용하는것이 아닌 해당 yml에 대한 확인이 가능합니다.
[beomjin@testbed-01 ansible_quickstart]$ ansible-playbook -i hosts.ini --check playbook.yml
PLAY [Configure hostname] ************************************************************************************************************************************************************************************
TASK [Gathering Facts] ***************************************************************************************************************************************************************************************
ok: [testbed-01]
TASK [Set hostname] ******************************************************************************************************************************************************************************************
ok: [testbed-01]
PLAY RECAP ***************************************************************************************************************************************************************************************************
testbed-01 : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
check 상 failed가 발생한 구간은 없습니다.
적용하면 아래와 같이 확인이 됩니다.
[beomjin@testbed ansible_quickstart]$ ansible-playbook -i hosts.ini --check playbook.yml
PLAY [Configure hostname] ************************************************************************************************************************************************************************************
TASK [Gathering Facts] ***************************************************************************************************************************************************************************************
ok: [testbed-01]
TASK [Set hostname] ******************************************************************************************************************************************************************************************
ok: [testbed-01]
PLAY RECAP ***************************************************************************************************************************************************************************************************
testbed-01 : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
[beomjin@testbed ansible_quickstart]$ ansible-playbook -i hosts.ini playbook.yml
PLAY [Configure hostname] ************************************************************************************************************************************************************************************
TASK [Gathering Facts] ***************************************************************************************************************************************************************************************
ok: [testbed-01]
TASK [Set hostname] ******************************************************************************************************************************************************************************************
ok: [testbed-01]
PLAY RECAP ***************************************************************************************************************************************************************************************************
testbed-01 : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
이로써 간단한 playbook을 확인해보았습니다.
여러가지 playbook이 있으니 다양한 공부가 될 것 같습니다.