Ansible study 2주차
목차
반복문
task 내부에 item이라는 변수를 입력하고
loop라는 키워드 내부에 반복할 구문을 넣는 방식
item과 loop가 반드시 짝지어져야한다.
loop 내에 vars라는 변수를 사용해도 된다.
---
- hosts: all
tasks:
- name: Check sshd state and rsylog state
ansible.builtin.service:
name: "{{ item }}"
state: started
loop:
- sshd
- rsyslog
사전 목록에 의한 반복문
여러개의 아이템 사용할때 사용하는 반복문
---
- hosts: all
tasks:
- name: Create files
ansible.builtin.file:
path: "{{ item['log-path'] }}"
mode: "{{ item['log-mode'] }}"
state: touch
loop:
- log-path: /var/log/test1.log
log-mode: '0644'
- log-path: /var/log/test2.log
log-mode: '0600'
반복문에서 Register 변수 사용
반복 실행되는 작업의 출력을 캡처할때 Register변수를 사용한다.
---
- hosts: localhost
tasks:
- name: Loop echo test
ansible.builtin.shell: "echo 'I can speak {{ item }}'"
loop:
- Korean
- English
register: result
- name: Show result
ansible.builtin.debug:
var: result
조건문
특정 조건을 만족할때 작업 또는 플레이가 실행되도록 하는것
조건문에는 플레이변수, 작업변수, 앤서블 팩트등을 사용할수 있다.
사용법은 when 을 사용하여 true인지 false인지 판단하여 실행한다.
해당 조건에 다음과 같이 사용 할 수 있다.
- != : 값이 같지 않을 때 참 true
- >, >=, <=, < : ‘초과, ‘ 이상’, ‘이하’, ‘미만’ 일 때에 참 true
- not : 조건의 부정
- and, or : ‘그리고’, ‘또는’의 의미로 여러 조건의 조합 가능
- in : 값이 포함된 경우에 참 true. 예를 들어 2 in “1, 2, 3” 은 참 true
- is defined : 변수가 정의된 경우 참 true
변수(vars)를 할당하여 여러 변수를 활용하여 조건(and, or..)을 넣을수도 있다.
---
- hosts: localhost
vars:
run_my_task: true
tasks:
- name: echo message
ansible.builtin.shell: "echo test"
when: run_my_task
register: result
- name: Show result
ansible.builtin.debug:
var: result
---
- hosts: all
vars:
supported_distros:
- Ubuntu
- CentOS
tasks:
- name: Print supported os
ansible.builtin.debug:
msg: "This {{ ansible_facts['distribution'] }} need to use dnf"
when: ansible_facts['distribution'] in supported_distro
핸들러 및 작업 실패 처리
핸들러는 다른 작업에서 트리거한 알림에 응답하는 작업이며, 해당 호스트에서 작업이 변경될 때만 핸들러에 통지
앤서블 핸들러
notify 문을 활용하여 handler를 생성하면 된다.
notify에 있는 task가 성공할 경우 핸들러가 실행된다 하지만 실패하면 실행이 되지 않는다.(일반적인 태스크도 마찬가지)
태스크가 실패할경우 ignore_errors:문을 추가하면 되고 핸들러가 실패하면 force_handlers 문을 넣으면된다.
---
- hosts: els
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"
작업실패 조정
앤서블에서 셸스크립트를 정상적으로 실행 시키기만 하면 success 가 떨어진다.
하지만 쉘스크립트가 실행된후 오류가 발생해도 앤서블에선 success로 떨어지게 된다.
이러한 이유로 앤서블에서 쉘스크립트를 권장하진 않는다.
이것을 방지하기 위하여 failed_when을 사용하긴하는데 일일이 결과 로그를 입력할수 없고 다른 에러가 발생할경우 피해갈 수 있을 것이다.
---
- hosts: ansible
tasks:
- name: Run user add script
ansible.builtin.shell: /home/ubuntu/test/adduser-script.sh
register: command_result
failed_when: "'Please input user id and password' in command_result.stdout"
- name:
ansible.builtin.debug:
msg: "This task is next task"
앤서블 블록 및 오류처리
오류를 제어하는 문법으로, 블록은 잡업을 논리적으로 그룹화 하여 작업 실행 방법을 제어하는데 사용할 수 있다.
- block : 실행할 기본 작업을 정의함
- rescure : block 절에 정의된 작업이 실패할 경우 실행할 작업을 정의함
- always : block 및 rescue 절에 정의된 작업의 성공 또는 실패 여부와 관계 없이 항상 실행되는 작업을 정의함
---
- hosts: ansible
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: "No such file or directory"
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'
만약 실패하면 디렉토리및 파일을 생성한것을 볼수 있다.
다시 실행하면 다시 create 파일을 한다.
롤과 콘텐츠 콜렉션
내가 만든 플레이북을 다른 사람들과 공유 하거나 다른 사람들이 만든 플레이북을 활용할 수 있는 기능을 구현하는 앤서블 롤, 공유할 수 있는 앤서블 갤럭시 등을 알아보자
앤서블 롤 구조
앤서블 롤을 생성하면 디렉토리가 생성되는데 각 역할은 다음과 같다.
하위 디렉터리 | 기능 |
defaults | 이 디렉터리의 main.yml 파일에는 롤이 사용될 때 덮어쓸 수 있는 롤 변수의 기본값이 포함되어 있습니다. 이러한 변수는 우선순위가 낮으며 플레이에서 변경할 수 있습니다. |
files | 이 디렉터리에는 롤 작업에서 참조한 정적 파일이 있습니다. |
handlers | 이 디렉터리의 main.yml 파일에는 롤의 핸들러 정의가 포함되어 있습니다. |
meta | 이 디렉터리의 main.yml 파일에는 작성자, 라이센스, 플랫폼 및 옵션, 롤 종속성을 포함한 롤에 대한 정보가 들어 있습니다. |
tasks | 이 디렉터리의 main.yml 파일에는 롤의 작업 정의가 포함되어 있습니다. |
templates | 이 디렉터리에는 롤 작업에서 참조할 Jinja2 템플릿이 있습니다. |
tests | 이 디렉터리에는 롤을 테스트하는 데 사용할 수 있는 인벤토리와 test.yml 플레이북이 포함될 수 있습니다. |
vars | 이 디렉터리의 main.yml 파일은 롤의 변수 값을 정의합니다. 종종 이러한 변수는 롤 내에서 내부 목적으로 사용됩니다. 또한 우선순위가 높으며, 플레이북에서 사용될 때 변경되지 않습니다 |
앤서블 롤 생성 명령어
ansible-galaxy role init my-role
롤을 이용한 플레이북 개발
다음과 같은 과정으로 롤을 만들 것이다.
- 프로세스 → 각 구조에 맞게 태스크를 작성 하자
- 롤이 호출되면 현재 호스트의 운영체제 버전이 지원 운영체제 목록에 포함되는지 확인한다.
- 운영체제가 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 목록
main task 작성
my-role/tasks/main.yml에서 작업한다.
loop문을 활용하여 httpd 관련 패키지및 설치를 하고 copy를 통해 파일을 복사하고 restart service라는 핸들러를 호출한다.
---
# 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
index.hml 파일 작성
files/index.html 파일을 작성하여 메인페이지에 보여줄 html을 간단하게 하자
핸들러 작성
handlers/main.yml
서비스 재시작으로 작성
---
# handlers file for my-role
- name: restart service
ansible.builtin.service:
name: "{{ service_name }}"
state: restarted
defaults 작성
defaults/main.yml
---
# defaults file for my-role
service_title: "Apache Web Server"
vars 작성
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-playbook명령어로 실행은 할수 없다.
role을 실행하기 위해서는 롤을 호출해주는 플레이북이 필요하다.
- 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
롤 생성한 폴더 밖에서 작업을 진행한다.
role-example.yml 을 다음과 같이 작성한다.
---
- hosts: ansible
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
그리고 실행
플레이북에서 Role 섹션 사용하기
my-role에서 생성한 apache의 포트는 8080 으로 80포트는 열려 있지 않다.
방화벽에 80포트를 여는
ansible-galaxy role init my-role2로 새로운 롤 생성하여 테스트 해보자
task 작성
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
vars 작성
my-role2/vars/main.yml
---
# defaults file for my-role2
service_port:
- http
- https
플레이북 작성
role-example2.yml
---
- hosts: ansible
roles:
- my-role
- my-role2
tasks:
- name: Print finish role play
ansible.builtin.debug:
msg: "Finish role play"
실행
확인해보면 http와 https 서비스가 허용되어 있는것을 확인할수 있다.
특수 작업 세션
태스크를 이전에 실행할지 아니면 이후에 실행할지 설정하는 방식
- pre_tasks 섹션: role 섹션보다 먼저 실행되며 이 섹션에서 핸들러에게 알리면 롤, 일반 태스크 이전에 실행이 됩니다.
- post_tasks 섹션: 일반 태스크의 핸들러 이후에 실행되는 태스크
---
- hosts: ansible
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 }}"