본문 바로가기

study/Ansible101 1기

Ansible101 1기 2주차 두번째

너무 길어서 포스팅을 나눠서 진행하겠습니다.

핸들러 및 작업 실패 처리

앤서블 모듈멱등(idempotent)이 가능하도록 설계되어 있습니다. 즉 플레이북을 여러 번 실행해도 결과는 항상 동일합니다. 또한 플레이 및 해당 작업은 여러 번 실행할 수 있지만, 해당 호스트는 원하는 상태로 만드는 데 필요한 경우에만 변경됩니다.

 

하지만 한 작업에서 시스템을 변경해야 하는 경우 추가 작업실행해야 할 수도 있습니다.

예를 들어 서비스의 구성 파일을 변경하려면 변경 내용이 적용되도록 서비스를 다시 로드해야 합니다.이때 핸들러는 다른 작업에서 트리거한 알림에 응답하는 작업이며, 해당 호스트에서 작업이 변경될 때만 핸들러통지합니다.

 

Handlers: running operations on change - https://docs.ansible.com/ansible/latest/playbook_guide/playbooks_handlers.html

 

핸들러는 사용하려면 notify 문을 사용하여 명시적으로 호출된 경우에만 사용할 수 있습니다. 또한 핸들러를 정의할 때는 같은 이름으로 여러 개의 핸드러를 정의하기보다는 각각의 고유한 이름을 사용하여 정의하는 것이 좋습니다.

 

1. 플레이북 생성 : rsyslog 재시작 태스크가 실행되면 notify 키워드를 통해 print msg라는 핸들러를 호출합니다. 핸들러는 handlers 키워드로 시작합니다.

~/my-ansible/handler-sample.yml

---
- hosts: tnode2
  tasks:
    - name: restart rsyslog
      ansible.builtin.service:
        name: "rsyslog"
        state: restarted
      notify:
        - print msg

  handlers:
    - name: print msg
      ansible.builtin.debug:
        msg: "rsyslog is restarted"

 

2. 실행: tnode2 노드에 rsyslog 서비스를 재시작하고, print msg라는 핸들러를 호출해 “rsyslog..” 메시지를 출력

 

ansible.builtin.apt 모듈 - https://docs.ansible.com/ansible/latest/collections/ansible/builtin/apt_module.html

ansible.builtin.dnf 모듈 - https://docs.ansible.com/ansible/latest/collections/ansible/builtin/dnf_module.html

Error handling in playbooks - https://docs.ansible.com/ansible/latest/playbook_guide/playbooks_error_handling.html

 

작업 실패를 무시할 수도 있습니다.

앤서블은 플레이 시 각 작업의 반환 코드를 평가하여 작업의 성공 여부를 판단합니다. 일반적으로 작업이 실패하면 앤서블은 이후의 모든 작업을 건너뜁니다.

하지만 작업이 실패해도 플레이를 계속 실행할 수 있습니다. 이는 ignore_errors라는 키워드로 구현할 수 있습니다.

 

1. 생성: apache3 패키지를 설치하는 작업을 추가하고 비교해보자

~/my-ansible/ignore-example-1.yml

---
- hosts : tnode1

  tasks:
    - name: Install apache3
      ansible.builtin.apt:
        name: apache3
        state: latest

    - name: Print msg
      ansible.builtin.debug:
        msg: "Before task is ignored"
        
        
        
~/my-ansible/ignore-example-2.yml
---
- hosts : tnode1

  tasks:
    - name: Install apache3
      ansible.builtin.apt:
        name: apache3
        state: latest
      ignore_errors: yes

    - name: Print msg
      ansible.builtin.debug:
        msg: "Before task is ignored"

 

 

작업 실패 후 핸들러 실행

앤서블은 일반적으로 작업이 실패하고 해당 호스트에서 플레이중단되면 이전 작업에서 알림을 받은 모든 핸들러실행되지 않습니다.

하지만 플레이북에 force_handlers: yes 키워드를 설정하면 이후 작업실패하여 플레이가 중단되어도 알림을 받은 핸들러가 호출됩니다.

 

1. 플레이북 생성 : hosts 아래 force_handlers: yes 를 추가하고, install apache2 태스크를 추가합니다

~/my-ansible/force-handler-1.yml

---
- hosts: tnode2

  tasks:
    - name: restart rsyslog
      ansible.builtin.service:
        name: "rsyslog"
        state: restarted
      notify:
        - print msg

    - name: install apache3
      ansible.builtin.apt:
        name: "apache3"
        state: latest

  handlers:
    - name: print msg
      ansible.builtin.debug:
        msg: "rsyslog is restarted"
        
        
my-ansible/force-handler-2.yml

---
- hosts: tnode2
  force_handlers: yes

  tasks:
    - name: restart rsyslog
      ansible.builtin.service:
        name: "rsyslog"
        state: restarted
      notify:
        - print msg

    - name: install apache3
      ansible.builtin.apt:
        name: "apache3"
        state: latest

  handlers:
    - name: print msg
      ansible.builtin.debug:
        msg: "rsyslog is restarted"

 

Error handling in playbooks - https://docs.ansible.com/ansible/latest/playbook_guide/playbooks_error_handling.html#defining-failure

ansible.builtin.fail 모듈 - https://docs.ansible.com/ansible/latest/collections/ansible/builtin/fail_module.html

 

작업 실패 조건 지정 : 셸 스크립트 보다는 모듈 사용 하자!

  • command 계열 모듈 사용 시
    • 앤서블에서 셸 스크립트를 실행한 뒤 결과로 실패 또는 에러 메시지를 출력해도, 앤서블에서는 작업이 성공했다고 간주합니다.
    • 어떤 명령이라도 실행된 경우에는 태스크 실행 상태를 항상 changed 로 한다.
    • 명령을 실행한 경우에 반환 코드가 0이 아니면 failed로 처리한다.
    • 이런 경우 failed_when 키워드를 사용하여 작업이 실패했음을 나타내는 조건을 지정할 수 있습니다
~/my-ansible/adduser-script.sh

# 사용자 추가하는 스크립트 파일 내용 확인
cat ~/my-ansible/Easy-Ansible/chapter_07.3/adduser-script.sh
cp ~/my-ansible/Easy-Ansible/chapter_07.3/adduser-script.sh adduser-script.sh
chmod +x adduser-script.sh
ls -l adduser-script.sh

# 해당 스크립트로 user1 생성해보기
## "passwd: unrecognized option '--stdin'" 에러는 암호 적용 부분에서 발생
sudo ./adduser-script.sh
sudo ./adduser-script.sh "user1" "qwe123"
tail -n 3 /etc/passwd
sudo userdel -rf user1

 

2. 사용자 추가하는 스크립트 파일을 tnode1에 복사 후 확인

# 사용자 추가하는 스크립트 파일을 tnode1에 복사
ansible -m copy -a 'src=/home/ubuntu/my-ansible/adduser-script.sh dest=/home/ubuntu/adduser-script.sh' tnode1

# 복사 확인
ssh tnode1 ls -l /home/ubuntu/
-rw-r--r-- 1 root root 846 Jan 13 22:09 adduser-script.sh

# 스크립트 실행 확인
ssh tnode1
---------------
sudo chmod +x adduser-script.sh
sudo ./adduser-script.sh
exit
---------------

 

3.  플레이북 생성 : sh 실행을 위해서 shell 모듈 사용 태스크를 사용

~/my-ansible/failed-when-1.yml

---
- hosts: tnode1

  tasks:
    - name: Run user add script
      ansible.builtin.shell: /home/ubuntu/adduser-script.sh
      register: command_result

    - name: Print msg
      ansible.builtin.debug:
        msg: "{{ command_result.stdout }}"

 

~/my-ansible/failed-when-2.yml

failed_when 조건식 : command_result.stdout 변수에 “Please…”라는 문자열이 있으면 작업을 실패(fail)로 처리하겠다는 의미
---
- hosts: tnode1

  tasks:
    - name: Run user add script
      ansible.builtin.shell: /home/ubuntu/adduser-script.sh
      register: command_result
      failed_when: "'Please input user id and password' in command_result.stdout"

    - name: Print msg
      ansible.builtin.debug:
        msg: "{{ command_result.stdout }}"

 

4.  실행

# 실행
ansible-playbook failed-when-1.yml
...

# 실행 후 user 가 추가되었는지 확인
ansible -m shell -a "tail -n 3 /etc/passwd" tnode1

# 실행 : 바로 위 실행 결과와 다른 점은 무엇인가?
ansible-playbook failed-when-2.yml
...
TASK [Run user add script] ******************************************************************************************************************************************************************
fatal: [tnode1-ubuntu.local]: FAILED! => {"changed": true, "cmd": "/root/adduser-script.sh", "delta": "0:00:00.003903", "end": "2024-01-03 14:33:04.634716", "failed_when_result": true, "msg": "", "rc": 0, "start": "2024-01-03 14:33:04.630813", "stderr": "", "stderr_lines": [], "stdout": "Please input user id and password.\nUsage: adduser-script.sh \"user01 user02\" \"pw01 pw02\"", "stdout_lines": ["Please input user id and password.", "Usage: adduser-script.sh \"user01 user02\" \"pw01 pw02\""]}
...

# 실행 후 user 가 추가되었는지 확인
ansible -m shell -a "tail -n 3 /etc/passwd" tnode1

 

5. fail 시 사용자 정의 메시지를 출력할 수 있습니다. 다만 실습에 출력 내용이 거의 동일하게 되어 있긴 합니다

~/my-ansible/failed-when-custom.yml

---
- hosts: tnode1

  tasks:
    - name: Run user add script
      ansible.builtin.shell: /home/ubuntu/adduser-script.sh
      register: command_result
      ignore_errors: yes
      
    - name: Report script failure
      ansible.builtin.fail:
        msg: "{{ command_result.stdout }}"
      when: "'Please input user id and password' in command_result.stdout"

 

6. 실행

# 실행
ansible-playbook failed-when-custom.yml
...
TASK [Run user add script] ******************************************************************************************************************************************************************
changed: [tnode1-ubuntu.local]

TASK [Report script failure] ****************************************************************************************************************************************************************
fatal: [tnode1-ubuntu.local]: FAILED! => {"changed": false, "msg": "Please input user id and password.\nUsage: adduser-script.sh \"user01 user02\" \"pw01 pw02\""}
...

ansible 사용 시 셸 스크립트 보다는 모듈을 사용합시다!!

 

 

 

 

 

Blocks - https://docs.ansible.com/ansible/latest/playbook_guide/playbooks_blocks.html

ansible.builtin.**find** 모듈 - https://docs.ansible.com/ansible/latest/collections/ansible/builtin/find_module.html

 

 

앤서블 블록 오류 처리

앤서블은 블록 block 이라는 오류를 제어하는 문법을 제공합니다. 블록은 작업을 논리적으로 그룹화하는 절이며, 작업 실행 방법을 제어하는 데 사용할 수 있습니다. 또한 블록을 통해 rescue 문과 always 문을 함께 사용함으로써 오류를 처리할 수 있습니다.

block : 실행할 기본 작업을 정의함

rescure : block 절에 정의된 작업이 실패할 경우 실행할 작업을 정의함

always : block 및 rescue 절에 정의된 작업의 성공 또는 실패 여부와 관계 없이 항상 실행되는 작업을 정의함

 

 

 

1. 생성

~/my-ansible/block-example.yml

---
- hosts: tnode2
  vars:
    logdir: /var/log/daily_log
    logfile: todays.log

  tasks:
    - name: Configure Log Env
      block:
        - name: Find Directory
          ansible.builtin.find:
            paths: "{{ logdir }}"
          register: result
          failed_when: "'Not all paths' in result.msg"

      rescue:
        - name: Make Directory when Not found Directory
          ansible.builtin.file:
            path: "{{ logdir }}"
            state: directory
            mode: '0755'

      always:
        - name: Create File
          ansible.builtin.file:
            path: "{{ logdir }}/{{ logfile }}"
            state: touch
            mode: '0644'

 

2. 2번 실행

참고로 오류 메세지를 주의 깊게 보시면 됩니다.

 

 

 

롤 구조 소개 및 사용법

Roles - https://docs.ansible.com/ansible/latest/playbook_guide/playbooks_reuse_roles.html

 

Roles — Ansible Documentation

The classic (original) way to use roles is with the roles option for a given play: When you use the roles option at the play level, Ansible treats the roles as static imports and processes them during playbook parsing. Ansible executes each play in this or

docs.ansible.com

 

은 플레이북에서 전달된 변수를 사용할 수 있습니다. 변수 미설정 시 기본값을 롤의 해당 변수에 설정하기도 합니다. 장점은 아래와 같습니다.

1. 콘텐츠그룹화하여 코드를 다른 사용자와 쉽게 공유할 수 있습니다.

2. 웹 서버, 데이터베이스 서버 또는 깃(Git) 리포지터리와 같은 시스템 유형의 필수 요소정의할 수 있습니다.

3. 대규모 프로젝트를 쉽게 관리할 수 있습니다.

4. 다른 사용자와 동시개발할 수 있습니다.

5. 잘 작성한 롤은 앤서블 갤럭시를 통해 공유하거나 다른 사람이 공유한 롤을 가져올 수도 있습니다.

 

앤서블 롤 구조 : 롤은 하위 디렉터리 및 파일의 표준화된 구조에 의해 정의됩니다.

최상위 디렉터리는 롤 자체의 이름을 의미하고, 그 안은 tasks 및 handlers 등 롤에서 목적에 따라 정의된 하위 디렉터리로 구성됩니다.

아래 표는 롤의 최상의 디렉터리 아래에 있는 하위 디렉터리의 이름과 기능을 설명한 것 입니다.

 

 

 

롤 생성

1. 롤 생성 명령어 확인

# (옵션) 이전 실습 yml 파일 삭제
rm -r *.yml

# 서브 명령어 확인 : init 롤 생성 서브 명령어
ansible-galaxy role -h
usage: ansible-galaxy role [-h] ROLE_ACTION ...

positional arguments:
  ROLE_ACTION
    init       Initialize new role with the base structure of a role.
    remove     Delete roles from roles_path.
    delete     Removes the role from Galaxy. It does not remove or alter the actual GitHub repository.
    list       Show the name and version of each role installed in the roles_path.
    search     Search the Galaxy database by tags, platforms, author and multiple keywords.
    import     Import a role into a galaxy server
    setup      Manage the integration between Galaxy and the given source.
    info       View more details about a specific role.
    install    Install role(s) from file(s), URL(s) or Ansible Galaxy

options:
  -h, --help   show this help message and exit

 

2. 롤 생성 및 디렉터리 구조 확인

~/my-ansible/my-role/…

#
ansible-galaxy role init my-role
- Role my-role was created successfully

 

 

롤을 이용한 플레이북 개발 : 간단한 롤 플레이북을 개발해보자

  • 프로세스 → 각 구조에 맞게 태스크를 작성 하자
    • 롤이 호출되면 현재 호스트의 운영체제 버전이 지원 운영체제 목록에 포함되는지 확인한다.
    • 운영체제가 CentOS나 레드햇이면 httpd 관련 패키지를 dnf 모듈을 이용해 설치한다.
    • 설치가 끝나면 제어 노드의 files 디렉터리 안에 있는 index.html 파일을 관리 노드의 /var/www/html 디렉터리에 복사한다.
    • 파일 복사가 끝나면 httpd 서비스를 재시작한다.
  • 롤 구조
    • 롤 이름 : my-role
    • tasks (메인 태스크)
      • install service : httpd 관련 패키지 설치
      • copy html file : index.html 파일 복사
    • files (정적 파일)
      • index.html
    • handlers (핸들러)
      • restart service : httpd 서비스 재시작
    • defaults (가변 변수) : 메인 태스크에서 사용된 변수 선언
      • service_title
    • vars (불변 변수) : 메인 태스크와 핸들러에서 사용된 변수 선언
      • service_name : 서비스명
      • src_file_path : 복사할 파일 경로
      • dest_file_path : 파일이 복사될 디렉터리 경로
      • httpd_packages : httpd 관련 패키지 목록
      • supported_distros : 지원 OS 목록

1. 메인 테스크 작성

cd ~/my-ansible/my-role

 

첫 번째 태스크인 install service에는 플레이북에서 변수로 정의한 서비스명을 함께 출력합니다. 그리고 ansible.builtin.apt 모듈을 이용하여 httpd 관련 패키지를 설치합니다. 이때 관련 패키지는 여러 개이며 loop 문을 사용합니다.

 

서비스 설치가 끝나면 ansible.builtin.copy 모듈을 이용하여 파일을 복사하고, 복사가 끝나면 restart servie라는 핸들러를 호출합니다.

 

~/my-ansible/my-role/tasks/main.yml

---
# tasks file for my-role

- name: install service {{ service_title }}
  ansible.builtin.apt:
    name: "{{ item }}"
    state: latest
  loop: "{{ httpd_packages }}"
  when: ansible_facts.distribution in supported_distros

- name: copy conf file
  ansible.builtin.copy:
    src: "{{ src_file_path }}"
    dest: "{{ dest_file_path }}"
  notify: 
    - restart service

 

2. index.html 정적 파일 생성

~/my-ansible/my-role/files/index.html

echo "Hello! Ansible" > files/index.html

 

3. 핸들러 작성 : 특정 태스크가 끝나고 그 다음에 수행해야 하는 태스크, service 모듈을 이용하여 서비스를 재시작

~/my-ansible/my-role/handlers/main.yml

---
# handlers file for my-role

- name: restart service
  ansible.builtin.service:
    name: "{{ service_name }}"
    state: restarted

 

4. defaults (가변 변수) 작성 : 외부로부터 재정의 될 수 있는 가변 변수, service_title을 외부에서 받아 수정 가능하도록 함

~/my-ansible/my-role/defaults/main.yml

echo 'service_title: "Apache Web Server"' >> defaults/main.yml

 

5. vars (불변 변수) 작성 : 한번 정의되면 외부로부터 변수 값을 수정 할 수 없음. 롤 내의 플레이북에서만 사용되는 변수로 정의하는 것이 좋음

my-ansible/my-role/vars/main.yml

---
# vars file for my-role

service_name: apache2
src_file_path: ../files/index.html
dest_file_path: /var/www/html
httpd_packages:
  - apache2
  - apache2-doc

supported_distros:
  - Ubuntu

 

 

ansible.builtin.import_role*모듈 - https://docs.ansible.com/ansible/latest/collections/ansible/builtin/import_role_module.html

ansible.builtin.include_role 모듈 - https://docs.ansible.com/ansible/latest/collections/ansible/builtin/include_role_module.html

ansible.posix.firewalld 모듈 - https://docs.ansible.com/ansible/latest/collections/ansible/posix/firewalld_module.html

 

 

플레이북에 롤 추가하기 : 롤 실행을 위해 롤을 호출해주는 플레이북 필요

플레이북에 롤을 추가하려면 ansible.builtin.import_roleansible.builtin.include_role 모듈 2가지 방법이 있습니다.

ansible.builtin.import_role은 롤을 정적으로 추가하며, ansible.builtin.include_role는 롤을 동적으로 추가합니다.

정적으로 롤을 추가한다는 건 고정된 롤을 추가하겠다는 의미이며, 동적으로 추가한다는 건 반복문이나 조건문에 의해 롤이 변경될 수 있다는 의미입니다.

 

1. 플레이북 파일 생성 : import_role 모듈을 이용하여 my-role 롤을 추가

cd ..
pwd
/home/ubuntu/my-ansibl

 

~/my-ansible/role-example.yml
---
- hosts: tnode1

  tasks:
    - name: Print start play
      ansible.builtin.debug:
        msg: "Let's start role play"

    - name: Install Service by role
      ansible.builtin.import_role:
        name: my-role

 

2. 실행: Print 태스트 후 my-role 내의 각 태스트와 핸들러가 순차적으로 수행

ansible-playbook role-example.yml

# 확인
curl tnode1
Hello! Ansible

 

3. default/main.yml 파일에 정의된 가변 변수인 service_title을 롤을 호출하는 곳에서 재정의하는 플레이북으로 수정 후 확인

 

~/my-ansible/role-example.yml

---
- hosts: tnode1

  tasks:
    - name: Print start play
      ansible.builtin.debug:
        msg: "Let's start role play"

    - name: Install Service by role
      ansible.builtin.import_role:
        name: my-role
      vars:
        service_title: Httpd

4. 실행

 

5. index.html 정적 파일 변경 적용 후 실행해보기

 

#
echo "Hello! CloudNet@" > my-role/files/index.html
ansible-playbook role-example.yml

# 확인
curl tnode1

 

 

 

플레이북에서 Roles 섹션 사용하기 : 롤 추가하는 또 다른 방법은 roles 섹션에 롤을 나열

- roles 섹션은 tasks 섹션과 매우 유사하나 작업 목록이 아닌 롤 목록으로 구성되어 있습니다.

 

1. 실습을 위해서 tnode1firewalld 설치 후 기본 설정

# tnode1 진입
ssh tnode1
-----------------------
# firewalld 설치
sudo apt install firewalld -y
systemctl status firewalld

# 기본 정책 확인
sudo firewall-cmd --list-all
...
  services: dhcpv6-client ssh
...

# 영구적으로 public zone에서 TCP 8080 포트 추가 설정
sudo firewall-cmd --permanent --zone=public --add-port=8080/tcp

# firewalld에 rule 적용 : 아래 명령 실행 전까지 추가한 rule은 적용되지 않음
sudo firewall-cmd --reload
sudo firewall-cmd --list-all
public
  target: default
  icmp-block-inversion: no
  interfaces: 
  sources: 
  services: dhcpv6-client ssh
  ports: 8080/tcp
  protocols: 
  forward: yes
  masquerade: no
  forward-ports: 
  source-ports: 
  icmp-blocks: 
  rich rules:

# 로컬에서 apache2 web 접속 확인
curl localhost

# tnode1 빠져나오기
exit
-----------------------

 

tnode1 에 TCP 80(http) 접속 확인

ping -c 1 tnode1
curl tnode1
curl: (7) Failed to connect to 10.10.13.147 port 80 after 46 ms: Couldn't connect to server

 

2. my-role2 롤 생성

my-ansible/my-role2/…

# 롤 생성
ansible-galaxy role init my-role2

# 디렉터리 구조 확인
tree my-role2

 

3. 메인 태스크 작성 : firewalld 방화벽 서비스에 http 서비스를 추가하는 태스크와 reload 태스크를 추가

my-ansible/my-role2/tasks/main.yml

---
# tasks file for my-role2

- name: Config firewalld
  ansible.posix.firewalld:
    service: "{{ item }}"
    permanent: true
    state: enabled
  loop: "{{ service_port }}"

- name: Reload firewalld
  ansible.builtin.service:
    name: firewalld
    state: reloaded

 

4. vars (불변 변수) 작성 : http 포트와 https 포트를 정의

my-ansible/my-role2/vars/main.yml

---
# defaults file for my-role2

service_port: 
  - http
  - https

 

5. 플레이북 작성

my-ansible/role-example2.yml

---

- hosts: tnode1

  roles:
    - my-role
    - my-role2

  tasks:
    - name: Print finish role play
      ansible.builtin.debug:
        msg: "Finish role play"

 

6. 실행

# --check 옵션 사용 시 실제 수행되기 전에 어떻게 플레이 될지 미리 시뮬레이션 해볼 수 있음
ansible-playbook --check role-example2.yml

# 실행
ansible-playbook role-example2.yml

# 확인
curl tnode1

# firewalld 정책 확인
ansible -m shell -a "firewall-cmd --list-all" tnode1

시뮬레이션 실행

 

실행 후 확인

 

 

7. 가변 변수 전달 확인

my-ansible/role-example3.yml

---

- hosts: tnode1

  roles:
    - role: my-role
      service_title: "Httpd Web"
    - role: my-role2

  tasks:
    - name: Print finish role play
      ansible.builtin.debug:
        msg: "Finish role play"

8. 실행

# 실행
ansible-playbook role-example3.yml

 

결과

 

 

 

ansible.builtin.uri 모듈 - https://docs.ansible.com/ansible/latest/collections/ansible/builtin/uri_module.html

특수 작업 섹션 : roles 섹션과 함께 자주 사용 - pre_tasks , post_tasks

- pre_tasks 섹션은 tasks와 유사한 작업 목록이지만 roles 섹션의 롤보다 먼저 실행됩니다. 또한 pre-tasks 섹션은 작업을 핸들러에 알리면 해당 핸들러 작업이 롤 또는 일반 태스크 전에 실행됩니다.

- post_tasks 섹션은 tasks 및 tasks에서 알림을 받은 핸들러 다음에 실행됩니다.

 

1. 플레이북 작성 : 특수 작업 섹션인 pre_tasks, post_tasks 포함되며 roles 섹션과 tasks 섹션(→ 호출한 handlers 섹션) 포함

~/my-ansible/special_role.yml
---

- hosts: tnode1

  pre_tasks:
    - name: Print Start role
      ansible.builtin.debug:
        msg: "Let's start role play"
 
  roles:
    - role: my-role
    - role: my-role2
 
  tasks:
    - name: Curl test
      ansible.builtin.uri:
        url: http://tnode1
        return_content: true
      register: curl_result
      notify: Print result
      changed_when: true

  post_tasks:
    - name: Print Finish role
      ansible.builtin.debug:
        msg: "Finish role play"

  handlers:
    - name: Print result
      ansible.builtin.debug:
        msg: "{{ curl_result.content }}"

uri return_content 가 true 경우 응답 본문 있으면 성공, 없을 경우 실패- Link

 

2. 실행 : 어떤 순서로 태스크와 롤이 실행되는지 확인

pre_tasks 섹션에 태스크 → my-role → my-role2 → tasks(curl test) ⇒ notify 구문에 의해 handlers 태스크 실행 → 마지막 post_tasks 실행

 

#
ansible-playbook special_role.yml
PLAY [tnode1-ubuntu.local] *******************************************************************************************************************************************

TASK [Gathering Facts] ***********************************************************************************************************************************************
ok: [tnode1-ubuntu.local]

TASK [Print Start role] **********************************************************************************************************************************************
ok: [tnode1-ubuntu.local] => {
    "msg": "Let's start role play"
}

TASK [my-role : install service Apache Web Server] *******************************************************************************************************************
ok: [tnode1-ubuntu.local] => (item=apache2)
ok: [tnode1-ubuntu.local] => (item=apache2-doc)

TASK [my-role : copy conf file] **************************************************************************************************************************************
ok: [tnode1-ubuntu.local]

TASK [my-role2 : Config firewalld] ***********************************************************************************************************************************
ok: [tnode1-ubuntu.local] => (item=http)
ok: [tnode1-ubuntu.local] => (item=https)

TASK [my-role2 : Reload firewalld] ***********************************************************************************************************************************
changed: [tnode1-ubuntu.local]

TASK [Curl test] *****************************************************************************************************************************************************
changed: [tnode1-ubuntu.local]

RUNNING HANDLER [Print result] ***************************************************************************************************************************************
ok: [tnode1-ubuntu.local] => {
    "msg": "Hello! CloudNet@\n"
}

TASK [Print Finish role] *********************************************************************************************************************************************
ok: [tnode1-ubuntu.local] => {
    "msg": "Finish role play"
}

 

 

3. tnode1 에 firewalld 삭제

ansible -m shell -a "systemctl stop firewalld" tnode1
ansible -m shell -a "apt remove firewalld -y" tnode1

 

 

 

앤서블 갤럭시

롤을 생성할 때 사용했던 앤서블 갤럭시 ansible-galaxy 에 대해 알아보겠습니다.

ansible-galaxy - https://docs.ansible.com/ansible/latest/cli/ansible-galaxy.html

 

ansible-galaxy — Ansible Documentation

Perform various Role and Collection related operations. ansible(1), ansible-config(1), ansible-console(1), ansible-doc(1), ansible-inventory(1), ansible-playbook(1), ansible-pull(1), ansible-vault(1)

docs.ansible.com

 

앤서블 갤럭시 소개 : 롤 공유, 다만 롤은 검증되지 않은 것이 대부분이기 때문에 사용 시 주의해야 합니다

https://galaxy.ansible.com/ui/

 

Ansible Galaxy

 

galaxy.ansible.com

 

1. Roles : 키워드 ‘postgres’ 검색 + 분류 ‘Download count

2. 검색될 롤 확인 - Link

- 롤 설치 방법, 커밋 commit 한 날짜, 다른 유저가 다운로드한 횟수, 설치 가능한 운영체제, 지원 가능한 버전 등 내용 확인할 수 있습니다.

 

 

 

명령어를 이용한 앤서블 갤럭시 활용 : 앤서블 갤럭시로부터 롤 가져오기

1.롤 서브 명령어 확인

ansible-galaxy role -h
usage: ansible-galaxy role [-h] ROLE_ACTION ...

positional arguments:
  ROLE_ACTION
    init       Initialize new role with the base structure of a role.
    remove     Delete roles from roles_path.
    delete     Removes the role from Galaxy. It does not remove or alter the actual GitHub repository.
    list       Show the name and version of each role installed in the roles_path.
    search     Search the Galaxy database by tags, platforms, author and multiple keywords.
    import     Import a role into a galaxy server
    setup      Manage the integration between Galaxy and the given source.
    info       View more details about a specific role.
    install    Install role(s) from file(s), URL(s) or Ansible Galaxy

options:
  -h, --help   show this help message and exit

 

2. 롤 검색

ansible-galaxy role search postgresql --platforms Ubuntu
Found 270 roles matching your search:

 Name                                                 Description
 ----                                                 -----------
 aaronpederson.postgresql                             PostgreSQL is a powerful, open source object-relational database system. It has more than 15 years of active>
 alainvanhoof.alpine_postgresql                       PostgreSQL for Alpine Linux
 alikins.postgresql                                   PostgreSQL server for Linux.
...

 

3. 롤 상세 정보 확인

ansible-galaxy role info geerlingguy.postgresql

 

 

4. 롤 가져오기

# -p 옵션으로 롤이 설치될 디렉터리 경로 지정
ansible-galaxy role install -p roles geerlingguy.postgresql

# 확인
tree roles
roles
└── geerlingguy.postgresql
    ├── defaults
    │   └── main.yml
    ├── handlers
    │   └── main.yml
	  ...

ansible-galaxy role list -p roles
# /root/my-ansible/roles
- geerlingguy.postgresql, 3.5.0
# /etc/ansible/roles
[WARNING]: - the configured path /root/.ansible/roles does not exist.
[WARNING]: - the configured path /usr/share/ansible/roles does not exist.

# (옵션) 앤서블 환경 설정에 롤 디렉터리 설정
## my-ansible/ansible.cfg 파일 편집
[defaults]
inventory = ./inventory
remote_user = root
ask_pass = false
roles_path = ./roles
...

inject_facts_as_vars = false <- 실습 사용 롤이 예전 facts 를 사용하니 이 옵션은 제거하자

# 확인
ansible-galaxy role list
ansible-galaxy role list -p roles

 

VSCODE에서 메인 태스크 등 확인 : my-ansible/roles/tasks/main.yml , my-ansible/roles/vars/Ubuntu-22.yml

 

---
# Variable configuration.
- include_tasks: variables.yml

# Setup/install tasks.
- include_tasks: setup-Archlinux.yml
  when: ansible_os_family == 'Archlinux'

- include_tasks: setup-Debian.yml
  when: ansible_os_family == 'Debian'

- include_tasks: setup-RedHat.yml
  when: ansible_os_family == 'RedHat'

- include_tasks: initialize.yml
- include_tasks: configure.yml

- name: Ensure PostgreSQL is started and enabled on boot.
  service:
    name: "{{ postgresql_daemon }}"
    state: "{{ postgresql_service_state }}"
    enabled: "{{ postgresql_service_enabled }}"

# Configure PostgreSQL.
- import_tasks: users.yml
- import_tasks: databases.yml
- import_tasks: users_props.yml

 

---
__postgresql_version: "14"
__postgresql_data_dir: "/var/lib/postgresql/{{ __postgresql_version }}/main"
__postgresql_bin_path: "/usr/lib/postgresql/{{ __postgresql_version }}/bin"
__postgresql_config_path: "/etc/postgresql/{{ __postgresql_version }}/main"
__postgresql_daemon: postgresql
__postgresql_packages:
  - postgresql
  - postgresql-contrib
  - libpq-dev
postgresql_python_library: python3-psycopg2

 

5. 가져온 롤을 이용하여 설치 : 설치 중 root 권한 필요(become: yes)

my-ansible/role-galaxy.yml
---
- hosts: tnode1

  roles:
    - geerlingguy.postgresql

 

ansible-playbook role-galaxy.yml

 

설치 확인

ssh tnode1 systemctl status postgresql

 

6. 가져온 롤 삭제

ansible-galaxy role remove geerlingguy.postgresql
ansible-galaxy role list
rm -r roles

 

 

콘텐츠 컬렉션

앤서블이 처음 개발되었을 때는 사용되는 모듈이 모두 핵심 소프트웨어 패키지의 일부로 포함되었습니다. 그런데 모듈 수가 늘어나면서 업스트림 프로젝트에서 모듈을 관리하기가 더 어려워졌습니다. 모든 모듈에는 고유한 이름이 필요하고, 모듈 업데이트를 핵심 앤서블 코드에 대한 업데이트와 동기화해야 했습니다.

그래서 개발한 것이 바로 앤서블 콘텐츠 컬렉션입니다. 앤서블 콘텐츠 컬렉션을 사용하면 핵심 앤서블 코드 업데이트와 모듈플러그인에 대한 업데이트가 분리됩니다. 그리고 플레이북에서 사용할 수 있는 일련의 관련 모듈, 역할, 기타 플러그인을 제공합니다. 그렇기 때문에 벤더개발자앤서블 릴리스독립적으로 컬렉션을 자신의 속도에 맞게 유지, 관리하고 배포할 수 있습니다.

앤서블 콘텐츠 컬렉션을 사용하면 유연성도 향상됩니다. 지원되는 모듈을 모두 설치하는 대신 필요한 콘텐츠설치할 수 있습니다. 특정 버전(이전 버전 또는 이후 버전)의 컬렉션을 선택하거나 레드햇 또는 벤더가 지원하는 컬렉션 버전 또는 커뮤니티에서 제공하는 버전 중에서 선택할 수도 있습니다.

Ansible 2.9 이상콘텐츠 컬렉션지원합니다. 업스트림 앤서블은 Ansible Base 2.10 및 Ansible Core 2.11의 코어 Ansible 코드에서 대부분의 모듈을 번들 해제하고 컬렉션에 배치했습니다. 레드햇 앤서블 오토메이션 플랫폼 2.2는 자동화 실행 기능을 상속하는 Ansible Core 2.13 기반의 자동화 실행 환경을 제공합니다.

 

앤서블 공식 문서의 콘텐츠 컬렉션 - https://docs.ansible.com/ansible/latest/collections/index.html

 

Collection Index — Ansible Documentation

© Copyright Ansible project contributors. Last updated on Jan 11, 2024.

docs.ansible.com

 

 

명령어를 이용한 앤서블 콘텐츠 컬렉션

1. 명령어 확인

ansible-galaxy collection -h

 

 

2. 앤서블이 설치된 프로젝트 환경에 설치된 컬렉션 확인

ansible-galaxy collection list


tree /usr/lib/python3/dist-packages/ansible_collections -L 1

3.컬렉션 삭제 및 설치

#
ansible-galaxy collection list openstack.cloud
# /usr/lib/python3/dist-packages/ansible_collections
Collection      Version
--------------- -------
openstack.cloud 2.2.0

tree /usr/lib/python3/dist-packages/ansible_collections/openstack -L 3
...

# 삭제
sudo rm -rf /usr/lib/python3/dist-packages/ansible_collections/openstack*

# 확인
ansible-galaxy collection list openstack.cloud
ansible-galaxy collection list 


##설치
# 특정 버전으로 설치
ansible-galaxy collection install openstack.cloud:2.1.0

# 설치 확인
ansible-galaxy collection list
ansible-galaxy collection list openstack.cloud
# /root/.ansible/collections/ansible_collections
Collection      Version
--------------- -------
openstack.cloud 2.1.0

tree /home/ubuntu/.ansible/collections/ansible_collections -L 3
...
4. 오프라인 환경 지원을 위해서, 컬렉션을 tar 파일 형태로 다운로드 가능
# -p 디렉터리 지정
ansible-galaxy collection download -p ./collection openstack.cloud

# 확인
tree collection/
collection/
├── openstack-cloud-2.2.0.tar.gz
└── requirements.yml

tar tvf collection/openstack-cloud-2.2.0.tar.gz
...

cat collection/requirements.yml
collections:
- name: openstack-cloud-2.2.0.tar.gz
  version: 2.2.0

ansible-galaxy collection list
...
ansible-galaxy collection list openstack.cloud
...



##tar 파일로 컬렉션 설치

# tar 파일로 컬렉션 설치
ansible-galaxy collection install ./collection/openstack-cloud-2.2.0.tar.gz

# 확인
ansible-galaxy collection list
# /root/.ansible/collections/ansible_collections
Collection                    Version
----------------------------- -------
openstack.cloud               2.2.0  

# /usr/lib/python3/dist-packages/ansible_collections
Collection                    Version
----------------------------- -------
amazon.aws                    6.5.0  
ansible.netcommon             5.3.0
...

ansible-galaxy collection list openstack.cloud
...

'study > Ansible101 1기' 카테고리의 다른 글

Ansible101 1기 3주차 두번째  (0) 2024.01.28
Ansible101 1기 3주차 첫번째  (0) 2024.01.28
Ansible101 1기 2주차 첫번째  (0) 2024.01.14
Ansible101 1기 1주차  (0) 2024.01.07
Ansible101 1기 실습환경 구성  (0) 2024.01.06