Basic Usage of Ansible Playbook

Introduction to Ansible Playbook

A Playbook is a component of Ansible used for configuration management. While Ansible’s AD-Hoc command functionality is powerful and can accomplish some basic configuration management tasks, AD-Hoc commands cannot support the configuration management of complex environments. In our practical use of Ansible, most of the time is spent writing Playbooks.

In simple terms, a Playbook is the foundation of a very simple configuration management and multi-machine deployment system, making it very suitable for deploying complex applications.

A Playbook script consists of a list of one or more “plays”.

The main function of a play is to dress a predefined set of hosts in roles defined in advance through tasks in Ansible. A task is essentially a call to an Ansible module, and by organizing multiple plays in a Playbook, they can work together to execute predefined actions according to a pre-arranged mechanism.

Basic Usage of Ansible Playbook

Core Components of a Playbook

A Playbook consists of multiple components, with common component types as follows:

  • Hosts: List of remote hosts on which to execute.

  • Tasks: A list of tasks, each task is a dictionary, and a complete code block must include at least the elements name and task; one name can only include one task.

  • Variables: Built-in or custom variables called within the Playbook.

  • Templates: Files that can replace variables in template files and implement some simple logic.

  • Handlers and notify: Operations triggered by specific conditions, executed only if conditions are met.

  • Tags: Specify which task to execute, used to select parts of the code to run in the Playbook. Ansible has idempotency, so it will automatically skip unchanged parts; however, some code may still take a long time to test for changes. If you are sure there are no changes, you can skip this code segment using tags.

---  - name: Playbook      # Name of the Playbook     hosts: webservers   # Host group to execute the Playbook     become: yes         # Whether to execute sudo     become_user: root   # User after executing sudo    tasks:              # List of tasks included in this Playbook       - name: ensure apache is at the latest version  # Task 1: Install the latest version of httpd         yum:          name: httpd          state: latest      - name: ensure apache is running               # Task 2: Start the httpd service         service:          name: httpd          state: started

Hosts Component

The purpose of each play in a Playbook is to allow specific hosts to execute tasks as a specified user. Hosts are used to specify which hosts to execute the specified tasks, which must be defined in the inventory beforehand.

web-01.example.comweb-01.example.com:web-02.example.com192.168.11.10192.168.11.*       web_srvs:db_srvs    # or  Union of two groupsweb_srvs:&db_srvs   # and Intersection of two groupsweb_srvs:!db_srvs   # In web_srvs group, but not in db_srvs group

Remote User Component

This can be used in either the Host or task. By default, Ansible uses the user executing the tasks on the control node to connect to the managed node. If you need to change this, you can use remote_user to specify the user, and you can also use become_user to switch users when executing specific tasks.

- hosts: web_srvs
  remote_user: root  # Log in as root user via SSH
  become: yes        # Enable privilege escalation
  become_user: chijinjing  # Switch to chijinjing user to execute tasks

  tasks:
    - name: Create a file
      file:
        path: /home/chijinjing/testfile.txt
        state: touch
        owner: chijinjing
        group: chijinjing
        mode: '0644'

Task List and Action Component

The main part of a play is the task list, which contains one or more tasks. Each task is executed sequentially on all hosts specified in the hosts, meaning that after completing the first task on all hosts, it will start the second task.

The purpose of a task is to execute a module with specified parameters, and variables can be used in the module parameters. Module execution is idempotent, meaning that multiple executions are safe as the results are consistent.

Each task should have its name for outputting the execution results of the Playbook, and it is recommended that the content clearly describes the steps of the task execution.

Tasks support two formats:

action: module args       # Example: action: shell echo hello 
module: args          # Example: shell: echo hello Recommended to use 

Usage examples:

- hosts: web
  remote_user: root
  gather_facts: no 

  tasks:
  - name: test network connection 
    ping:
  - name: execute demo command 
    command: echo "hello world!"
- hosts: web
  remote_user: root
  gather_facts: no 

  tasks:
  - name: install httpd  
    yum: name=httpd
  - name: start httpd 
    service: name=httpd state=started enabled=yes

Ansible-Playbook Command

ansible-playbook  [options] playbook.yaml 

Common parameters:

--list-hosts           # List the hosts running the tasks 
--list-tags            # List the tags included in the Playbook 
--list-tasks           # List the tasks included in the Playbook 
--syntax-check         # Syntax check of the Playbook 
-C, --check            # Simulate execution
-t TAGS, --tags TAGS   # Only run specified tags 
-v  -vv  -vvv          # Show detailed information, debug 

Playbook Examples

Example-1: Install a Single Software Package

---
 - hosts: web 
   # Switch to root user
   become: yes
   
   # Task list 
   tasks:
     - yum:  # Module name 
         name: wget     # Package name
         state: absent  # Installation state

Example-2: Install Multiple Software Packages on Different Managed Nodes

---
- hosts: db
  become: yes
  tasks:
  - yum: 
      name: wget
      state: latest
  - yum: 
      name: vim
      state: latest

- hosts: web
  become: yes
  tasks:
  - yum: 
      name: httpd
      state: latest

Example-3: Do Not Gather Facts from Managed Nodes

---
- hosts: web
  become: yes
  gather_facts: false
  tasks:
  - yum: 
      name: wget 
      state: absent

Example-4: Assign Unique Names to Plays and Tasks

---
 - name: Hello Playbook 
   hosts: web
   gather_facts: false
   tasks:
   - name: Copy file to web group
     copy: 
       src: /tmp/demo.txt  
       dest: ~/
   - name: Create an empty file on web group
     file: 
       path: /tmp/src_file.txt 
       state: touch

Example-5: Print Debug Information from Playbooks

---
 - name: debug demo
   hosts: web
   tasks:
   - debug: 
       msg: "Hello World"

Output multiple lines of information

---
- name: debug demo 
  hosts: web
  tasks:
  - debug:
      msg:
       - "This is first line"
       - "This is second line"
       - "This is third line"

Example-6: Increase the Log Level of Playbooks


---
 - hosts: web
   tasks:
   - name: default verbose
     debug:
       msg:
       - This is a test message without verbosity
   - name: verbosity level 2
     debug:
       msg:
       - This is a test message with verbosity level 2
       verbosity: 2

To execute, add the -vv parameter

Example-7: Execute Syntax Check:

--- - hosts: all   tasks:      - debug:       msg: "Hello World"

Executing the Playbook may show the following error

[root@jenkins hello-playbook]# ansible-playbook 07-example.yaml  --syntax-checkERROR! We were unable to read either as JSON nor YAML, these are the errors we got from each:JSON: No JSON object could be decodedSyntax Error while loading YAML.  did not find expected '-' indicatorThe error appears to be in '/etc/ansible/playbooks/hello-playbook/07-example.yaml': line 5, column 7, but maybe elsewhere in the file depending on the exact syntax problem.The offending line appears to be:     - debug:      msg: "Hello World"      ^ here

Example-8: Simulate Testing Playbooks

---
- hosts: web
  tasks:
  - name: Install telnet
    yum: name=telnet state=latest
[root@jenkins hello-playbook]# ansible-playbook 08-example.yaml  --check
[WARNING]: Could not match supplied host pattern, ignoring: web

PLAY [demo playbook] ****************************************************************************************************************************************
skipping: no hosts matched

PLAY RECAP **************************************************************************************************************************************************

Not all modules support check mode, but all major modules do, and more modules are added with each version. It is particularly important to note that the command module and shell module do not support check mode because these modules cannot determine which commands will cause changes and which will not. Therefore, these modules always return changed when run outside of check mode, as they assume changes have already been made.

Examples of Using Playbooks

Using Playbook to Install Nginx

  1. Add Nginx yum repository

  2. Install Nginx

  3. Start Nginx

---- name: Install and configure Nginx  hosts: nginx  become: yes   tasks:    - name: Add Nginx official repository      yum_repository:        name: nginx stable repo         description: Nginx Official Repository        baseurl: http://nginx.org/packages/centos/$releasever/$basearch/        gpgcheck: yes        gpgkey: https://nginx.org/keys/nginx_signing.key        enabled: yes              - name: Install Nginx      package:        name: nginx        state: present    - name: Start Nginx service      service:        name: nginx        state: started        enabled: yes

Using Playbook to Install MySQL

---- name: Install and configure MySQL 8  hosts: mysql  become: yes    vars:    new_mysql_root_password: jIJQiP$iSiralimofpiw+oS0rJa  tasks:    - name: Copy yum repo rpm       copy:        src: mysql84-community-release-el7-1.noarch.rpm        dest: /tmp/mysql84-community-release-el7-1.noarch.rpm    - name: Install repo rpm       package:        name: /tmp/mysql84-community-release-el7-1.noarch.rpm        state: present     - name: Install MySQL       package:         name: "{{item}}"         state: present      loop:        - mysql-community-server-8.4.4        - mysql-community-client-8.4.4    - name: Create directory      file:        path: /data/mysql/        state: directory        mode: '0755'        owner: mysql        group: mysql    - name: copy config file      copy:        src: my.cnf        dest: /etc/my.cnf    - name: start and enable mysql service      service:         name: mysqld         state: started         enabled: yes

Leave a Comment