Playbook


Playbook

1개 이상의 play를 저장한 것 (.yaml / .yml)

위에서부터 차례대로 play하기 때문에 start 먼저하고 install 하면 안됨.

 

** 문법체크

"ansible-playbook --syntax-check http.yaml"

 

 

기본 틀 (useradd)

더보기
--- # yaml문서의 시작 (생략가능)
- name: For useradd # 문서를 설명하는 이름 playbook의 시작은 무조건 리스트형("-")
  hosts: all
  tasks: # tasks의 시작도 리스트형("-")
    - name: For useradd task # task를 설명하는 이름 (얘는 생략가능)
      user:
        name: tuser10 # 얘만 생략불가 나머지는 안쓰면 디폴트
        comment: guaba # 유저코멘트
        shell: /bin/bash
        state: present # present=생성
    - name: 두번째 계정 생성
      user:
        name: tuser20
        state: present

http 깔고 실행하기

"ansible-doc yum", "ansible-doc service"로 확인해보면 편함

 

http.yaml

- name: playbook for http service
  hosts: node1
  tasks:
    - name: installed httpd
      yum:
        name: httpd
        state: latest # 설치되어있어도 최신버전으로 업데이트
    - name: started httpd
      service:
        name: httpd
        state: started # systemctl start httpd
        enabled: yes

 

방화벽(firewalld) 설치 및 추가

[opuser@control sample]$ cat http.yaml
- name: playbook for http service
  hosts: node1
  tasks:
    - name: installed httpd
      yum:
        name: httpd
        state: latest # 설치되어있어도 최신버전으로 업데이트

    - name: installed firewalld
      yum:
        name: firewalld
        state: latest

    - name: started httpd
      service:
        name: httpd
        state: started # systemctl start httpd
        enabled: yes

    - name: started firewalld
      service:
        name: firewalld
        state: restarted
        enabled: yes

    - name: add service https
      firewalld:
        service: https
        state: enabled
        permanent: yes # firewall-cmd --add-service=https --permanent
        immediate: yes # firewall-cmd --reload
          
    - name: add service http
      firewalld:
        service: http
        state: enabled

 

여기에 install이 두개니까 리스트로 묶어서 할 수도 있다.

- name: installed httpd, firewalld
  yum:
    name: 
      - httpd
      - firewalld
    state: latest
이런식으로

혹은 
    name: [httpd, firewalld] 도 됨

 

index.html copy

멱등성 때문에 한번더 실행해도 change가 안됨.

하지만, index.html을 수정 혹은 변경하면 복사함

체크섬을 확인해서 복사하기 때문에

체크섬 확인 방법

"md5sum index.html"

- name: copy index.html
  copy:
    src: ./src/index.html # 출발지
    dest: /var/www/html   # 도착지

 

echo 출력 (command 모듈)

[opuser@control sample]$ cat test.yaml
- name: test
  hosts: localhost
  tasks:
    - command: echo "hello ans"
      register: myvar # register 변수의 이름은 myvar
    - debug:
        msg: "{{myvar.stdout}}"
    - command: echo "hello linux"
      register: myvar2
    - debug:
        msg: "{{myvar2.stdout}}"
    - command: date
      register: myvar3
    - debug:
        msg: "{{myvar3.stdout}}"

 

결과 출력

[opuser@control sample]$ ansible-playbook test.yaml

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

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

TASK [command] ************************************************************************************
changed: [localhost]

TASK [debug] **************************************************************************************
ok: [localhost] => {
    "msg": "hello ans"
}

TASK [command] ************************************************************************************
changed: [localhost]

TASK [debug] **************************************************************************************
ok: [localhost] => {
    "msg": "hello linux"
}

TASK [command] ************************************************************************************
changed: [localhost]

TASK [debug] **************************************************************************************
ok: [localhost] => {
    "msg": "Tue Feb 13 06:47:34 UTC 2024"
}

PLAY RECAP ****************************************************************************************
localhost          : ok=7    changed=3    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

 

변수 (var - variable)

변수이름은 문자로 시작해야 하고 특수문자는 '_' 만 사용가능하다.

변수로 인식은 {{변수}} 다. (중괄호 두개)

 

var.yaml

[opuser@control sample]$ cat var.yaml
- name: var
  hosts: node1
  vars: # 변수선언
    service: vsftpd
    service_port: 21
  tasks:
    - name: installed {{service}} # 변수가 뒤에있다면 "" 안붙여도 됨
      yum:
        name: "{{service}}" # 변수가 맨 앞에 있다면 "" 붙여야함
        state: present
    - name: "{{service_port}} is ftp port"
      debug:
        var: service_port
TASK [21 is ftp port] *****************************************************************************
ok: [node1] => {
    "service_port": 21
}

 

inventory에 변수 등록

[opuser@control sample]$ cat inventory
[webservers]
node1           package=finger # 한칸 이상만 띄우면 된다. node1에서 package=finger로 변수 설정
node2           package=finger-server    service=finger-server

[dbservers]
node3

[dbservers:vars] # 그룹으로 묶어서 변수 설정
service=mariadb

 

** inventory에 변수를 등록하면 지저분해질 수 있다.

그래서 host_varsgroup_vars에 등록할 수 있다. (이름 이대로 해야함)

vim host_vars/node1  # 호스트 이름을 파일명으로
>> package: finger   # ":" 콜론뒤에 한칸 띄워야함

vim host_vars/node2
>> package: finger-server
   service: finger-server

vim group_vars/dbservers  # 그룹 이름을 파일명으로
>> service: mariadb

 

등록된 변수 확인

[opuser@control sample]$ cat var.yaml
- name: var
  hosts: [node1, node2]
  tasks:
    - name: "{{package}}"
      debug:
        var: package

- name: var2
  hosts: node2
  tasks:
    - debug:
        var: service
[opuser@control sample]$ ansible-playbook var.yaml

PLAY [var] ****************************************************************************************

TASK [Gathering Facts] ****************************************************************************
ok: [node2]
ok: [node1]

TASK [finger] *************************************************************************************
ok: [node1] => {
    "package": "finger"
}
ok: [node2] => {
    "package": "finger-server"
}

PLAY [var2] ***************************************************************************************

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

TASK [debug] **************************************************************************************
ok: [node2] => {
    "service": "finger-server"
}

 

실습

시나리오:

192.168.110.20 (node1)에서는 node1

192.168.110.30 (node2)에서는 node2

192.168.110.40 (node3)에서는 node3

이라고 나오도록 만들기

더보기

src/index.html에 node1

src2/index.html에 node2

src3/index.html에 node3 를 만든뒤 

[opuser@control sample]$ cat index.yaml
- name: playbook for http service
  hosts: [node1, node2, node3]
  tasks:
    - name: installed httpd, firewalld
      yum:
        name:
          - httpd
          - firewalld
        state: latest # 설치되어있어도 최신버전으로 업데이트

    - name: started httpd
      service:
        name: httpd
        state: started # systemctl start httpd
        enabled: yes

    - name: started firewalld
      service:
        name: firewalld
        state: restarted
        enabled: yes

    - name: add service https
      firewalld:
        service: https
        state: enabled
        permanent: yes
        immediate: yes

    - name: add service http
      firewalld:
        service: http
        state: enabled
        permanent: yes
        immediate: yes
- name: node1 index
  hosts: node1
  tasks:
    - name: copy index.html
      copy:
        src: ./src/index.html # 출발지
        dest: /var/www/html   # 도착지
- name: node2 index
  hosts: node2
  tasks:
    - name: copy index.html
      copy:
        src: ./src2/index.html
        dest: /var/www/html
- name: node3 index
  hosts: node3
  tasks:
    - name: copy index.html
      copy:
        src: ./src3/index.html
        dest: /var/www/html

 

이거 말고도 커맨드로 echo "node1" > /var/www/html/index.html 하는 방법도 있지만 이건 멱등성 문제때매 패스

목적지 dest: 를 변수로 잡고 해도 될거같음

혹은

node1.html, node2.html, node3.html 이런식으로 다 만들어두고

inventory에 node1    index_file=node1.html 이런식으로 변수 등록 한 뒤

src를 ./src/{{index_file}} 하고

dest를 /var/www/html/index.html 로 바꿔서 저장하면 된다. - 요러면 yaml파일에 task 한번으로 다됨

혹은

lineinfile을 사용하면 되는데 (한줄 추가하는것)

- name: 
  lineinfile:
    path: /var/www/html/index.html # 도착지 경로
    line: welcome to {{nodename}} # nodename은 inventory에 등록해두고
    create: yes # 없으면 추가하는것

** 여러줄 추가는 blockinfile

 

debug를 통한 팩트변수 출력하기

[vagrant@control /home/vagrant/sample]$ cat b.yaml
- hosts: all
  tasks:
    - debug:
        msg: "{{ansible_facts['nodename']}} {{ ansible_facts['devices']}}"
    - debug:
        msg: "{{ansible_facts['system']}}"
    - debug:
        msg: "{{ansible_facts['os_family']}}"

 

결과

더보기
[vagrant@control /home/vagrant/sample]$ ansible-playbook b.yaml

PLAY [all] ****************************************************************************************

TASK [Gathering Facts] ****************************************************************************
ok: [node2]
ok: [node3]
ok: [node1]

TASK [debug] **************************************************************************************
ok: [node1] => {
    "msg": "node1.example.com {u'sda': {u'scheduler_mode': u'noop', u'sectorsize': u'512', u'vendor': u'ATA', u'sectors': u'83886080', u'links': {u'masters': [], u'labels': [], u'ids': [u'ata-VBOX_HARDDISK_VB7fb4235f-51b795ad'], u'uuids': []}, u'sas_device_handle': None, u'sas_address': None, u'virtual': 1, u'holders': [], u'host': u'IDE interface: Intel Corporation 82371AB/EB/MB PIIX4 IDE (rev 01)', u'rotational': u'1', u'removable': u'0', u'support_discard': u'0', u'serial': u'VB7fb4235f', u'size': u'40.00 GB', u'model': u'VBOX HARDDISK', u'partitions': {u'sda1': {u'sectorsize': 512, u'uuid': u'1c419d6c-5064-4a2b-953c-05b2c67edb15', u'sectors': u'83884032', u'links': {u'masters': [], u'labels': [], u'ids': [u'ata-VBOX_HARDDISK_VB7fb4235f-51b795ad-part1'], u'uuids': [u'1c419d6c-5064-4a2b-953c-05b2c67edb15']}, u'start': u'2048', u'holders': [], u'size': u'40.00 GB'}}}}"
}
ok: [node2] => {
    "msg": "node2.example.com {u'sda': {u'scheduler_mode': u'noop', u'sectorsize': u'512', u'vendor': u'ATA', u'sectors': u'83886080', u'links': {u'masters': [], u'labels': [], u'ids': [u'ata-VBOX_HARDDISK_VB331308a0-1b094729'], u'uuids': []}, u'sas_device_handle': None, u'sas_address': None, u'virtual': 1, u'holders': [], u'host': u'IDE interface: Intel Corporation 82371AB/EB/MB PIIX4 IDE (rev 01)', u'rotational': u'1', u'removable': u'0', u'support_discard': u'0', u'serial': u'VB331308a0', u'size': u'40.00 GB', u'model': u'VBOX HARDDISK', u'partitions': {u'sda1': {u'sectorsize': 512, u'uuid': u'1c419d6c-5064-4a2b-953c-05b2c67edb15', u'sectors': u'83884032', u'links': {u'masters': [], u'labels': [], u'ids': [u'ata-VBOX_HARDDISK_VB331308a0-1b094729-part1'], u'uuids': [u'1c419d6c-5064-4a2b-953c-05b2c67edb15']}, u'start': u'2048', u'holders': [], u'size': u'40.00 GB'}}}}"
}
ok: [node3] => {
    "msg": "node3.example.com {u'sda': {u'scheduler_mode': u'noop', u'sectorsize': u'512', u'vendor': u'ATA', u'sectors': u'83886080', u'links': {u'masters': [], u'labels': [], u'ids': [u'ata-VBOX_HARDDISK_VB96bd062b-9460dfb3'], u'uuids': []}, u'sas_device_handle': None, u'sas_address': None, u'virtual': 1, u'holders': [], u'host': u'IDE interface: Intel Corporation 82371AB/EB/MB PIIX4 IDE (rev 01)', u'rotational': u'1', u'removable': u'0', u'support_discard': u'0', u'serial': u'VB96bd062b', u'size': u'40.00 GB', u'model': u'VBOX HARDDISK', u'partitions': {u'sda1': {u'sectorsize': 512, u'uuid': u'1c419d6c-5064-4a2b-953c-05b2c67edb15', u'sectors': u'83884032', u'links': {u'masters': [], u'labels': [], u'ids': [u'ata-VBOX_HARDDISK_VB96bd062b-9460dfb3-part1'], u'uuids': [u'1c419d6c-5064-4a2b-953c-05b2c67edb15']}, u'start': u'2048', u'holders': [], u'size': u'40.00 GB'}}}}"
}

TASK [debug] **************************************************************************************
ok: [node1] => {
    "msg": "Linux"
}
ok: [node2] => {
    "msg": "Linux"
}
ok: [node3] => {
    "msg": "Linux"
}

TASK [debug] **************************************************************************************
ok: [node1] => {
    "msg": "RedHat"
}
ok: [node2] => {
    "msg": "RedHat"
}
ok: [node3] => {
    "msg": "RedHat"
}

when 제어구문

[vagrant@control /home/vagrant/sample]$ cat when.yaml
- hosts: localhost
  tasks:
    - command: /bin/false
      register: result # register는 결과물을 변수로 정의하는 것
      ignore_errors: True # 에러가 나더라도 무시하고 아래꺼를 실행해라
    - command: cal
      register: cal_result
      when: result is failed # 위의 register의 result(변수)가 failed라면 아래꺼를 실행해라
    - debug:
        msg: "{{cal_result}}"

** register는 결과물을 변수로 정의하는 것이다.

 

결과

더보기
[vagrant@control /home/vagrant/sample]$ ansible-playbook when.yaml

PLAY [localhost] **********************************************************************************

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

TASK [command] ************************************************************************************
fatal: [localhost]: FAILED! => {"changed": true, "cmd": ["/bin/false"], "delta": "0:00:00.006196", "end": "2024-02-14 12:01:56.983409", 
"msg": "non-zero return code", "rc": 1, "start": "2024-02-14 12:01:56.977213", "stderr": "", "stderr_lines": [], "stdout": "", "stdout_lines": []}
...ignoring

TASK [command] ************************************************************************************
changed: [localhost]

TASK [debug] **************************************************************************************
ok: [localhost] => {
    "msg": {
        "changed": true,
        "cmd": [
            "cal"
        ],
        "delta": "0:00:00.008171",
        "end": "2024-02-14 12:01:57.620365",
        "failed": false,
        "rc": 0,
        "start": "2024-02-14 12:01:57.612194",
        "stderr": "",
        "stderr_lines": [],
        "stdout": "    February 2024   \nSu Mo Tu We Th Fr Sa\n             
        1  2  3\n 4  5  6  7  8  9 10\n11 12 13 14 15 16 17\n18 19 20 21 22 23 24\n25 26 27 28 29",
        "stdout_lines": [
            "    February 2024   ",
            "Su Mo Tu We Th Fr Sa",
            "             1  2  3",
            " 4  5  6  7  8  9 10",
            "11 12 13 14 15 16 17",
            "18 19 20 21 22 23 24",
            "25 26 27 28 29"
        ]
    }
}

loop (반복)

[vagrant@control /home/vagrant/sample]$ cat loop2.yaml
- name: add several users
  hosts: all
  tasks:
    - user:
        name: "{{ item }}"
        state: present
        groups: "wheel"
      loop:
        - testuser1
        - testuser2

 

[vagrant@control /home/vagrant/sample]$ ansible-playbook loop2.yaml

PLAY [add several users] **************************************************************************

TASK [Gathering Facts] ****************************************************************************
ok: [node2]
ok: [node3]
ok: [node1]

TASK [user] ***************************************************************************************
changed: [node2] => (item=testuser1)
changed: [node3] => (item=testuser1)
changed: [node1] => (item=testuser1)
changed: [node2] => (item=testuser2)
changed: [node3] => (item=testuser2)
changed: [node1] => (item=testuser2)
[vagrant@control /home/vagrant/sample]$ ansible all -a "ls /home"
node1 | CHANGED | rc=0 >>
admin
devops
opuser
testuser1 # 추가됨
testuser2 # 추가됨 
tuser10
vagrant
node2 | CHANGED | rc=0 >>
admin
devops
opuser
testuser1 # 추가됨
testuser2 # 추가됨
vagrant
node3 | CHANGED | rc=0 >>
admin
devops
opuser
testuser1 # 추가됨
testuser2 # 추가됨
vagrant

 

handlers

서비스를 등록 해두고 notify로 불러올 수 있다. (평상시에는 안됨)

* 대신 불러올 때 handlers의 name을 참조하기 때문에 name을 잘 쓸 필요가 있다.

* notify가 붙은 모듈에서 change가 발생해야 handlers로 등록된 모듈이 실행된다.

* handlers는 tasks와 같은 라인임 (띄어쓰기 주의)

* handlers는 tasks가 다 끝난 이후에 실행됨.

더보기
- hosts: all
  tasks:
    - name: install httpd
      yum:
        name: httpd
        state: present
    - name: start httpd
      service:
        name: httpd
        state: started
        enabled: yes
    - name: start firewalld
      service:
        name: firewalld
        state: started
    - name: permit httpd on firewalld
      firewalld:
        service: http
        permanent: yes
        immediate: yes
        state: enabled
    - name: copy file httpd.conf to managed nodes
      copy:
        src: ./src/httpd.conf
        dest: /etc/httpd/conf/
      notify:
        - restart apache
    - name: line add in index.html to managed nodes
      lineinfile:
        path: /var/www/html/index.html
        line: <h1>welcome to {{hostname}}</h1>
        create: yes

  handlers:
    - name: restart apache
      service:
        name: httpd
        state: restarted

handler 출력 순서 확인

[vagrant@control sample]$ cat handler.yaml
- hosts: localhost
  tasks:
    - command: /bin/true
    - debug:
        msg: test messages 1
    - command: /bin/true
      notify: second handler
    - debug:
        msg: test messages 2
    - command: /bin/true
      notify: first handler
    - debug:
        msg: test messages 3

  handlers:
    - name: first handler
      debug:
        msg: first handler's message
    - name: second handler
      debug:
        msg: second handler's message
    - name: third handler
      debug:
        msg: third handler's message

test 1 > second handler > test 2 > first handler > test 3 로 적혀있지만

실제로는 test 1 > test 2 > test 3 > first handler > second handler 순으로 출력된다.

(그냥 모든 모듈이 먼저 출력이 된 후에 소환된 핸들러를 출력함)

[vagrant@control sample]$ ansible-playbook handler.yaml

TASK [debug] **************************************************************************************
ok: [localhost] => {
    "msg": "test messages 1"
}

TASK [debug] **************************************************************************************
ok: [localhost] => {
    "msg": "test messages 2"
}

TASK [debug] **************************************************************************************
ok: [localhost] => {
    "msg": "test messages 3"
}

RUNNING HANDLER [first handler] *******************************************************************
ok: [localhost] => {
    "msg": "first handler's message"
}

RUNNING HANDLER [second handler] ******************************************************************
ok: [localhost] => {
    "msg": "second handler's message"
}

 

 

 

'Ansible' 카테고리의 다른 글

centos, ubuntu, window node 생성 및 nfs  (0) 2024.02.15
실습  (0) 2024.02.14
Ansible Yaml  (0) 2024.02.07
Ansible 기본 설정 및 Ad-hoc  (0) 2024.02.06
Ansible 사전 작업 (VM생성) - Vagrant를 통해  (0) 2024.02.06

+ Recent posts