Ansible 구현하기; 서버에 구성 변경 사항을 적용하기; 첫 번째 Ansible 플레이북을 만들기.
ansible, 모듈, 플레이북
지식: 복잡성:
소요 시간: 30분
Ansible은 관리 작업을 중앙 집중화하고 자동화하는 도구입니다. 다음과 같은 특징이 있습니다:
에이전트 미사용(클라이언트에 특정 배포가 필요하지 않음),
멱동성(실행할 때마다 동일한 효과).
Linux 클라이언트를 원격으로 구성하기 위해 SSH 프로토콜을 사용하거나 Windows 클라이언트와 작업하기 위해 WinRM 프로토콜을 사용합니다. 이러한 프로토콜 중 어느 것도 사용할 수 없는 경우에는 항상 API를 사용하여 서버, 워크스테이션, 도커 서비스, 네트워크 장비 등 (사실 거의 모든 것)의 구성에 Ansible을 사용할 수 있습니다.
주의
SSH 또는 WinRM 흐름을 Ansible 서버에서 모든 클라이언트로 열어 놓는 것은 아키텍처의 중요한 요소이므로 주의 깊게 모니터링해야 합니다.
Ansible은 푸시 기반이므로 각 실행 사이에 대상 서버의 상태를 유지하지 않습니다. 반대로 실행될 때마다 새로운 상태 검사를 수행합니다. 이를 스테이트리스(stateless)라고 합니다.
Ansible은 다음과 같은 작업에 도움을 줄 수 있습니다:
프로비저닝(새 VM 배포),
애플리케이션 배포,
구성 관리,
자동화,
오케스트레이션 (1개 이상의 대상을 사용할 때).
참고
Ansible은 원래 Cobbler와 같은 다른 도구의 설립자인 Michael DeHaan이 작성했습니다.
가장 초기 버전은 2012년 3월 9일에 출시된 0.0.1 버전입니다.
2015년 10월 17일, AnsibleWorks(Ansible 뒤에 있는 회사)는 Red Hat에 1억 5천만 달러에 인수되었습니다.
일상적인 Ansible 사용을 위해 그래픽 인터페이스를 제공하기 위해 Ansible Tower (RedHat)와 같은 도구를 설치할 수 있습니다. 이는 유료인 경우도 있으며 오픈소스 대안으로 Awx 또는 Jenkins와 Rundeck와 같은 다른 프로젝트도 사용할 수 있습니다.
개요
이 교육을 따르려면 최소 2개의 Rocky8 서버가 필요합니다:
첫 번째는 관리 기기이고, Ansible은 그 위에 설치될 것입니다.
두 번째는 구성 및 관리할 서버입니다(Rocky Linux 이외의 다른 Linux도 사용 가능).
아래 예에서 관리 스테이션의 IP 주소는 172.16.1.10이고, 관리 대상 스테이션의 IP 주소는 172.16.1.11입니다. IP 주소 지정 계획에 따라 예시를 조정하십시오.
Ansible은 EPEL 리포지토리에서 사용할 수 있지만 지금은 꽤 오래된 버전인 2.9.21로 제공됩니다. 이를 따라하면 수행하면 이 작업이 어떻게 수행되는지 볼 수 있지만 최신 버전을 설치할 예정이므로 실제 설치 단계를 건너뛸 것 입니다. _EPEL_은 두 버전 모두에 필요하므로 지금 바로 설치할 수 있습니다.
python3-argcomplete는 _EPEL_에서 제공합니다. 아직 설치하지 않았다면 epel-release를 설치하십시오.
이 패키지는 Ansible 명령어를 자동 완성하는 데 도움이 됩니다.
Ansible을 실제로 설치하기 전에, Rocky Linux에 새로 설치한 Python 버전을 사용하도록 설정해야 합니다. 그 이유는 이 설정 없이 계속 설치하면 기본 python3 (이 글을 쓰는 시점에서 3.6 버전) 이 새로 설치한 3.8 버전 대신 사용될 것입니다. 원하는 버전을 다음 명령어로 설정합니다:
Ansible은 구성할 모든 장비와 함께 작동해야 하므로, 조직과 완벽히 일치하는 잘 구조화된 인벤토리 파일(하나 또는 여러 개)을 제공하는 것이 매우 중요합니다.
이 파일을 구성하는 방법에 대해 신중히 생각해야 할 때가 있습니다.
기본 인벤토리 파일인 /etc/ansible/hosts로 이동하세요. 몇 가지 예시가 제공되며 주석 처리되어 있습니다:
# 이것은 기본 ansible 'hosts' 파일입니다.
#
# /etc/ansible/hosts에 위치해야 합니다.
#
# - 주석은 '#' 문자로 시작합니다.
# - 빈 줄은 무시됩니다.
# - 호스트 그룹은 [헤더] 요소로 구분됩니다.
# - 호스트 이름 또는 IP 주소를 입력할 수 있습니다.
# - 호스트 이름/ip는 여러 그룹의 구성원이 될 수 있습니다.
# Ex 1: 그룹에 속하지 않은 호스트, 그룹 헤더 앞에 지정하세요:
## green.example.com
## blue.example.com
## 192.168.100.1
## 192.168.100.10
# Ex 2: 'webservers' 그룹에 속하는 호스트 모음:
## [webservers]
## alpha.example.org
## beta.example.org
## 192.168.1.100
## 192.168.1.110
# 패턴에 따라 여러 호스트가 있는 경우 다음과 같이 지정할 수 있습니다:
# 그들은 다음과 같습니다:
## www[001:006].example.com
# Ex 3: 'dbservers' 그룹에 속하는 데이터베이스 서버 모음:
## [dbservers]
##
## db01.intranet.mydomain.net
## db02.intranet.mydomain.net
## 10.25.1.56
## 10.25.1.57
# 다음은 호스트 범위의 또 다른 예입니다.
# 이번에는 선행 0이 없습니다.
## db-[99:101]-node.example.com
예시에서 볼 수 있듯이, 제공된 파일은 시스템 관리자에게 잘 알려진 INI 형식을 사용합니다. 다른 파일 형식(예: yaml)을 선택할 수도 있지만, 첫 번째 테스트에는 INI 형식이 우리의 예제에 적합합니다.
물론 실제 환경에서는 인벤토리를 자동으로 생성할 수도 있으며, 특히 VMware VSphere나 AWS, Openstack 등의 클라우드 환경과 같은 가상화 환경이 있는 경우에 유용합니다.
/etc/ansible/hosts에서 호스트 그룹 생성:
그룹은 대괄호로 선언됩니다. 그룹에 속하는 요소가 이어집니다. 예를 들어 이 파일에 다음 블록을 삽입하여 rocky8 그룹을 만들 수 있습니다.
[rocky8]
172.16.1.10
172.16.1.11
그룹은 다른 그룹 내에서 사용할 수 있습니다. 이 경우 상위 그룹이 다음과 같이 :chidren 속성이 있는 하위 그룹으로 구성되도록 지정해야 합니다.
ansible 사용자가 관리 스테이션에서 ssh-keygen 명령으로 이중 키를 생성합니다.
[ansible]$ ssh-keygen
Generating public/private rsa key pair.
Enter file in which to save the key (/home/ansible/.ssh/id_rsa):
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /home/ansible/.ssh/id_rsa.
Your public key has been saved in /home/ansible/.ssh/id_rsa.pub.
The key fingerprint is:
SHA256:Oa1d2hYzzdO0e/K10XPad25TA1nrSVRPIuS4fnmKr9g ansible@localhost.localdomain
The key's randomart image is:
+---[RSA 3072]----+
| .o . +|
| o . =.|
| . . + +|
| o . = =.|
| S o = B.o|
| = + = =+|
| . + = o+B|
| o + o *@|
| . Eoo .+B|
+----[SHA256]-----+
다음 플레이북을 사용하면 대상 서버에 Apache 및 MariaDB를 설치할 수 있습니다.
다음 내용을 갖는 test.yml 파일을 생성하세요:
---
- hosts: rocky8 <1>
become: true <2>
become_user: root
tasks:
- name: ensure apache is at the latest version
dnf: name=httpd,php,php-mysqli state=latest
- name: ensure httpd is started
systemd: name=httpd state=started
- name: ensure mariadb is at the latest version
dnf: name=mariadb-server state=latest
- name: ensure mariadb is started
systemd: name=mariadb state=started
...
<1> 대상 그룹 또는 대상 서버는 인벤토리에 존재해야 합니다.
<2> 연결되면 사용자는 기본적으로 sudo를 통해 root가 됩니다.
플레이북 실행은 ansible-playbook 명령으로 수행됩니다.
$ ansible-playbook test.yml
PLAY [rocky8] ****************************************************************
TASK [setup] ******************************************************************
ok: [172.16.1.10]
ok: [172.16.1.11]
TASK [ensure apache is at the latest version] *********************************
ok: [172.16.1.10]
ok: [172.16.1.11]
TASK [ensure httpd is started] ************************************************
changed: [172.16.1.10]
changed: [172.16.1.11]
TASK [ensure mariadb is at the latest version] **********************************
changed: [172.16.1.10]
changed: [172.16.1.11]
TASK [ensure mariadb is started] ***********************************************
changed: [172.16.1.10]
changed: [172.16.1.11]
PLAY RECAP *********************************************************************
172.16.1.10 : ok=5 changed=3 unreachable=0 failed=0
172.16.1.11 : ok=5 changed=3 unreachable=0 failed=0
가독성을 높이기 위해 플레이북을 완전한 yaml 형식으로 작성하는 것이 권장됩니다. 이전 예제에서 인수는 모듈과 동일한 줄에 주어지고, 인자의 값은 이름과 =로 분리된 형식으로 주어졌습니다. 동일한 플레이북을 완전한 yaml 형식으로 살펴보세요:
---
- hosts: rocky8
become: true
become_user: root
tasks:
- name: ensure apache is at the latest version
dnf:
name: httpd,php,php-mysqli
state: latest
- name: ensure httpd is started
systemd:
name: httpd
state: started
- name: ensure mariadb is at the latest version
dnf:
name: mariadb-server
state: latest
- name: ensure mariadb is started
systemd:
name: mariadb
state: started
...
Tip
dnf는 목록을 인수로 제공할 수 있는 모듈 중 하나입니다.
컬렉션에 대한 참고 사항: Ansible은 이제 컬렉션 형식의 모듈을 제공합니다. 일부 모듈은 ansible.builtin 컬렉션 내에서 기본적으로 제공되며, 다른 모듈은 수동으로 설치해야 합니다. 예를 들면 다음과 같습니다:
여기서 [collectionname]은 컬렉션의 이름입니다(여기서 대괄호는 이것을 실제 컬렉션 이름으로 대체해야 할 필요성을 강조하는 데 사용되며 명령의 일부가 아닙니다).
이전 예제는 다음과 같이 작성해야 합니다.
---
- hosts: rocky8
become: true
become_user: root
tasks:
- name: ensure apache is at the latest version
ansible.builtin.dnf:
name: httpd,php,php-mysqli
state: latest
- name: ensure httpd is started
ansible.builtin.systemd:
name: httpd
state: started
- name: ensure mariadb is at the latest version
ansible.builtin.dnf:
name: mariadb-server
state: latest
- name: ensure mariadb is started
ansible.builtin.systemd:
name: mariadb
state: started
...
플레이북은 하나의 대상으로 제한되지 않습니다.
---
- hosts: webservers
become: true
become_user: root
tasks:
- name: ensure apache is at the latest version
ansible.builtin.dnf:
name: httpd,php,php-mysqli
state: latest
- name: ensure httpd is started
ansible.builtin.systemd:
name: httpd
state: started
- hosts: databases
become: true
become_user: root
- name: ensure mariadb is at the latest version
ansible.builtin.dnf:
name: mariadb-server
state: latest
- name: ensure mariadb is started
ansible.builtin.systemd:
name: mariadb
state: started
...
플레이북의 구문을 확인할 수 있습니다.
$ ansible-playbook --syntax-check play.yml
yaml에 "linter"를 사용할 수도 있습니다.
$ dnf install -y yamllint
그런 다음 플레이북의 yaml 구문을 확인합니다.
$ yamllint test.yml
test.yml
8:1 error syntax error: could not find expected ':' (syntax)