어쩌다 IT
article thumbnail
반응형

리뷰 (Review)

더보기

Playbook의 Play 코드 구조

  • 타겟 부분
    • Play에 대한 공통 정보 
    • name, hosts, user, become, gather_facts, ...
  • 변수 부분 (선택 사항)
  • 테스크 부분
    • Task 목록, Managed node에서 수행할 모듈 명시

 

Play에서 변수(Variable) 내용 출력

  • debug 모듈 사용
  • 변수 내용을 사용하고자 할 때는 "{{변수명}}" 형식으로 사용
  • var 또는 msg 파라미터를 이용하여 변수 내용 출력

 

Task 결과 변수 저장

  • Task 동작 결과에 따라 변수를 설정할 때는 모듈을 호출할 때 register 사용하여 변수 생성
  • error 발생하더라도 무시하고자 하면 ignore_errors: True 사용

 

팩트 (Facts)

  • Managed node에 대한 정보
  • gather_facts를 사용하여 팩트 수집 유무 결정

Playbook 확장

 

제어 구조

  • 순차 구조 - 명령이 기술된 순서로 순차적으로 수행하는 구조
  • 선택 구조 - 조건에 따라 명령의 실행 순서를 변경할 수 있는 구조
  • 반복 구조 - 특정 명령을 일정 횟수 동안 반복해서 수행하는 구조
  • Ansible Playbook에 선택문 / 반복문은 모듈 키워드 형태를 사용하여 적용

반복문

  • Task를 반복해서 동작시킬 때 사용
  • 모듈의 키워드(keyword, Attribute 성격)로 사용
  • with_* 키워드와 loop 키워드 사용
    • with_items
    • with_nested
    • with_sequence
  • 패키지 관련 모듈은 반복문을 사용하지 않는 것을 권장
  • 반복문에서 제공되는 목록을 참조하는 변수명은 항상 item 사용
더보기
---
- name: loop
  hosts: private
  gather_facts: Flase

  tasks:
    - name: loop basic 1
      debug:
        msg: "{{item}}"
      loop:
        - a
        - b
        - c

    - name: loop basic 2
      debug:
        msg: "{{item.user}} [ {{item.group}} ]"
      loop:
        - user: user1
          group: group1
        - user: user2
          group: group2

    - name: none loop 2-1
      debug:
        msg: "user1 [group1]"

    - name: none loop 2-2
      debug:
        msg: "user2 [group2]"
[ec2-user@ip-12-12-12-12 work-ansible]$ ansible-playbook loop.yml -i ./hosts

PLAY [loop] *****************************************************************************************************************

TASK [loop basic 1] *********************************************************************************************************
ok: [host3] => (item=a) => {
    "msg": "a"
}
ok: [host3] => (item=b) => {
    "msg": "b"
}
ok: [host3] => (item=c) => {
    "msg": "c"
}

TASK [loop basic 2] *********************************************************************************************************
ok: [host3] => (item={u'group': u'group1', u'user': u'user1'}) => {
    "msg": "user1 [ group1 ]"
}
ok: [host3] => (item={u'group': u'group2', u'user': u'user2'}) => {
    "msg": "user2 [ group2 ]"
}

TASK [none loop 2-1] ********************************************************************************************************
ok: [host3] => {
    "msg": "user1 [group1]"
}

TASK [none loop 2-2] ********************************************************************************************************
ok: [host3] => {
    "msg": "user2 [group2]"
}

PLAY RECAP ******************************************************************************************************************
host3                      : ok=4    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

[ec2-user@ip-12-12-12-12 work-ansible]$

---
- name: create file
  hosts: private
  gather_facts: Flase

  vars:
    file_path: /home/ec2-user/work_touch
    id: ansible

  tasks:
    - name: create directory
      file:
        path: "{{file_path}}"
        state: directory

    - name: confime file
      stat:
        path: "{{file_path}}/{{id}}.txt"
      register: result
    - name: create file
      file:
        path: "{{file_path}}/{{item}}.txt"
        state: touch
      loop:
        - "{{id}}1"
        - "{{id}}2"
        - "{{id}}3"
[ec2-user@ip-12-12-12-12 work-ansible]$ ansible-playbook create_file.yml -i ./hosts

PLAY [create file] **********************************************************************************************************

TASK [create directory] *****************************************************************************************************
ok: [host3]

TASK [confime file] *********************************************************************************************************
ok: [host3]

TASK [create file] **********************************************************************************************************
changed: [host3] => (item=ansible1)
changed: [host3] => (item=ansible2)
changed: [host3] => (item=ansible3)

PLAY RECAP ******************************************************************************************************************
host3                      : ok=3    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

[ec2-user@ip-12-12-12-12 work-ansible]$ ansible private -m shell -a "ls -lF /home/ec2-user/work_touch" -i ./hosts
host3 | CHANGED | rc=0 >>
total 0
-rw-rw-r-- 1 ec2-user ec2-user 0 Sep 23 02:40 ansible1.txt
-rw-rw-r-- 1 ec2-user ec2-user 0 Sep 23 02:40 ansible2.txt
-rw-rw-r-- 1 ec2-user ec2-user 0 Sep 23 02:40 ansible3.txt
[ec2-user@ip-12-12-12-12 work-ansible]$

조건문 (선택문)

  • Task가 특정 조건에만 작업을 수행하도록 구성할 때 사용
  • when 키워드 사용
  • 조건에 대한 표현식을 테스트문 또는 필터 사용
  • 조건문에서 변수를 참조할 때 "{{변수명}}" 사용하지 않고 바로 변수명 사용
  • 조건 결과가 True인 경우에 Task 실행
  • 테스트문
    • 테스트는 표현식을 평가하고 True / False 반환
    • when: 변수 연산
      • 변수를 테스트하기 위한 테스트문
      • <변수> is failed - 작업 실패
      • <변수> is changed - 작업 성공적 실행 및 변경 수행
      • <변수> is succeeded - 작업 성공적 실행
      • <변수> is skipped - 조건문에 의해 실행되지 않음
  • 필터
    • when: <변수 [| (자료형)]> <조건 연산자> 값
    • <변수 [| (자료형)]> 표현은 변수형 변환을 의미하고 | 다음에 형 변환을 원하는 자료형 기입
    • 숫자형으로 변환할 때 사용
    • 조건 연산자 - >, <, >=, <=, ==, !=
더보기
---
- name: condition test
  hosts: private

  tasks:
    - name: shell command - /usr/bin/foo
      shell: python3 --version
      register: result
      ignore_errors: True

    - debug:
        msg: "{{result.stderr}}"
      when: result is failed
    
    - debug:
        msg: "{{result.stdout}}"
      when: result is changed
[ec2-user@ip-12-12-12-12 work-ansible]$ ansible-playbook cond.yml -i ./hosts

PLAY [condition test] *******************************************************************************************************

TASK [Gathering Facts] ******************************************************************************************************
ok: [host3]

TASK [shell command - /usr/bin/foo] *****************************************************************************************
changed: [host3]

TASK [debug] ****************************************************************************************************************
skipping: [host3]

TASK [debug] ****************************************************************************************************************
ok: [host3] => {
    "msg": "Python 3.7.10"
}

PLAY RECAP ******************************************************************************************************************
host3                      : ok=4    changed=1    unreachable=0    failed=0    skipped=1    rescued=0    ignored=0   

[ec2-user@ip-12-12-12-12 work-ansible]$

---
- name: condition test
  hosts: private

  tasks:
    - name: shell command
      # shell: python3 --version
      shell: py3 --version		# error 발생 시키기 위함
      register: result
      ignore_errors: True

    - debug:
        var: ansible_facts
    
    - debug:
        msg: "{{result.stderr}}"
      when: result is failed
    
    - debug:
        msg: "{{result.stdout}}"
      when: result is changed
[ec2-user@ip-12-12-12-12 work-ansible]$ ansible-playbook cond.yml -i ./hosts

PLAY [condition test] *******************************************************************************************************

TASK [Gathering Facts] ******************************************************************************************************
ok: [host3]

TASK [shell command] ********************************************************************************************************
fatal: [host3]: FAILED! => {"changed": true, "cmd": "py3 --version", "delta": "0:00:00.038310", "end": "2022-09-23 03:38:35.610204", "msg": "non-zero return code", "rc": 127, "start": "2022-09-23 03:38:35.571894", "stderr": "/bin/sh: py3: command not found", "stderr_lines": ["/bin/sh: py3: command not found"], "stdout": "", "stdout_lines": []}
...ignoring

TASK [debug] ****************************************************************************************************************
ok: [host3] => {
    "msg": "/bin/sh: py3: command not found"
}

TASK [debug] ****************************************************************************************************************
ok: [host3] => {
    "msg": ""
}

PLAY RECAP ******************************************************************************************************************
host3                      : ok=4    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=1   

[ec2-user@ip-12-12-12-12 work-ansible]$

Include (포함)

  • Playbook의 내용이 많아지거나 복잡한 경우 더 작은 단위로 나누면 관리 편의성이 높아진다.
  • 모듈식으로 여러 개의 Playbook을 Main Playbook에 결합하거나 파일의 Task를 Play에 포함시킬 수 있다.
  • 이와 같은 방식으로 Playbook을 모듈로 나누면 재사용성이 높아진다. (모듈화)
  • Ansible에서 파일이나 role을 특정 Playbook에 읽어 들일 때 import / incloude 2가지 방법 중 하나를 사용할 수 있다.
    • import - static(정적, 고정적) re-use
      • role, task, Playbook 등을 Playbook에 정적으로 포함
      • Ansible은 읽어 들인 파일이나 role 등을 최상위 Playbook에서 작업 실행하기 전에 사전 처리한다.
      • import 된 Playbook은 최상위 Playbook이 되며 다른 task에 영향을 받지 않는다.
      • import_playbook: <playbook 파일명>으로 사용
    • include - dynamic(동적, 유동적) re-use
      • role, task, Playbook 등을 Playbook에 동적으로 포함
      • include 된 콘텐츠는 최상위 Playbook의 이전 작업의 결과에 영향을 받는다.
      • 최상위 Playbook의 실행 결과에 따라 실행될 수도 안 될 수도 있다.
      • include: <playbook 파일명>로 사용
더보기
### common.yml ###
---
- name: Install Web Server
  hosts: private

  tasks:
  - name: Collect only selected facts
    setup:
      filter:
        - 'ansible_distribution'

  - debug:
      var: ansible_facts
...

### webserver.yml ###
---
- import_playbook: common.yml

- name: Install Web Server
  hosts: private
  become: yes
  gather_facts: False

  tasks:
    - name: Ubuntu - Install Apache2
      apt:
        upgrade: yes
        update_cache: yes
        name: apache2
        state: present
      ignore_errors: True
      when: ansible_facts['distribution'] == "Ubuntu"
  
    - name: Amazon Linux - Install httpd
      yum:
        name: httpd
        state: present
      when: ansible_facts['distribution'] == "Amazon"
...

### install_pack_web.yml ###
---
- include: webserver.yml
...

Handler

  • 참고 자료
  • Handler는 함수(function)와 비슷한 성격 - 단위 기능 실행
  • Task가 할 수 있는 일을 똑같이 할 수 있다.
  • Playbook의 Task에서 Handler를 호출하게 되면 해당 Handler가 호출되어 실행되는 방식으로 동작
  • 반복되는 동작(Task)에 대하여 별도의 Handler로 정의
  • Handler 정의
    • 정의 - Handlers 섹션에 Task 정의, Tasks 섹션과 같은 level
    • 호출 - Handler 호출은 notify: 에 해당 Handler 이름 명시, 모듈과 같은 level
  • Handler는 이름으로 호출되므로 noitify에 기술된 이름이 실제 Handler 섹션에 정의된 이름과 같아야 한다.
  • 동일한 Handler에 대해서 여러번 호출되어도 한번만 실행
  • 변수 사용 시에는 include_vars 모듈 사용
더보기
---
- name: Verify apache installation
  hosts: public
  become: yes
  gather_facts: False

  tasks:
    - name: Ensure apache is at the latest version
      yum:
        name: httpd
        state: latest

    - name: Write the apache config file
      template:
        src: ./httpd.j2
        dest: /etc/httpd.conf2
      notify:
      - Restart apache

    - name: Ensure apache is running
      service:
        name: httpd
        state: started

  handlers:
    - name: Restart apache
      service:
        name: httpd
        state: restarted
[ec2-user@ip-12-12-12-12 work-ansible]$ ansible-playbook handler.yml -i ./hosts

PLAY [Verify apache installation] *******************************************************************************************

TASK [Ensure apache is at the latest version] *******************************************************************************
changed: [host2]
changed: [host1]

TASK [Write the apache config file] *****************************************************************************************
changed: [host1]
changed: [host2]

TASK [Ensure apache is running] *********************************************************************************************
changed: [host2]
changed: [host1]

RUNNING HANDLER [Restart apache] ********************************************************************************************
changed: [host1]
changed: [host2]

PLAY RECAP ******************************************************************************************************************
host1                      : ok=4    changed=4    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
host2                      : ok=4    changed=4    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

[ec2-user@ip-12-12-12-12 work-ansible]$ ansible public -m shell -a "ls -lF /etc/httpd.*" -i ./hosts
host1 | CHANGED | rc=0 >>
-rw-r--r-- 1 root root 19 Sep 23 06:41 /etc/httpd.conf2
host2 | CHANGED | rc=0 >>
-rw-r--r-- 1 root root 19 Sep 23 06:41 /etc/httpd.conf2
[ec2-user@ip-12-12-12-12 work-ansible]$

Roles

  • Roles는 include의 확장 개념
  • 역할에 따라 roles 폴더에 필요한 파일들을 별도로 생성하여 사용
  • role에서 다른 role을 포함할 수 있고 변수 전달도 가능
  • 역할에 따른 role을 작성해서 관리함으로써 편의성과 재사용성을 높일 수 있는 프로젝트 관리 방법
  • role 관리 방법
    • roles 이름의 폴더 생성
    • roles 폴더 아래 필요한 폴더 추가 생성 - files, handlers, tasks, templates, vars, meta, ...
      • tasks/main.yml - 역할 실행 task 저장 파일
      • handlers/main.yml - handler 저장 파일
      • vars/main.yml - 변수 저장 파일
    • Playbook에 적용하고 싶은 role을 roles 섹션에 추가

TIF

Include 까지 실습은 잘 따라갔는데

Role 로 넘어가면서 어디서부터 꼬였는지 중간중간에 발생하는 에러때문에 따라가지를 못했다.

흔들린 집중력도 문제거니와... 오늘은 금요일이고... 국대 축구하니까...

오늘만...

 

 

2022. 09. 23 에 작성된 글입니다.

반응형
profile

어쩌다 IT

@jwlish

포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!