Ansible 네트워크 자동화 – 4

앤시블 네트워크 자동화 – 4

앤시블 role

Role은 함께 작동하는 앤시블 기본값, 파일, 작업, 템플릿, 변수, 그리고 다른 앤시블 구성요소들의 집합이다. 첫번째 playbook과 명령에서 본것 처럼, 명령에서 플레이북으로 이동하면 여러 작업을 쉽게 실행하고 같은 작업을 같은 순서로 반복할 수 있다. 플레이북에서 Role로 이동하면 명령한 작업을 보다 쉽게 재사용하고 공유할 수 있다. 내 role과 다른사람의 role을 직접 또는 갖법적으로 사용할 수있는 Ansible Galaxy를 볼 수 있다.

role의 이해

role이 정확히 무엇이며 왜 관심가져야 하는가? 앤시블 role은 기본적으로 알려진 파일구조로 나뉜 플레이북이다. 플레이북에서 role로 이동하면 앤시블 작업흐름을 쉽게 공유하고 읽고 업데이트할 수 있다.
예를들면 DNS 플레이북을 스스로 성할 필요가 없다. 대신 DNS서버와 role을 지정하여 구성하면된다.

DNS플레이북 예제.

role의 개념을 알기 위해 아래의 playbook.yml 파일은 두개의 작업을 가지는 하나의 yml 파일이다.
이 앤시블 플레이북은 시스코 IOS 장비의 호스트네임을 설정한 후 DNS 서버를 설정한다.

먼저, 인벤토리(hosts.yml)에 대상 장비를 등록한다.

$ vi hosts.yml
---
switches:
  hosts:
    Training_Main:
      ansible_host: 192.168.232.121
    Support:
      ansible_host: 192.168.232.120
  vars:
    ansible_network_os: cisco.ios.ios
    ansible_user: admin

dns_playbook.yml 파일을 작성한다.

$ cat dns_playbook.yml
---
- name: configure cisco switches
  hosts: switches
  connection: ansible.netcommon.network_cli
  gather_facts: no
  vars:
    dns: "8.8.8.8 8.8.4.4"

  tasks:
   - name: configure hostname
     cisco.ios.ios_config:
       lines: hostname {{ inventory_hostname }}

   - name: configure DNS
     cisco.ios.ios_config:
       lines: ip name-server {{ dns }}

ansible-playbook 명령으로 플레이북을 실행한다. -l 옵션은 해당 노드(Support)에만 실행하도록 제한하는 옵션이다.

$ ansible-playbook dns_playbook.yml -i hosts.yml -l Support -k
SSH password:

PLAY [configure cisco switches] ********************************************************************************

TASK [configure hostname] **************************************************************************************
[WARNING]: To ensure idempotency and correct diff the input configuration lines should be similar to how they
appear if present in the running configuration on device
changed: [Support]

TASK [configure DNS] *******************************************************************************************
changed: [Support]

PLAY RECAP *****************************************************************************************************
Support                    : ok=2    changed=2    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

호스트네임은 인벤토리에 지정된 이름(Support)으로 바뀌고 dns는 플레이북에 저장된 변수로 설정이 변경되었다.

플레이북을 role로 변환

다음 과정으로 이 플레이북을 재사용가능한 role로 변환해 보도록 한다.
디렉토리 구조를 수동으로 만들거나 ansible-galaxy init 명령으로 role을 위한 표준 프레임워크를 생성할 수 있다.

$ ansible-galaxy init test-demo
- Role test-demo was created successfully
$ cd test-demo/
$ tree
.
├── defaults
│   └── main.yml
├── files
├── handlers
│   └── main.yml
├── meta
│   └── main.yml
├── README.md
├── tasks
│   └── main.yml
├── templates
├── tests
│   ├── inventory
│   └── test.yml
└── vars
└── main.yml

8 directories, 8 files

먼저 예제에서는 tasks와 vars디렉토리만 사용할 것이다. 디렉토리 구조는 아래와 같다.

$ tree
.

├── tasks
│   └── main.yml
...
└── vars
└── main.yml

위에서 만든 플레이북의 변수와 작업을 role로 이동한다.
tasks/main.yml 파일을 아래처럼 수정한다.

$ vi tasks/main.yml

---
# tasks file for test-demo

- name: configure hostname
cisco.ios.ios_config:
lines: hostname {{ inventory_hostname }}

- name: configure DNS
cisco.ios.ios_config:
lines: ip name-server {{ dns }}

다음으로 vars/main.yml 파일에 변수를 작성한다.

$ vi vars/main.yml

---
# vars file for test-demo

dns: "8.8.8.8 8.8.4.4"

마지막으로, 원래의 앤시블 플레이북에서 tasks 와 var 섹션을 제거하고 roles 이름을 가지는 roles 키워드를 추가한다. 여기서는 test-demo로 한다.
플레이북은 아래와 같아진다.

$ cat dns_playbook.yml
---
- name: configure cisco switches
hosts: switches
connection: ansible.netcommon.network_cli
gather_facts: no

roles:
- test-demo

요약하면, 이제 모두 3개의 디렉토리와 3개의 YAML 파일이 만들어졌다.
test-demo 폴더는 tasks와 vars 두개의 폴더를 가진다.
각 폴더에는 main.yml 파일이 있다. vars/main.yml은 dns_playbook.yml로 부터 이동한 변수들을 가진다.
tasks/main.yml 파일은 dns_playbook.yml로부터 이동한 작업을 가진다.
dns_playbook.yml 파일은 vars 와 tasks 를 직접 명시하는 대신 role을 호출하도록 변경되었다.
디렉토리 구조는 아래와 같다.

.
├── hosts.yml
├── dns_playbook.yml
└── test-demo
├── tasks
│   └── main.yml
└── vars
└── main.yml

플레이북을 실행하면 아래와 비슷한 결과를 볼 수 있다.

$ ansible-playbook dns_playbook.yml -i hosts.yml -l Support -k
SSH password:

PLAY [configure cisco switches] ********************************************************************************

TASK [test-demo : configure hostname] **************************************************************************
[WARNING]: To ensure idempotency and correct diff the input configuration lines should be similar to how they
appear if present in the running configuration on device
ok: [Support]

TASK [test-demo : configure DNS] *******************************************************************************
changed: [Support]

PLAY RECAP *****************************************************************************************************
Support : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0

위의 결과에서 보면 각 task 에 role 이름이 추가된다.(test-demo)
이것은 여러 role을 가지는 플레이북을 실행할 때, 작업이 호출되는 위치를 파악하는데 도움이된다.
이 플레이북은 처음 시작한 단일 플레이북에 대해 같은 작업을 하므로 changed=0이 되고 ok를 반환해야하나, 위의 경고문때문인지 changed=1을 반환했다.
실제 장비에 접속해 확인해 보면 변경된 것은 없다.(이미 변경했으므로)

플레이북에 의해 cisco ios 스위치는 아래처럼 설정되었다.

Support#sh run | include hostname
hostname Support
Support#sh run | include name-server
ip name-server 8.8.8.8
ip name-server 8.8.4.4

이것이 앤시블 role을 해체된 플레이북으로 간단히 생각할수 있는 이유이다. role은 단순하고 효과적이며 재사용가능하다.
이제, 다른 사용자는 하드코딩된 플레이북을 만드는 대신 test-demo role을 포함하기만 하면 된다.

변수 우선순위

DNS서버를 변경하려면 무엇을 해야하나? 아마도 role 구조의 vars/main.yml 을 변경하지 않아도 된다.
앤시블은 여러 위치에 주어진 플레이에 대한 변수를 지정할 수 있다. 자세한것은 변수사용에 관한 문서를 참고하면 된다.
실제로, 변수를 지정할 수 있는곳이 21개나 된다.
이 리스트는 살짝 보기에 압도적으로 보일 수 있으나 대부분은 우선순위가 가장 낮은 변수의 위치와 가장높은 변수를 전달하는 방법만 알고 있다.

가장 낮은 우선순위

가장 낮은 우선순위는 role의 defaults 디렉토리다. 이것은 잠재적으로 변수를 지정할 수 있는 다른 20개의 위치가 모두 default 보다 높은 우선순위를 가진다는것을 뜻한다.
test-demo role의 vars에 가장낮은 우선순위를 즉시 부여하려면 vars 디렉토리를 default로 변경한다.

$ cd test-demo
$ mv vars/main.yml defaults/

이제 플레이북(dns_playbook.yml)에 vars 항목을 추가하여 기본 동작을 재 정의한다.(dns 변수는 8.8.8.8 8.8.4.4로 설정되어 있음)
플레이북에 dns를 1.1.1.1로 설정한다.

$ vi dns_playbook.yml
---
- name: configure cisco switches
hosts: switches
connection: ansible.netcommon.network_cli
gather_facts: no
vars:
dns: 1.1.1.1

roles:
- test-demo

플레이북을 실행하여 name-server를 업데이트한다.

$ ansible-playbook dns_playbook.yml -i hosts.yml -l Training_Main -k
SSH password:

PLAY [configure cisco switches] ********************************************************************************

TASK [test-demo : configure hostname] **************************************************************************
[WARNING]: To ensure idempotency and correct diff the input configuration lines should be similar to how they
appear if present in the running configuration on device
changed: [Training_Main]

TASK [test-demo : configure DNS] *******************************************************************************
changed: [Training_Main]

PLAY RECAP *****************************************************************************************************
Training_Main : ok=2 changed=2 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0

해당 스위치에서 설정을 확인해 보면,

Training_Main#show run | inc name-server
ip name-server 1.1.1.1

결과를 보면, 우선순위가 가장 낮은 defaults 에 설정된 값보다 우선순위가 더 높은 플레이북에 설정된 값이 적용된 것을 확인 할 수 있다.

가장 높은 우선순위

role내의 defaults 디렉토리아래 변수를 설정하면 항상 가장 낮은 우선순위를 가지지만 -e 또는 –extra-vars= 와 함께 vars를 명시하면 항상 가장 높은 우선순위를 가지게된다.
-e 옵션을 사용하여 플레이북을 다시 실행하면 role이나 플레이북에 정의된 변수가 모두 재정의된다.

일단, 장비에 접속하여 설정된 name-server를 삭제한다.

Training_Main#conf t
Enter configuration commands, one per line. End with CNTL/Z.
Training_Main(config)#no ip name-server 1.1.1.1
Training_Main(config)#end

그리고, -e 옵션을 주고 플레이북을 실행한다.

$ ansible-playbook dns_playbook.yml -i hosts.yml -l Training_Main -k -e "dns=192.168.0.1"
SSH password:

PLAY [configure cisco switches] ********************************************************************************

TASK [test-demo : configure hostname] **************************************************************************
[WARNING]: To ensure idempotency and correct diff the input configuration lines should be similar to how they
appear if present in the running configuration on device
ok: [Training_Main]

TASK [test-demo : configure DNS] *******************************************************************************
changed: [Training_Main]

PLAY RECAP *****************************************************************************************************
Training_Main : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0

장비 접속하여 확인해보면,

Training_Main#sh run | inc name-server
ip name-server 192.168.0.1

어떻게 이것이 유용할까? 왜 관심가져야 할까? 여분의 변수는 보통 네트워크 운영자가 기본값을 재설정하는데 사용한다.
이에 대한 강력한 예는 RedHat Ansible Tower and the Survey 기능이다. 그것은 웹 UI를 통해서 네트워크 운영자에게 웹포맷으로 매개변수를 입력하라는 메시지를 표시할 수 있다.
이것은 기술자가 아닌 플레이북 작성자가 웹브라우져를 사용하여 간단히 플레이북을 실행할 수 있도록한다.
자세한것은 Ansible Tower Job Template Surveys를 참고하면 된다.

설치된 role의 업데이트

role에 대한 앤시블 갤럭시(Ansible Galaxy) 페이지는 모든 유효한 버전의 목록이 있다.
로컬에 설치된 role을 새버전이나 다른 버전으로 업데이트하려면 ansible-galaxy install 명령을 버전과 –force 옵션을 함께 사용하면 된다.
또한 이 버전을 지원하려면 연관된 role을 수동으로 업데이트 해야한다. 연관된 role의 최소 버전 요구사항은 Galaxy의 role ReadMe 탭을 참조하면 된다.

$ ansible-galaxy install mynamespace.my_role,v2.7.1 --force

참고문서: https://docs.ansible.com/ansible/latest/network/getting_started/network_roles.html#a-sample-dns-playbook

답글 남기기

Your email address will not be published.