Sat. Jan 25th, 2025

Series Ansible – Bài 3 – Ansible playbook và cách sử dụng

By admin Mar 28, 2024
Ansibe

Xin chào các bạn, đây là bài thứ 3 trong series ansible của mình. Ở bài 1bài 2 mình đã giới thiệu với các bạn về Ansible và cách để cài đặt cũng như cách chạy một ad-hoc đơin giản trên các mát target. Trong bài này mình sẽ hướng dẫn các bạn setup một playbook đơn giản.Playbook Ansible chính là cách để sử dụng module hoàn thành một tác vụ. Nó là một tệp cấu hình được viết bằng YAML cung cấp các hướng dẫn về việc cần thực hiện trên các nút quản lý vào trạng thái mong muốn. Nó rất đơn giản, bạn có thể đọc được và tự ghi lại. Điều này có nghĩa Playbook có thể chạy trên hệ thống bất cứ lúc nào mà không gây ảnh hưởng tiêu cực.

Một số thuật ngữ trong Ansible

Dưới đây là danh sách một số thuật ngữ được Ansible sử dụng:

  • Control Node/Management Control : server cài đặt Ansible, chịu trách nhiệm cho việc “đưa các công việc bạn cung cấp đến các server từ xa mà bạn quản lý và chạy chúng” .Nói một cách dễ hiểu hơn thì đây là server mà bạn đứng trên đó và lệnh cho các server khác thực hiện các việc bạn muốn mà không cần trực tiếp đăng nhập vào chúng.
  • Inventory : Một file INI chứa các thông tin về các server từ xa mà bạn quản lý.
  • Playbook : Một file YAML chứa một tập các công việc cần tự động hóa.
  • Task : một task sẽ xác định một công việc đơn lẻ sẽ được thực hiện.
  • Module : Một Module sẽ trừu tượng hóa một tác vụ hệ thống. Ansible cũng cấp rất nhiều Module tích hợp để ta sử dụng nhưng nếu muốn bạn cũng có thể tự tạo Module. Nói cách khác, ta giao tiếp với Ansible thông qua các Module.
  • Role : Một tập hợp các Playbook, các template và các file khác, được tổ chức theo cách được xác định trước để tạo điều kiện tái sử dụng và chia sẻ.
  • Play : Một lần thực thi suôn sẻ từ đầu tới cuối được gọi là một play.
  • Facts : Các biến toàn cục chứa các thông tin về hệ thống, như các network interface hay operating system.
  • Handlers : Sử dụng để kích hoạt thay đổi trạng thái các service, như việc ta restart hay reload một service

Một đống các khái niệm khô khan.

Đọc qua chẳng có chút gì đọng lại được cả, đúng không?

Đễ dễ hiểu bạn có thế nhìn qua sơ đồ sau:

Ansible_Flow

Bạn đứng trên một Node Control và ra lệnh cho các server mà bạn quản lý. Tuy nhiên vấn đề đặt ra là số lượng thao tác cần thực hiện trên các server kìa thì nhiều, nhiều server có tác dụng,nhiệm vụ giống nhau nên cần thực hiện các tháo tác giống nhau. Vậy không lẽ bạn định gõ tay hàng trăm thậm chí hàng ngàn lệnh. Để rồi khi có một server mới, bạn lại gõ tay lại, chưa kể việc sai sót khi thao tác. Lúc này bạn sẽ cần viết một Playbook – nơi sẽ chứa chi tiết tất cả những gì bạn muốn làm với các server từ xa kia và cách thức thực hiện chúng Mỗi một thao tác trong Playbook gọi là một Task (Cài đặt, khởi động, dừng,….) Ta sử dụng Module để tạo thành Task (Ví dụ: muốn cài đặt một gói trên CentOs7 ta sử dụng Module yum của Ansible). Có việc cần làm rồi, giờ ta cần truyền thông tin chi tiết hơn về server cho Playbook chứ không thì làm sao nó biết sẽ làm việc với ai. Lúc này ta cần đến Inventory.

Vậy  ansible hoạt động như thế nào khi sử dụng playbook?

ansible_model

Tương tự như ad-hoc Ansible sẽ dùng SSH để chạy lệnh trên các server target thông qua cấu trúc của file playbook.

Thành phần cơ bản của 1 playbook.

Một tệp playbook Ansible có cấu trúc dựa trên cú pháp YAML. Cấu trúc chung của một tệp playbook bao gồm một loạt các mục sau:

  1. Khai báo ---: Tệp playbook Ansible bắt đầu bằng dòng --- để chỉ ra rằng đây là một tệp YAML.

  2. Khai báo name: Mục name cho phép bạn đặt tên cho playbook để mô tả mục đích hoặc công việc mà playbook thực hiện.

  3. Khai báo hosts: Mục hosts xác định tên của các máy chủ hoặc nhóm máy chủ mà playbook sẽ chạy trên. Nếu bạn xác định một nhóm máy chủ, các task sẽ được thực thi trên tất cả các máy chủ trong nhóm đó.

  4. Khai báo become (tùy chọn): Mục become xác định xem liệu playbook có cần chạy với quyền đặc quyền (privileged) hay không. Nếu become: yes được đặt, các task trong playbook sẽ được thực thi với quyền đặc quyền (thông qua sudo hoặc su).

  5. Các task: Các task là các công việc cụ thể mà playbook sẽ thực hiện. Mỗi task bao gồm một hoặc nhiều module Ansible và các tham số tương ứng. Một task có thể làm việc với các module như copyshellaptservice, và nhiều module khác. Mỗi task thường có một tên, một module và các tham số của module đó.

Cấu trúc mẫu của 1 file Ansible Playbook như sau

				
					---
- name: Tên playbook
  hosts: tên_máy_chủ
  become: yes

  tasks:
    - name: Tên task 1
      module1:
        tham_số_1: giá_trị_1
        tham_số_2: giá_trị_2

    - name: Tên task 2
      module2:
        tham_số_3: giá_trị_3
        tham_số_4: giá_trị_4
				
			

Dưới đây là một mẫu file ansible đơn giản để thực hiện update repo và cài một số packages cơ bản.

				
					---
- name : Ansible Playbook Demo #Ten cua Playbook
  hosts: target-server # Server hoac group Server thuc hien playbook
  become: true # Cap quyen thuc hien thao tac duoi quyen root
  task:
    - name: Update Repo
      apt:
        update_cache: yes
    - name: Install CURL
      apt:
        name: curl
        state: persent
    - name: Install nettool
        name: net-tools
        state: persent

				
			

Trong ví dụ trên, mình sử dụng modules apt của Ansible do mình sử dụng các target chạy hệ điều hành Ubutu 22, nếu bạn sử dụng CentOS7 thì bạn có thể sử dụng modules là yum. Ngoài ra để đáp ứng được nhu cầu thì các bạn có thể xem thêm nhiều modules và cách sử dụng của chúng tại trang tài liệu của Ansible.

Để chạy file ansible play book ta dùng lệnh sau:

ansible-playbook -i path_to_inventory_file path_to_playbook
  • -i : Chỉ định đường dẫn inventory file, mặc định nếu bạn không truyền tham số này vào sẽ sử dụng file host mặc định của ansible

Ví dụ khi chạy fie ansible mẫu trên như sau:

 

				
					[root@ansible]# ansible-playbook playbook_ansible.yaml
[WARNING]: Invalid characters were found in group names but not replaced, use -vvvv to see details

PLAY [Ansible Playbook Demo] **************************************************************************************************************************************

TASK [Gathering Facts] ********************************************************************************************************************************************
ok: [server1]
ok: [server2]

TASK [Update Repo] ************************************************************************************************************************************************
changed: [server1]
changed: [server2]

TASK [Install CURL] ***********************************************************************************************************************************************
ok: [server1]
ok: [server2]

TASK [Install nettool] ********************************************************************************************************************************************
changed: [server1]
changed: [server2]

PLAY RECAP ********************************************************************************************************************************************************
server1                    : ok=4    changed=2    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
server2                    : ok=4    changed=2    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0



				
			

Một số biến có thê sử dụng trong Playbook

Loop Item

Phần trước, thay vì viết module apt cho từng gói cài đặt. Giờ ta sẽ nhóm vào Item để chạy 1 lần luôn.

				
					### VD cho Ubuntu###
---
- hosts: allone
  become: yes

  tasks:
    - name: Install Apache.
      apt:
        name: "{{ item }}"
        state: present
      loop:
        - apache2
        - mysql-server
        - php
        - php-mysql
    - name: Restart Apache and Mysql
      service:
        name: "{{item}}"
        state:  running
      loop:
          - apache2
          - mysql


### VD cho Centos7###
--
- hosts: allone
  become: yes

  tasks:
    - name: Install Apache.
      yum:
        name: "{{ item }}"
        state: present
      loop:
        - nginx
        - redis
    - name: Restart Apache and Mysql
      service:
        name: "{{item}}"
        state:  restarted
      loop:
          - nginx
          - redis


				
			

Handlers

Handlers giúp chúng ta gọi lại hành động thực thi nhiều lần (notify) mà không cần phải viết lại.

				
					---
- hosts: allone
  become: yes

tasks:
    - name: Install Apache.
      apt:
        name: "{{ item }}"
        state: present
      loop:
        - apache2
        - mysql-server
        - php
        - php-mysql

    - name: deploy html file
      template:
        src: /tmp/index.html
        dest: /var/www/html/index.html
      notify: restart web

  handlers:
    - name: restart web
      service:
        name: "{{ item }}"
        state:  running
      loop:
          - apache2
          - mysql


### Ví dụ handlers cho Centos
---
- hosts: allone
  become: yes

  tasks:
    - name: Install Apache.
      yum:
        name: "{{ item }}"
        state: present
      loop:
        - nginx
        - redis
      notify: restart service

  handlers:
    - name: restart service
      service:
        name: "{{ item }}"
        state:  restarted
      loop:
        - nginx
        - redis


				
			

Nếu handlers không chạy (do file không có sự thay đổi), bạn hãy thử sửa file /tmp/index.html và chạy lại. Ansible nhận ra sự thay đổi của file index nên sẽ thực thi Handlers.

C.Variables và Template

Đặt giá trị cho biến cố định

 

				
					---
- hosts: allone
  become: yes

  vars:
     - domain_name: "thanhdan.name.vn"
     - index_file: "index.html"
     - config_file: "thanhdan.conf"

  tasks:
    - name: Install Apache.
      apt:
        name: "{{ item }}"
        state: present
      loop:
        - apache2
        - mysql-server
        - php
        - php-mysql

    - name: deploy html file
      template:
        src: /tmp/{{ index_file }}
        dest: /var/www/html/index.html
      notify: restart web

  handlers:
    - name: restart web
      service:
        name: "{{ item }}"
        state:  running
      loop:
          - apache2
          - mysql

				
			

Sử lại file index.html ở trên server ansible.

vim /tmp/index.html

				
					This is <BR>
FILE_NAME: {{ index_file }} <BR>
DOMAIN NAME: {{ domain_name }} <BR>

				
			

Kết quả cho ta biết là Variable có thể ăn đến tận file được deploy nhờ Template.

Fact và when

Ở đây ta sẽ dùng Fact để lấy thông tin và dùng when để thiết lập varriable. Ta có nhìn qua thông tin của Fact client bằng lệnh sau

				
					#ansible 192.168.1.59 -m setup

				
			
				
					---
- hosts: allone
  become: yes

  tasks:
    - name: Define Red Hat.
      set_fact:
         package_name: "httpd"
      when:
         ansible_os_family == "Red Hat"

    - name: Define Debian.
      set_fact:
         package_name: "apache2"
      when:
         ansible_os_family == "Debian"

    - name: Stop apache
      service:
        name: "{{ package_name }}"
        state: stopped


				
			
				
					#ansible 192.168.1.59 -m setup

				
			

Một số Module Ansible thuòng được sử dụng

Module 1: Package management

Đây là module được thiết kế cho hầu hết các trình quản lý gói (package management) phổ biến, chẳng hạn như apt, dnf,… cho phép bạn cài đặt các package trên hệ thống. Ngoài các chức năng cụ thể của từng trình quản lý gói thì hầu hết các trình quản lý gọi đều có thể install, update, upgrade, downgrade, remove, và list các packages.

Ví dụ, ở đây, mình có một task là install gói httpd trên CentOS/RHEL 8 sử dụng trình quản lý gói dnf.

				
					- hosts: all
  user: ansible
  become: True
  tasks:
    - name: Install httpd package
      dnf:
        name: httpd
        state: present
        update_cache: True

				
			

Module 2: Flie

Trong Ansible, có nhiều các module làm việc với tệp tin, thư mục, links trên các node đích (node client) như copy, template, file,… thường được sử dụng. Trước tiên, chúng ta sẽ cùng tìm hiểu về file module. File module giúp quản lý tập tin và các thuộc tính của nó. Ngoài việc taọ, xóa, xác định vị trí của tệp tin file module cũng đặt các quyền và quyền sở hữu hay thiết lập symlinks cho tệp tin.

Ví dụ,

				
					- hosts: all
  user: ansible
  become: True
  tasks:
    - name: Change file ownership, group and permissions
      file:
        path: /etc/thuntt.config
        owner: danht
        group: systemadmin
        mode: '0644'

    - name: Create an insecure file
      file:
        path: /vnh
        owner: root
        group: root
        mode: '1777'

    - name: Create a symbolic link
      file:
        src: /file/to/link/to
        dest: /path/to/symlink
        owner: danht
        group: systemadmin
        state: link

				
			

Module 3: Template

Có nhiều cách khác nhau với Ansible giúp bạn có thể thao tác với nội dung của tệp, ngoài template module thì mình còn thấy lineinfile module cũng rất phổ biến và được sử dụng nhiều. Tuy nhiên, đối với mình, sau khi sử dụng thì mình cảm thấy template module rõ ràng và dễ hiểu hơn khá nhiều so với lineinfile module.Template trong Ansible là một tệp chứa tất cả các tham số cấu hình của bạn, nhưng các giá trị động được cung cấp dưới dạng biến. Trong quá trình thực thi playbook, các biến có thể được thay thế bằng các giá trị bạn cần. Ngoài ra, bạn có thể làm được nhiều việc hơn là thay thế các biến, với sự trợ giúp của công cụ tạo template Jinj2. Bạn có thể có các câu lệnh có điều kiện, vòng lặp, viết macro, bộ lọc để chuyển đổi dữ liệu, thực hiện các phép tính số học, v.v. Các tệp template thường sẽ có phần mở rộng là .j2. Các biến trong tệp template sẽ được ký hiệu bằng dấu ngoặc nhọn kép, ‘{{biến}}’.

				
					- hosts: all
  vars:
    variable_to_be_replaced: 'Hello world'
    inline_variable: 'hello again'
  tasks:
    - name: Ansible Template Example
      template:
        src: hello_world.j2
        dest: /Users/mdtutorials2/Documents/Ansible/hello_world.txt

hello_world.j2
--------------
{{ variable_to_be_replaced }}
This line won't be changed
Variable given as inline - {{ inline_variable }} - 🙂

output - hello_world.txt
------
Hello world
This line won't be changed
Variable given as inline - hello again - 🙂

mdtutorials2$ ls -lrt hello_world.txt
-rw-r--r--  1 root  wheel  81 Oct 16 07:23 hello_world.txt

				
			

Module 4: Copy

Copy module là module thường được sử dụng khi chúng ta muốn sao chép một tệp tin từ Ansible server (Management node) đến các node đích (client node).

Ví dụ:

				
					- name: copy file from local to remote with owner, group and file permissions (octal)
  copy:
    src: test_file
    dest: $HOME/test_file
    owner: danht
    group: danht
    mode: 0644

- name: copy file from local to remote with owner, group and file permissions (octal)
  copy:
    src: test_file
    dest: $HOME/test_file
    owner: danht
    group: danht
    mode: 0644

- name: copy file from local to remote with root as the owner (become required)
  copy:
    src: test_file
    dest: "/home/{{ ansible_user }}/test_file"
    owner: root
    group: root
    mode: 0644
  become: true

				
			

Modlue 5: Service

Đối với các node client là Unix/Linux, service module là một module rất hữu ích giúp kiểm soát các service chạy trên các server này. Giống với các module khác, service module cũng đi kèm với một số tham số và các tham số này có các tùy chọn riêng hoặc giá trị phù hợp. Sử dụng các tham số này và các giá trị bắt buộc, các banj có thể quản lý các service với các chức năng như stop, start, reload, … trên các node client.

Ví dụ:

				
					- name: Start service httpd, if not running
  service:
    name: httpd
    state: started

- name: Stop service httpd, if running
  service:
    name: httpd
    state: stopped

- name: Restart service httpd, in all cases
  service:
    name: httpd
    state: restarted

- name: Reload service httpd, in all cases
  service:
    name: httpd
    state: reloaded

- name: Enable service httpd, and not touch the running state
  service:
    name: httpd
    enabled: yes

				
			

Module 6: shell

Trong Ansible, chúng ta có shell module được sử dụng để chạy các lệnh thông qua shell (/bin/sh) trên các máy đích từ xa. Module này nhận các lệnh làm đầu vào cùng với một tập hợp các đối số.

Ví dụ:

				
					- name: Execute the command in remote shell; stdout goes to the specified file on the remote.
  shell: somescript.sh >> somelog.txt

- name: Change the working directory to somedir/ before executing the command.
  shell: somescript.sh >> somelog.txt
  args:
    chdir: somedir/

				
			

Ansible-Roles và Ansible-galaxy

   Ansible roles :

Roles một cách đơn giản luôn, bạn có thể hiểu đơn giản là mỗi một ứng dụng, tool,… đều sẽ tạo thành 1 role vậy tương ứng

  • Role Directory Structure

image 110
  1. Thư mục “tasks“: Thư mục này chứa các tệp tin YAML mà định nghĩa danh sách các tác vụ mà Ansible sẽ thực hiện trên các máy chủ mục tiêu. Các tác vụ này được liệt kê theo thứ tự và sẽ được thực thi một cách tuần tự.
  2. Thư mục “handlers“: Thư mục này chứa các tệp tin YAML định nghĩa các handlers, các tác vụ được kích hoạt khi có sự thay đổi hoặc thông báo từ các tác vụ khác. Handlers thường được sử dụng để khởi động lại dịch vụ hoặc thực hiện các hành động khác khi cấu hình thay đổi.
  3. Thư mục “library“: Thư mục này chứa các module mở rộng hoặc script tùy chỉnh có thể được sử dụng trong các tác vụ của role. Các module mở rộng có thể cung cấp chức năng bổ sung mà Ansible không hỗ trợ sẵn.
  4. Thư mục “files“: Thư mục này chứa các tệp tin tĩnh (không phải tệp tin template) mà cần được sao chép từ máy điều khiển Ansible đến máy chủ mục tiêu. Các tệp tin này có thể là các script, file cấu hình, hoặc tài nguyên khác cần thiết cho role.
  5. Thư mục “templates“: Thư mục này chứa các tệp tin template Jinja2. Các tệp tin template cho phép tạo ra các tệp tin động bằng cách kết hợp dữ liệu và biến từ Ansible với cú pháp Jinja2.
  6. Thư mục “vars“: Thư mục này chứa các tệp tin YAML chứa các biến cục bộ cho role. Các biến này có thể được sử dụng trong các tác vụ và templates trong role.
  7. Thư mục “defaults“: Thư mục này chứa các tệp tin YAML định nghĩa các giá trị mặc định cho role. Các giá trị mặc định có thể được ghi đè bởi biến trong inventory hoặc khi triển khai role.
  8. Tệp tin “meta“: Tệp tin này chứa thông tin mô tả về role và các phụ thuộc của nó. Nó có thể chứa các định nghĩa về các role cần được chạy trước hoặc sau role hiện tại, các phụ thuộc gói và phiên bản Ansible yêu cầu, tác giả, mô tả và các thông tin khác.

Role search path

Bạn phải khai báo việc set role chính xác trong ansible.cfg để ansible có thể hiểu được bạn viết role và thực thi nó.

Using Roles

Bạn có thể sử dụng role theo cách sau .

 

				
					             ---
             - hosts: dev
               roles:
                 - nginx

				
			

Ansible Galaxy

Ansible Galaxy là một kho lưu trữ trực tuyến chứa các roles và các bộ sưu tập (collections) có thể được sử dụng bởi cộng đồng Ansible. Nó cung cấp một cách tiện lợi để chia sẻ và tái sử dụng các tài nguyên Ansible đã được phát triển trước đó.

 

Install Role

 

Bạn dùng command ansible-galaxy để download role từ Galaxy :
ansible-galaxy install geerlingguy.nginx

Để xem danh sách các role được install thì bạn dùng :
ansible-galaxy list

Create Role

Như hướng dẫn ở trên phần Role thì bạn có thể dùng command này :
ansible-galaxy init __template__

Search for Roles

Để tìm kiếm 1 role thì bạn có thể sử dụng command sau :
ansible-galaxy search apache --author geerlingguy

 

Trên đây là những modules thường xuyên được sử dụng nhất. Ngoài ra để đáp ứng được nhu cầu thì các bạn có thể xem thêm nhiều modules và cách sử dụng của chúng tại trang tài liệu của Ansible.

Ở bài tiếp theo mình sẽ ứng dụng ansible để cài đặt LAMP stack và triển khai wordpress. Các bạn nhớ chú ý đón xem nhé.

Tài liệu tham khảo :
https://docs.ansible.com/ansible/latest/index.html
[Book]

  • Ansible Up And Running Book
  • Ansible Playbook Essentials
  • Learning Ansible – Use Ansible to Configure Systems Deploy Software and Orchestrate Advanced IT Tasks

By admin

Related Post

Leave a Reply

Your email address will not be published. Required fields are marked *

error: Content is protected !!
Don`t copy text!