Site logo

Ansible Playbooks Phần 3: Conditionals, Loops và Tags

5:00 read

Phần 3 tập trung vào control flow với Conditionals, Loops và Tags để tạo playbooks linh hoạt và mạnh mẽ.

Phần 3: Conditionals, Loops và Tags:

  • Conditionals (when) cho control flow
  • Loops: simple, dictionaries, nested
  • Loop với conditionals và register
  • Tags cho selective execution
  • Blocks và error handling (block/rescue/always)
  • Ví dụ multi-tier deployment

Conditionals (Điều kiện)

Chạy task chỉ khi điều kiện thỏa mãn sử dụng when.

Basic conditionals

tasks:
  - name: Install Apache on Debian/Ubuntu
    apt:
      name: apache2
      state: present
    when: ansible_os_family == "Debian"

  - name: Install Apache on RedHat/CentOS
    yum:
      name: httpd
      state: present
    when: ansible_os_family == "RedHat"

  - name: Start service only on production
    service:
      name: nginx
      state: started
    when: env == "production"

Multiple conditions với and

tasks:
  - name: Install package on Ubuntu 20.04
    apt:
      name: nginx
      state: present
    when:
      - ansible_distribution == "Ubuntu"
      - ansible_distribution_version == "20.04"

  # Hoặc viết trên một dòng
  - name: Same as above
    apt:
      name: nginx
      state: present
    when: ansible_distribution == "Ubuntu" and ansible_distribution_version == "20.04"

Multiple conditions với or

tasks:
  - name: Install on Debian or Ubuntu
    apt:
      name: nginx
      state: present
    when: ansible_distribution == "Debian" or ansible_distribution == "Ubuntu"

  # Hoặc dùng list
  - name: Install on Debian family
    apt:
      name: nginx
      state: present
    when: ansible_distribution in ["Debian", "Ubuntu"]

Conditions với registered variables

tasks:
  - name: Check if nginx is installed
    command: which nginx
    register: nginx_check
    ignore_errors: yes

  - name: Install nginx if not present
    apt:
      name: nginx
      state: present
    when: nginx_check.rc != 0

  - name: Check disk usage
    shell: df -h / | awk 'NR==2 {print $5}' | sed 's/%//'
    register: disk_usage

  - name: Warning if disk > 80%
    debug:
      msg: "WARNING: Disk usage is {{ disk_usage.stdout }}%"
    when: disk_usage.stdout|int > 80

Conditions với facts

tasks:
  - name: Install specific version on old Ubuntu
    apt:
      name: nginx=1.18.0-0ubuntu1
      state: present
    when:
      - ansible_distribution == "Ubuntu"
      - ansible_distribution_major_version|int < 22

  - name: Set timezone on physical machines
    timezone:
      name: Asia/Ho_Chi_Minh
    when: ansible_virtualization_role != "guest"

Conditions với file checks

tasks:
  - name: Check if config exists
    stat:
      path: /etc/nginx/nginx.conf
    register: config_file

  - name: Backup config if exists
    copy:
      src: /etc/nginx/nginx.conf
      dest: /etc/nginx/nginx.conf.backup
      remote_src: yes
    when: config_file.stat.exists

  - name: Create config if not exists
    copy:
      src: templates/nginx.conf
      dest: /etc/nginx/nginx.conf
    when: not config_file.stat.exists

Conditions với boolean

vars:
  install_monitoring: true
  enable_ssl: false

tasks:
  - name: Install monitoring agent
    apt:
      name: node-exporter
      state: present
    when: install_monitoring

  - name: Configure SSL
    template:
      src: ssl.conf.j2
      dest: /etc/nginx/ssl.conf
    when: enable_ssl | bool

Loops

Lặp qua danh sách items để thực thi task nhiều lần.

Simple loop

- name: Install multiple packages
  apt:
    name: "{{ item }}"
    state: present
  loop:
    - nginx
    - git
    - vim
    - htop
    - curl

Loop với dictionaries

- name: Create multiple users
  user:
    name: "{{ item.name }}"
    state: present
    groups: "{{ item.groups }}"
    shell: "{{ item.shell }}"
  loop:
    - { name: 'john', groups: 'developers', shell: '/bin/bash' }
    - { name: 'jane', groups: 'admins', shell: '/bin/bash' }
    - { name: 'bob', groups: 'developers', shell: '/bin/zsh' }

- name: Create directories with permissions
  file:
    path: "{{ item.path }}"
    state: directory
    owner: "{{ item.owner }}"
    mode: "{{ item.mode }}"
  loop:
    - { path: '/opt/app', owner: 'appuser', mode: '0755' }
    - { path: '/var/log/app', owner: 'appuser', mode: '0755' }
    - { path: '/etc/app', owner: 'root', mode: '0644' }

Loop với variables

vars:
  packages:
    - nginx
    - postgresql
    - redis
  
  users:
    - alice
    - bob
    - charlie

tasks:
  - name: Install packages
    apt:
      name: "{{ item }}"
      state: present
    loop: "{{ packages }}"

  - name: Create users
    user:
      name: "{{ item }}"
      state: present
    loop: "{{ users }}"

Loop với conditionals

- name: Install packages only on Ubuntu
  apt:
    name: "{{ item }}"
    state: present
  loop:
    - nginx
    - apache2
    - mysql-server
  when: ansible_distribution == "Ubuntu"

- name: Create users only in production
  user:
    name: "{{ item }}"
    state: present
  loop:
    - produser1
    - produser2
  when: env == "production"

Loop với register

- name: Check multiple services
  systemd:
    name: "{{ item }}"
  register: service_status
  loop:
    - nginx
    - mysql
    - redis

- name: Display service status
  debug:
    msg: "{{ item.item }} is {{ item.status.ActiveState }}"
  loop: "{{ service_status.results }}"

Nested loops

- name: Create files in multiple directories
  file:
    path: "{{ item.0 }}/{{ item.1 }}"
    state: touch
  loop: "{{ directories | product(files) | list }}"
  vars:
    directories:
      - /tmp/dir1
      - /tmp/dir2
    files:
      - file1.txt
      - file2.txt

Loop control

- name: Install packages with index
  apt:
    name: "{{ item }}"
    state: present
  loop:
    - nginx
    - git
    - vim
  loop_control:
    index_var: idx
    label: "Installing {{ item }}"

- name: Process with pause between iterations
  command: process_item.sh {{ item }}
  loop:
    - item1
    - item2
    - item3
  loop_control:
    pause: 5  # Pause 5 seconds between iterations

Loop until

- name: Wait for service to be ready
  uri:
    url: http://localhost:8080/health
    status_code: 200
  register: health_check
  until: health_check.status == 200
  retries: 10
  delay: 5  # Wait 5 seconds between retries

Yêu cầu đăng nhập

Vui lòng đăng nhập để truy cập nội dung này

Additional Resources

Course Guide

Comprehensive PDF guide with examples

GitHub Repository

Example code for all lessons

Discussion

Have a question about this lesson? Post it here and get answers from instructors and peers.