728x90

핸들러


핸들러란

처리를 도와주는 역할

  • 작업을 도와줌
  • 핸들러를 사용하면 불필요하게 실행되는 태스크를 줄일 수 있음

 

핸들러 동작 조건

  • 전 단계에서 작업이 정상적으로 실행되고
  • 변경 사항이 발생한 경우에 동작

 


 

핸들러 동작 과정

nginx_install_w_handlers.yml

  • nginx 설치를 위한 메인 코드에 핸들러 추가
---
- name: Install nginx on the nodes
  hosts: nodes
  become: yes
  vars:
    lnx_name: "{{ 'CentOS' if ansible_distribution == 'CentOS'
                   else 'Ubuntu' if ansible_distribution == 'Ubuntu'
                   else 'Just Linux' }}"

  tasks:
    - name: nginx for any linux
      include_tasks: "{{ lnx_name }}.yml"

  handlers:
    - name: restart nginx web server
      service: name=nginx state=restarted

 

CentOS.yml

  • nginx 설치에 핸들러의 실행을 요청하는 옵션 추가
  • notify: 핸들러가 동작할 경우 실행되는 명령
- name: install epel-release
  action: "{{ ansible_pkg_mgr }} name=epel-release state=latest"
- name: install nginx web server
  action: "{{ ansible_pkg_mgr }} name=nginx state=present"
- name: upload default index.html for web server
  get_url: url=https://www.nginx.com dest=/usr/share/nginx/html/ mode=0644
  notify:
    - restart nginx web server

 

Ubuntu.yml

  • nginx 설치에 핸들러의 실행을 요청하는 옵션 추가
  • 우분투 노드에서 nginx.com url은 오류가 발생하므로 apache.com으로 변경
- name: install nginx web server
  action: "{{ ansible_pkg_mgr }} name=nginx state=present update_cache=yes"
- name: upload default index.html for web server
  get_url: url=https://www.apache.com dest=/usr/share/nginx/html/ 
           mode=0644 validate_certs=no
  notify:
    - restart nginx web server

 

플레이북 실행

  • 첫 번째 실행
  • 핸들러가 동작함
[vagrant@ansible-server install]$ anp nginx_install_w_handlers.yml

 

 

  • 두 번째 실행
  • 핸들러가 실행되지 않음 > 변경 사항이 없기 때문에

728x90
728x90

if 조건문


if 조건문

- 기존의 when 조건문에 비해 코드가 간결하고, 확장성이 뛰어남

- 하나의 태스크로 수행이 가능하여 보다 효율적임

- skipping 태스크를 없앨 수 있음 (효율적인 태스크 실행)

 

 

if 조건문을 이용한 태스크 실행

1) CentOS.yml

- name: install epel-release
  action: "{{ ansible_pkg_mgr }} name=epel-release state=latest"
- name: install nginx web server
  action: "{{ ansible_pkg_mgr }} name=nginx state=present"
- name: upload default index.html for web server
  get_url: url=https://www.nginx.com dest=/usr/share/nginx/html/ mode=0644
- name: start nginx web server
  service: name=nginx state=started

 

2) Ubuntu.yml

- name: install nginx web server
  action: "{{ ansible_pkg_mgr }} name=nginx state=present update_cache=yes"
- name: upload default index.html for web server
  get_url: url=https://www.apache.com dest=/usr/share/nginx/html/ 
           mode=0644 validate_certs=no

 

3) nginx_install_w_if.yml

---
- name: Install nginx on the nodes
  hosts: nodes
  become: yes
  vars:
    lnx_name: "{{ 'CentOS' if ansible_distribution == 'CentOS'
                   else 'Ubuntu' if ansible_distribution == 'Ubuntu'
                   else 'Just Linux' }}"

  tasks:
    - name: nginx for any linux
      include_tasks: "{{ lnx_name }}.yml"

 

4) 실행

skipping 태스크를 확인할 수 없음 > 태스크의 낭비를 줄임

[vagrant@ansible-server install]$ anp nginx_install_w_if.yml

 

 

728x90
728x90

운영체제를 구분하여 한 번에 설치


include_tasks란?

- 각 리눅스에 필요한 태스크를 정의한 yml 파일을 호출하여 실행

- 구조적인 태스크 관리가 가능함

 

include_tasks를 사용하는 이유

- 불필요하게 실행되는 태스크들을 관리하기 위해서

 => when을 사용하여 자동으로 노드의 종류를 구분하여 설치하는 경우 CentOS 태스크에서는 우분투의 태스크가 불필요하게 실행되고, Ubuntu 태스크에서는 CentOS의 태스크가 불필요하게 실행되므로 include_tasks를 이용

 

include_tasks를 사용하지 않고 웹 서버 설치 (nginx, apache)

CentOS 태스크가 실행될 때 > Ubuntu 노드들에 불필요한 태스크가 실행되는 것을 확인할 수 있음

 

 

Ubuntu 태스크가 실행될 때 > CentOS 노드들에 불필요한 태스크가 실행되는 것을 확인할 수 있음

 

 

include_tasks를 사용하여 웹 서버 설치 (nginx, apache)

1) CentOS.yml

- name: install epel-release
  action: "{{ ansible_pkg_mgr }} name=epel-release state=latest"
- name: install nginx web server
  action: "{{ ansible_pkg_mgr }} name=nginx state=present"
- name: upload default index.html for web server
  get_url: url=https://www.nginx.com dest=/usr/share/nginx/html/ mode=0644
- name: start nginx web server
  service: name=nginx state=started

 

2) Ubuntu.yml

- name: install nginx web server
  action: "{{ ansible_pkg_mgr }} name=nginx state=present update_cache=yes"
- name: upload default index.html for web server
  get_url: url=https://www.apache.com dest=/usr/share/nginx/html/ 
           mode=0644 validate_certs=no

 

3) nginx_install_w_include_tasks.yml

---
- name: Install nginx on the nodes
  hosts: nodes
  become: yes

  tasks:
    - name: nginx for CentOS
      include_tasks: CentOS.yml
      when: ansible_distribution == 'CentOS'
    
    - name: nginx for Ubuntu
      include_tasks: Ubuntu.yml
      when: ansible_distribution == 'Ubuntu'

 

4) 설치

[vagrant@ansible-server install]$ anp nginx_install_w_include_tasks.yml

 

CentOS 태스크가 실행될 때 > include를 사용하여 작성한 CentOS.yml 파일을 호출함 > CentOS 노드들에서만 태스크가 실행 됨

 

 

Ubuntu 태스크가 실행될 때 > include를 사용하여 작성한 Ubuntu.yml 파일을 호출함 > Ubuntu 노드들에서만 태스크가 실행 됨

 

 

웹 브라우저에서 확인

CentOS 노드로 접속 172.30.1.101

 

 

Ubuntu 노드로 접속 172.30.1.201

 

 

설치한 웹 서버 삭제

1) CentOS_remove.yml

- name: remove epel-release
  action: "{{ ansible_pkg_mgr }} name=epel-release state=absent"
- name: remove nginx web server
  action: "{{ ansible_pkg_mgr }} name=nginx state=absent"

 

2) Ubuntu_remove.yml

  1 - name: remove nginx web server
  2   action: "{{ ansible_pkg_mgr }} name=nginx state=absent autoremove=yes"

 

3) nginx_remove_w_include_tasks.yml

  1 ---
  2 - name: Remove nginx on the nodes
  3   hosts: nodes
  4   become: yes
  5
  6   tasks:
  7     - name: nginx for CentOS
  8       include_tasks: CentOS_remove.yml
  9       when: ansible_distribution == 'CentOS'
 10
 11     - name: nginx for Ubuntu
 12       include_tasks: Ubuntu_remove.yml
 13       when: ansible_distribution == 'Ubuntu'
 14
~

 

4) 삭제

[vagrant@ansible-server remove]$ anp nginx_remove_w_include_tasks.yml

728x90
728x90

when 조건을 사용한 nginx 설치


when 조건 사용

- when 조건을 사용하면, 코드가 스스로 앤서블 노드의 운영체제를 파악하고 조건에 맞는 패키지 관리자를 호출하여 nginx를 설치함

- facts에서 제공하는 ansible_pkg_mgransible_distribution 인자 값을 사용하여 운영체제 정보 확인

 

 

 

1. nginx_install_w_when.yml 파일 실행

CentOS는 CentOS에 해당하는 태스크를 수행하고, 우분투는 우분투에 해당하는 태스크를 수행하는 것을 확인할 수 있음

---
- name: Install nginx on the nodes
  hosts: nodes
  become: yes

  tasks:  
    - name: install epel-release for CentOS
      action: "{{ ansible_pkg_mgr }} name=epel-release state=latest"
      when: ansible_distribution == 'CentOS'
	  
    - name: install nginx web server for CentOS
      action: "{{ ansible_pkg_mgr }} name=nginx state=present"
      when: ansible_distribution == 'CentOS'

    - name: upload default index.html for web server
      get_url: url=https://www.nginx.com dest=/usr/share/nginx/html/ mode=0644
      when: ansible_distribution == 'CentOS'
	  
    - name: start nginx web server
      service: name=nginx state=started
      when: ansible_distribution == 'CentOS'
	  
    - name: install nginx web server for Ubuntu
      action: "{{ ansible_pkg_mgr }} name=nginx state=present update_cache=yes"
      when: ansible_distribution == 'Ubuntu'

    - name: upload default index.html for web server
      get_url: url=https://www.nginx.com dest=/usr/share/nginx/html/ 
               mode=0644 validate_certs=no
      when: ansible_distribution == 'Ubuntu'

 

2. 주의: 우분투 버전 및 nginx.com의 설정에 따라 에러가 발생할 수 있음

  => get_url의 url=https://www.nginx.com을 url=http://www.apache.com으로 변경

 

 

3. url 수정 부분

 27     - name: upload default index.html for web server
 28       get_url: url=https://www.apache.com dest=/usr/share/nginx/html/
 29                mode=0644 validate_certs=no
 30       when: ansible_distribution == 'Ubuntu'

 

4. 정상 실행 확인

 

CentOS가 설치된 노드

 

Ubuntu가 설치된 노드

 

5. 설치한 nginx 삭제

nginx_remove_w_when.yml 파일 실행

[vagrant@ansible-server ~]$ anp nginx_remove_w_when.yml
---
- name: Remove nginx on the nodes
  hosts: nodes
  become: yes

  tasks:
    - name: remove epel-release for CentOS
      action: "{{ ansible_pkg_mgr }} name=epel-release state=absent"
      when: ansible_distribution == 'CentOS'
	  
    - name: remove nginx web server for CentOS
      action: "{{ ansible_pkg_mgr }} name=nginx state=absent"
      when: ansible_distribution == 'CentOS'
  
    - name: remove nginx web server
      action: "{{ ansible_pkg_mgr }} name=nginx state=absent autoremove=yes"
      when: ansible_distribution == 'Ubuntu'

 

728x90
728x90

FACT(s)


FACT(s)란

- 일반적으로 구성 요소의 의미로 쓰여짐

- 호스트에 따라 동적으로 할당되는 변수 인자

- 앤서블 노드들에 다양한 정보를 미리 정의해 둔 변수

- 앤서블은 기본적으로 setup 모듈을 통해 facts를 수집함 -> 'gather_facts: no'는 facts 수집을 하지 않겠다는 의미 -> 성능 향상

 

FACT(s) 사용법

facts 값 확인을 위한 실습 코드 실행

git clone을 이용해 코드 다운로드

https://github.com/sysnet4admin/_Book_Ansible.git

 

facts.yml 파일이 있는 디렉토리로 이동

[vagrant@ansible-server ~]$ cd _Book_Ansible/
[vagrant@ansible-server _Book_Ansible]$ ls
부록
2. 앤서블을 체험하기
3. 베이그런트를 통해서 앤서블의 실습 환경 구성하기
4. 리눅스와 윈도우를 앤서블을 통해서 관리하기
5. 네트워크 운영체제를 앤서블을 통해서 관리하기
6. 플레이북을 효율적으로 작성하기
7. 재사용이 가능한 플레이북 만들기
README.md
[vagrant@ansible-server _Book_Ansible]$ cd 6.\ 플레이북을\ 효율적으로\ 작성하기/
[vagrant@ansible-server 6. 플레이북을 효율적으로 작성하기]$ ls
6.1.1. 기본 실습 환경을 구성하기
6.1.2. known_hosts를 자동으로 등록하기
6.1.3. authorized_keys를 자동으로 등록하기
6.2.1. 숨겨왔던 facts의 정체
6.2.2. when 조건
6.2.3. include_tasks 구문
6.2.4. if 조건
6.3.1. NFS 구성을 효율적으로 하기
6.3.2. 넥서스 스위치의 구성 파일을 효율적으로 백업하기
6.3.3. Cumulus로 접속하기 위한 인증을 자동화하기
6.3.4. Cumulus 노드 간에 OSPF를 빠르고 정확하게 구성하기
[vagrant@ansible-server 6. 플레이북을 효율적으로 작성하기]$ cd 6.2.1.\ 숨겨왔던\ facts의\  정체/
[vagrant@ansible-server 6.2.1. 숨겨왔던 facts의 정체]$ ls
facts_collector.yml  facts_output  facts.yml
[vagrant@ansible-server 6.2.1. 숨겨왔던 facts의 정체]$

 

facts.yml 코드 확인

[vagrant@ansible-server 6.2.1. 숨겨왔던 facts의 정체]$ vi facts.yml

 

facts를 수집하도록 gather_facts: no 주석 처리

 

facts.yml 파일을 실행하여 IP 주소가 각 노드에 맞게 출력되는지 확인

[vagrant@ansible-server 6.2.1. 숨겨왔던 facts의 정체]$ anp facts.yml

 

setup 모듈을 호출하여 앤서블이 실행되는 노드들에 대한 facts를 수집하고 출력함

이 때, 화면상에 그대로 출력되어 가독성이 떨어지므로 리다이렉션을 이용해 파일로 저장

[vagrant@ansible-server 6.2.1. 숨겨왔던 facts의 정체]$ ans nodes -m setup > facts.txt

728x90
728x90

authorized_keys란

- 인증된 키

- 이미 사용 허가를 받아 믿을 수 있는 사용자

 

authorized_keys 적용 과정

1. 앤서블 서버에서 앤서블 노드로 접속 시도

2. 앤서블 노드의 ~/.ssh/authorized_keys 파일의 존재 확인

3. authorized_keys 파일에 해당 호스트의 접속 허가 정보가 저장되어 있다면  접속 허용

 

 

autopass.yml 파일 수정

1) vars: 추가

2) ssh-keygen for authorized_keys file과 input key for each node 부분 추가

  vars:
    ansible_password: vagrant
    - name: ssh-keygen for authorized_keys file
      command: "ssh-keygen -b 2048 -t rsa -f ~/.ssh/id_rsa -q -N ''"
      ignore_errors: yes
      run_once: true

    - name: input key for each node
      connection: ssh
      authorized_key:
        user: vagrant
        state: present
        key: "{{ lookup('file', '~/.ssh/id_rsa.pub') }}"

코드 전체

---
- name: Create authority between server and nodes
  hosts: nodes
  connection: local
  serial: 1
  gather_facts: no
  vars:
    ansible_password: vagrant

  tasks:
    - name: ssh-keyscan for known_hosts file
      command: /usr/bin/ssh-keyscan -t ecdsa {{ ansible_host }}
      register: keyscan

    - name: input key
      lineinfile:      
        path: ~/.ssh/known_hosts
        line: "{{ item }}"
        create: yes     
      with_items:
        - "{{ keyscan.stdout_lines }}"

    - name: ssh-keygen for authorized_keys file
      command: "ssh-keygen -b 2048 -t rsa -f ~/.ssh/id_rsa -q -N ''"
      ignore_errors: yes
      run_once: true

    - name: input key for each node
      connection: ssh
      authorized_key:
        user: vagrant
        state: present
        key: "{{ lookup('file', '~/.ssh/id_rsa.pub') }}"

 

vag_reconf.bat 파일 실행

PS C:\HashiCorp\udemy-ansible> .\vag_reconf.bat

 

 

-k 옵션과 암호 입력 없이 통신 확인 가능

ans nodes -m ping

728x90
728x90

known_hosts란

- 알려진 호스트

- 이미 알고 있어 확인하지 않아도 되는 호스트

 

Vagrantfile 파일 수정

Ansible Server 영역에 두 줄 추가

    cfg.vm.provision "file", source: "auto_pass.yml", destination: "auto_pass.yml"
    cfg.vm.provision "shell", inline: "ansible-playbook auto_pass.yml", privileged: false
  #================#
  # Ansible Server #
  #================#
  
  config.vm.define "ansible-server" do |cfg|
    cfg.vm.box = "centos/7"
    cfg.vm.provider "virtualbox" do |vb|
      vb.name = "Ansible-Server"
      end
    cfg.vm.host_name = "ansible-server"
    cfg.vm.network "public_network", ip: "172.30.1.100"
    cfg.vm.network "forwarded_port", guest: 22, host: 60010, auto_correct: true, id: "ssh"
    cfg.vm.synced_folder "../data", "/vagrant", disabled: true
    cfg.vm.provision "shell", inline: "yum install epel-release -y"
    cfg.vm.provision "shell", inline: "yum install ansible -y"
    cfg.vm.provision "file", source: "ansible_env_ready.yml", 
      destination: "ansible_env_ready.yml"
    cfg.vm.provision "shell", inline: "ansible-playbook ansible_env_ready.yml"
    cfg.vm.provision "file", source: "auto_pass.yml", destination: "auto_pass.yml"	# 추가
    cfg.vm.provision "shell", inline: "ansible-playbook auto_pass.yml", privileged: false	# 추가
  end

 

ansible_env_ready.yml 파일 수정

해당 부분 지우기

    - name: Generate sshkey
      become: yes
      become_user: vagrant
      shell: "{{ item }}"
      with_items:
        - "ssh-keyscan 172.30.1.101 >> ~/.ssh/known_hosts"
        - "ssh-keyscan 172.30.1.102 >> ~/.ssh/known_hosts"
        - "ssh-keyscan 172.30.1.103 >> ~/.ssh/known_hosts"
        - "ssh-keyscan 172.30.1.104 >> ~/.ssh/known_hosts"
        - "ssh-keyscan 172.30.1.105 >> ~/.ssh/known_hosts"
        - "ssh-keyscan 172.30.1.201 >> ~/.ssh/known_hosts"
        - "ssh-keyscan 172.30.1.202 >> ~/.ssh/known_hosts"
        - "ssh-keyscan 172.30.1.203 >> ~/.ssh/known_hosts"
        - "ssh-keyscan 172.30.1.204 >> ~/.ssh/known_hosts"
        - "ssh-keyscan 172.30.1.205 >> ~/.ssh/known_hosts"

 

auto_pass.yml 파일 생성

ansible_host: /etc/ansible/hosts 파일에 등록된 모든 호스트

keyscan.stdout_lines: keyscan 명령 실행 결과를 with_items를 이용해 지속적으로 출력함

  -> 출력 결과는 다시 ~/.ssh/known_hosts로 입력됨

 

---
- name: Create authority between server and nodes
  hosts: nodes
  connection: local
  serial: 1
  gather_facts: no

  tasks:
    - name: ssh-keyscan for known_hosts file
      command: /usr/bin/ssh-keyscan -t ecdsa {{ ansible_host }}
      register: keyscan

    - name: input key
      lineinfile:      
        path: ~/.ssh/known_hosts
        line: "{{ item }}"
        create: yes     
      with_items:
        - "{{ keyscan.stdout_lines }}"

 

vag_reconf.bat 실행

- known_hosts 자동 등록을 위해 생성한 auto_pass.yml 파일과 수정한 Vagranfile이 제대로 적용되는지 vag_reconf.bat 파일을 실행하여 테스트 진행

- 파일 실행 결과: 모든 가상 머신이 삭제되고 재생성되어 결과 마지막 부분에서 known_hosts를 자동으로 등록한 것을 확인할 수 있음

 

[ 배치 파일의 LF, CR ]

- 유닉스/리눅스 OS의 경우 유닉스 타입의 LF( Line Feed: 커서를 현재 행의 다음 행으로, 즉 아래로 이동 )를 사용함

- 윈도우 OS의 경우 CR( Carriage Return: 커서를 현재 행의 제일 좌측으로 이동 )과 LF를 동시에 사용함 > 따라서 해당 파일을 실행하려면 CRLF( 커서를 다음 줄, 그 줄의 시작 부분으로 이동) 타입으로 변경하고 저장해야 함

 

@echo off
setlocal 
set /p name=어느 vagrant를 재구성 및 시작하시겠습니까? ^
모두는 그냥 enter를 입력 하세요: || set name=default

if %name%==default (
	vagrant halt && vagrant destroy -f && vagrant up
) else (
    vagrant halt %name% && vagrant destroy %name% -f && vagrant up %name%
)
PS C:\HashiCorp\udemy-ansible> .\vag_reconf.bat

통신 확인

- 모든 노드에 ping이 앤서블을 통해서 전달된 것을 확인할 수 있음

PS C:\HashiCorp\udemy-ansible> vagrant ssh ansible-server
[vagrant@ansible-server ~]$ ans nodes -m ping -k
SSH password: # vagrant

728x90
728x90

아키텍처

 

 

아래 링크로 접속하여 파일을 모두 다운로드하고 vagrant up으로 실습 환경 구성

 

https://github.com/sysnet4admin/_Book_Ansible/tree/master/6.%20%ED%94%8C%EB%A0%88%EC%9D%B4%EB%B6%81%EC%9D%84%20%ED%9A%A8%EC%9C%A8%EC%A0%81%EC%9C%BC%EB%A1%9C%20%EC%9E%91%EC%84%B1%ED%95%98%EA%B8%B0/6.1.1.%20%EA%B8%B0%EB%B3%B8%20%EC%8B%A4%EC%8A%B5%20%ED%99%98%EA%B2%BD%EC%9D%84%20%EA%B5%AC%EC%84%B1%ED%95%98%EA%B8%B0

 

 

 

728x90

+ Recent posts