Playbook

来自linux中国网wiki
Evan讨论 | 贡献2025年3月27日 (四) 08:38的版本 →‎常用 role 及playbook 例子
(差异) ←上一版本 | 最后版本 (差异) | 下一版本→ (差异)
跳到导航 跳到搜索

通过ansible命令执行操作的方式 call ad-hoc

简单例子

在线playbook分享平台:https://galaxy.ansible.com

ansible tree  ansible-nginx 
ansible-nginx
├── files
│   └── nginx.conf.j2
└── playbook.yml

1 directory, 2 files

➜  ansible-nginx cat files/nginx.conf.j2 
server {
  listen 80;

  root /tmp/;
  index index.html index.htm;

  server_name a.com;
  
  location / {
   default_type "text/html";
   try_files $uri.html $uri $uri/ =404;
  }
}

➜  ansible-nginx cat playbook.yml 
---
- hosts: d11
  name: playbook demo
  become: yes
  gather_facts: false
  remote_user: root
  become_user: root 
  tasks:
    - name: Update apt cache and install Nginx
      apt:
        name: nginx
        state: latest
        update_cache: yes

    - name: Apply Nginx template
      template:
        src: files/nginx.conf.j2
        dest: /etc/nginx/sites-available/default
      notify: Restart Nginx

    - name: Enable new site
      file:
        src: /etc/nginx/sites-available/default
        dest: /etc/nginx/sites-enabled/default
        state: link
      notify: Restart Nginx

    - name: Allow all access to tcp port 80
      ufw:
        rule: allow
        port: '80'
        proto: tcp

  handlers:
    - name: Restart Nginx
      service:
        name: nginx
        state: restarted


ansible-playbook -C  playbook.yml
ansible-playbook   playbook.yml



galaxy.ansible

找几个例子看看

https://galaxy.ansible.com/andrewrothstein/java-oracle-jdk


https://galaxy.ansible.com/sansible/golang

#快速创建role文件与目录
  ansible ansible-galaxy init  --init-path playbooks/roles web 
- Role web was created successfully
➜  ansible 

 ansible tree playbooks/roles/web 
playbooks/roles/web
├── defaults
│   └── main.yml
├── files
├── handlers
│   └── main.yml
├── meta
│   └── main.yml
├── README.md
├── tasks
│   └── main.yml
├── templates
├── tests
│   ├── inventory
│   └── test.yml
└── vars
    └── main.yml

8 directories, 8 files


基本语法

变量

---
- name: Install Apache on Ubuntu using variables
  hosts: web   # 替换成你的目标主机组名或主机名
  become: true  # 以特权用户执行任务
  vars:
    apache_package: apache2
    apache_service: apache2

  tasks:
    - name: Install Apache
      ansible.builtin.package:
        name: "{{ apache_package }}"
        state: present

    - name: Start and enable Apache service
      ansible.builtin.service:
        name: "{{ apache_service }}"
        state: started
        enabled: true


---
- name: Remove the apache package
  hosts: evan
  become: true  # 以特权用户执行任务
  vars:
    apache_package: apache2
    apache_service: apache2

  tasks:
    - name: Remove the apache package
      ansible.builtin.package:
        name: "{{ apache_package }}"
        state: absent
    

3.4.4 条件语句 when

#如果是debian类,关机
playbooks cat when.yml 
---
- name: shtudown 
  hosts: pi3
  tasks:
    - name: shutdown if debian 
      command: /sbin/shutdown -t now 
      when: ansible_os_family =="Debian"


#更加好的例子
---
- name: Install vim
  hosts: all
  tasks:
    - name:Install VIM via yum
      yum: 
        name: vim-enhanced 
        state: installed
      when: ansible_os_family =="RedHat"
      
    - name:Install VIM via apt
      apt: 
        name: vim 
        state: installed
      when: ansible_os_family =="Debian"
      
    - name: Unexpected OS family
      debug: msg="OS Family {{ ansible_os_family }} is not supported" fail=yes
      when: not ansible_os_family =="RedHat" or ansible_os_family =="Debian"

*************
利用when 判断文件在不在 
- name: Execute task only if a file exists
  hosts: evan
  tasks:
    - name: Check if file exists
      stat:
        path: /tmp/myfile.txt
      register: file_check

    - name: Do something if file exists
      debug:
        msg: "File /tmp/myfile.txt exists!"
      when: file_check.stat.exists




PLAY [Execute task only if a file exists] ****************************************************

TASK [Gathering Facts] ***********************************************************************
ok: [192.168.10.74]
ok: [192.168.10.93]

TASK [Check if file exists] ******************************************************************
ok: [192.168.10.74]
ok: [192.168.10.93]

TASK [Do something if file exists] ***********************************************************
skipping: [192.168.10.74]
skipping: [192.168.10.93]

PLAY RECAP ***********************************************************************************
192.168.10.74              : ok=2    changed=0    unreachable=0    failed=0    skipped=1    rescued=0    ignored=0   
192.168.10.93              : ok=2    changed=0    unreachable=0    failed=0    skipped=1    rescued=0    ignored=0  


ansible evan -m shell -a "touch /tmp/myfile.txt"
touch 文件之后 

TASK [Do something if file exists] *****************************************************************************************************
ok: [192.168.10.74] => {
    "msg": "File /tmp/myfile.txt exists!"
}
ok: [192.168.10.93] => {
    "msg": "File /tmp/myfile.txt exists!"
}



Ansible14:Playbook条件语句

3.4.5循环控制

Loops (循环)

使用 loop 或 with_items 可以在 Playbook 中进行循环操作。


一般书上都是用with_item 
cat loop-user2.yml 
---
- name: create user
  hosts: pi3
  tasks:
    - name: create user
      user:
        name: "{{ item }}"
        state: present
      with_items:
      - user04
      - user05
      - user06

    - name: set password
      shell: echo 'e12345678' | passwd --stdin "{{ item }}"
      with_items:
      - user04
      - user05
      - user06



➜  ansible cat loop-user.yml 
---
- name: create user
  hosts: pi3
  tasks:
    - name: create user
      user:
        name: "{{ item }}"
        state: present
      loop:
      - user01
      - user02
      - user03

    - name: set password
      shell: echo 'e12345678' | passwd --stdin "{{ item }}"
      loop:
      - user01
      - user02
      - user03


ansible-playbook -C  loop-user.yml
ansible-playbook   loop-user.yml


执行后查看结果 

root@mypi3b:~# cat /etc/passwd | grep user
root@mypi3b:~# 
root@mypi3b:~# cat /etc/passwd | grep user
user01:x:1003:1004::/home/user01:/bin/sh
user02:x:1004:1005::/home/user02:/bin/sh
user03:x:1005:1006::/home/user03:/bin/sh
root@mypi3b:~# su  - user01
$ hostname
mypi3b
$ id 
uid=1003(user01) gid=1004(user01) groups=1004(user01)



利用loop 安装多个软件  例如 os init etc 
- name: Install multiple packages
  hosts: evan
  become: yes
  vars:
    packages:
      - vim
      - wget
      
  tasks:
    - name: Install packages using loop
      package:
        name: "{{ item }}"
        state: present
      loop: "{{ packages }}"

3.4.6 include语法

playbook中代码复用非常爽,eg task   
---
- tasks:
   - include: a.yml user=root
   - include: b.yml user=root
   - include: c.yml user=root


或者是下面的多个项目用一个脚本的例子 


➜  playbooks cat  restart_ng.yml 
- name: Restart ng Server 
  service: 
    name: nginx 
    state: restarted


➜  playbooks cat a.yml 
- hosts: pi3 
  tasks: 
    - name: A Project command 
      command: echo "A" 
      
    - name: Restart ng 
      include: restart_ng.yml
➜  playbooks cat b.yml 
- hosts: mytmp 
  tasks: 
    - name: A Project command 
      command: echo "A" 
      
    - name: Restart ng 
      include: restart_ng.yml

ansible-playbook a.yml
ansible-playbook b.yml


成功执行后 查看结果 

nsible pi3 -m shell  -a "systemctl status nginx"
192.168.10.5 | CHANGED | rc=0 >>
● nginx.service - A high performance web server and a reverse proxy server
   Loaded: loaded (/lib/systemd/system/nginx.service; enabled; vendor preset: enabled)
   Active: active (running) since Thu 2023-08-24 12:59:57 CST; 3min ago







Inlcude结合tags应用

”include”不仅能够引用任务列表,还能够引用playbook,比如,在一个playbook中引用另一个playbook。

示例:通过指定标签 tags ,来说明是安装 tomcat8 还是 tomcat9

1.准备入口 main.yml 文件,然后包含 install_tomcat8.yml 以及install_tomcat9.yml

2.在执行 main.yml 时,需要通过 --tags 指明要安装的版本

3.还可以在主playbook文件中向引用的playbook传递变量。

    编写main.yml入口文件:
# cat tomcat_main.yml
- name: Install Tomcat8
  import_playbook: install_tomcat8.yml
  tags: tomcat8
  vars:
    tomcat_version: 8.5.69
    tomcat_install_path: /usr/local

- name: Install Tomcat9
  import_playbook: install_tomcat9.yml
  tags: tomcat9
  vars:
    tomcat_version: 9.0.50
    tomcat_install_path: /usr/local

编写install_tomcat8.yml文件
cat install_tomcat8.yml 
---
- hosts: localhost
  
  tasks:
    - name: Install JDK
      yum:
        name: java-1.8.0-openjdk
        state: present
  
    - name: Download Tomacat
      get_url:
        url: https://mirrors.tuna.tsinghua.edu.cn/apache/tomcat/tomcat-8/v{{ tomcat_version }}/bin/apache-tomcat-{{ tomcat_version }}.tar.gz
        dest: /root
  
    - name: Unarchive Tomcat
      unarchive:
        src: /root/apache-tomcat-{{ tomcat_version }}.tar.gz
        dest: "{{ tomcat_install_path }}"
  
    - name: Create Link File
      file:
        src: "{{ tomcat_install_path }}/apache-tomcat-{{ tomcat_version }}"
        dest: "{{ tomcat_install_path }}/tomcat8"
        state: link
  
    - name: Start Tomcat
      shell: cd "{{ tomcat_install_path }}"/tomcat8/bin && nohup ./startup.sh &

编写install_tomcat9.yml文件:
 cat install_tomcat9.yml 
---
- hosts: localhost

  tasks:
    - name: Install JDK
      yum:
        name: java-1.8.0-openjdk
        state: present

    - name: Download Tomacat
      get_url:
        url: https://mirrors.tuna.tsinghua.edu.cn/apache/tomcat/tomcat-9/v{{ tomcat_version }}/bin/apache-tomcat-{{ tomcat_version }}.tar.gz
        dest: /root

    - name: Unarchive Tomcat
      unarchive:
        src: /root/apache-tomcat-{{ tomcat_version }}.tar.gz
        dest: "{{ tomcat_install_path }}"

    - name: Create Link File
      file:
        src: "{{ tomcat_install_path }}/apache-tomcat-{{ tomcat_version }}"
        dest: "{{ tomcat_install_path }}/tomcat9"
        state: link

    - name: Start Tomcat
      shell: cd "{{ tomcat_install_path }}"/tomcat9/bin && nohup ./startup.sh &

#安装tomcat9
[root@xuzhichao playbook]# ansible-playbook -t tomcat9 tomcat_main.yml

#安装tomcat8
[root@xuzhichao playbook]# ansible-playbook -t tomcat8 tomcat_main.yml

https://blog.51cto.com/u_15127516/3557509

[Ansible系列]ansible-playbook之include和import

ansible10:include说明

pre-tasks and post-tasks

---
- hosts: www
  remote_user: vagrant
  sudo: yes
  pre_tasks:
     - name: update the apt cache
       apt: update_cache=yes
     - shell: echo 'I":" Beginning to configure web server..'
  roles:
     - nginx
  post_tasks:
     - shell: echo 'I":" Done configuring nginx web server...'

https://www.oreilly.com/library/view/ansible-playbook-essentials/9781784398293/ch02s09.html

Handlers (处理程序)

Handlers 是一种特殊的任务,只有在其他任务发生更改时才会被触发。常用于在配置文件更改后重启服务。
例如ng config

---
- name: Example with handlers
  hosts: all
  become: yes
  tasks:
    - name: Copy configuration file
      copy:
        src: /path/to/config.conf
        dest: /etc/config.conf
        owner: root
        group: root
        mode: '0644'
      notify:
        - Restart MyService

  handlers:
    - name: Restart MyService
      service:
        name: myservice
        state: restarted

常用 role 及playbook 例子

Ansible Roles Roles 是组织 Playbooks 和相关文件的一种方式,可以提高代码的可重用性和可维护性。

Roles 的结构

一个典型的 Role 包含以下目录结构:

roles/
└── <role_name>/
    ├── tasks/
    │   └── main.yml           # 主要任务
    ├── handlers/
    │   └── main.yml           # 处理程序
    ├── vars/
    │   └── main.yml           # 变量定义
    ├── defaults/
    │   └── main.yml           # 默认变量定义
    ├── meta/
    │   └── main.yml           # Role 的元数据
    ├── files/                 # 静态文件
    ├── templates/             # Jinja2 模板文件
    └── tasks/                 # 包含更小的任务文件

创建和使用 Roles

    创建 Role 目录结构:
    Bash

ansible-galaxy init <role_name>

这将创建一个基本的 Role 目录结构。

在 Playbook 中使用 Role:
YAML

---
- name: Deploy My Application
  hosts: webservers
  become: yes
  roles:
    - common # 调用名为 common 的 Role
    - { role: apache, version: 2.4 } # 调用 apache Role 并传递变量
    - myapp

在 Role 的 tasks/main.yml 中定义任务:
YAML

- name: Install required packages
  package:
    name: "{{ item }}"
    state: present
  loop: "{{ common_packages }}"

- name: Configure application
  template:
    src: "{{ app_config_template }}"
    dest: "{{ app_config_path }}"
    owner: appuser
    group: appgroup
    mode: '0644'
  notify:
    - Restart Application Service

在 Role 的 vars/main.yml 中定义变量:



playbook role 安装golang

https://docs.ansible.com/ansible/latest/playbook_guide/playbooks_reuse_roles.html

https://www.redhat.com/en/topics/automation/what-is-an-ansible-role

Why use an Ansible Role instead of an Ansible Playbook?

Ansible Roles and Ansible Playbooks are both tools for organizing and executing automation tasks, but each serves a different purpose. Whether you choose to create Ansible Roles or write all of your tasks in an Ansible Playbook depends on your specific use case and your experience with Ansible.

Most automation developers and system administrators begin creating automation content with individual playbooks. A playbook is a list of automation tasks that execute for a defined inventory. Tasks can be organized into a play—a grouping of 1 or more tasks mapped to a specific host and executed in order. A playbook can contain 1 or more plays, offering a flexible mechanism for executing Ansible automation in a single file.

While playbooks are a powerful method for automating with Ansible, writing all of your tasks in a playbook isn’t always the best approach. In instances where scope and variables are complex and reusability is helpful, creating most of your automation content in Ansible Roles and calling them within a playbook may be the more appropriate choice.

The following example illustrates the use of a role, linux-systemr-roles.timesync, within a playbook. In this instance, over 4 tasks would be required to achieve what the single role accomplishes.

pre config

#pre config
 cat    /etc/ansible/ansible.cfg
[defaults]
inventory = /home/evan/ansible/inventory/hosts
roles_path = /home/evan/ansible/playbooks/roles

cat ~/ansible/inventory/hosts
[mytmp]
192.168.10.7  ansible_user=root

目录

├── go.yml
├── roles
│   └── go_install
│       ├── files
│       │   └── go1.17.1.linux-amd64.tar.gz
│       ├── tasks
│       │   ├── copy.yml
│       │   ├── install.yml
│       │   └── main.yml
│       └── templates
│           └── go_install.sh

文件详情

 cat go.yml 
---
- name: Installing Go from source 
  hosts: mytmp
  remote_user: root
  roles:
    - go_install

**********
 cat copy.yml 
- name: copy go_tgz to client
  copy: src=/home/evan/ansible/playbooks/roles/go_install/files/go1.17.1.linux-amd64.tar.gz dest=/usr/local/src/
- name: copy install_go_script to client
  copy: src=/home/evan/ansible/playbooks/roles/go_install/templates/go_install.sh dest=/tmp/go_install.sh owner=root group=root mode=755

cat install.yml 
- name: install go 
  shell: /bin/bash /tmp/go_install.sh

cat  main.yml 
- include_tasks: copy.yml
- include_tasks: install.yml

 cat templates/go_install.sh 
#!/bin/bash
# install golang
# yum tools

yum -y groupinstall "Development tools"
yum -y install zlib-devel bzip2-devel openssl-devel ncurses-devel sqlite-devel readline-devel tk-devel gdbm-devel db4-devel libpcap-devel xz-devel
cd /usr/local/src
tar -C /usr/local -xzf go1.17.1.linux-amd64.tar.gz
echo 'export PATH=$PATH:/usr/local/go/bin'  >> /etc/profile 
source  /etc/profile
# end

install zabbix-agent2

ansible-playbook -C   zabbix-agent2.yml
ansible-playbook    zabbix-agent2.yml


 cat /etc/ansible/zabbix-agent2.yml 
---
- hosts: mytmp
  become: yes
  become_method: sudo
  remote_user: evan  
  #remote_user: ops 
  roles:
    - ag2_conf

 cat /etc/ansible/roles/ag2_conf/tasks/copy.yml 
- name: copy install__script to client
  copy: src=/etc/ansible/roles/ag2_conf/templates/age2_install.sh dest=/tmp/age2_install.sh owner=root group=root mode=755

cat /etc/ansible/roles/ag2_conf/tasks/install.yml 
- name: install conig  zbx agent2 
  shell: /bin/bash /tmp/age2_install.sh

cat /etc/ansible/roles/ag2_conf/tasks/main.yml 
- include_tasks: copy.yml
- include_tasks: install.yml


 cat /etc/ansible/roles/ag2_conf/templates/age2_install.sh 
#!/bin/bash
sudo  yum remove zabbix-agent -y 
sudo /usr/bin/rpm -ivh https://mirrors.aliyun.com/zabbix/zabbix/5.0/rhel/7/x86_64/zabbix-release-5.0-1.el7.noarch.rpm
sudo sleep 5
sudo /usr/bin/yum install zabbix-agent2 -y 
sudo sleep 5
#bak cong
sudo sed  -i 's/127.0.0.1/172.16.0.42/g'  /etc/zabbix/zabbix_agent2.conf  #/etc/zabbix/zabbix_agent2.conf
sudo cp /etc/zabbix/zabbix_agent2.conf /etc/zabbix/zabbix_agent2.confbakevan
sudo sed  -i "s/Hostname=Zabbix server/Hostname=${HOSTNAME}/g"  /etc/zabbix/zabbix_agent2.conf
#grep "^\s*[^# \t].*$" /etc/zabbix/zabbix_agent2.conf

sudo systemctl  enable  zabbix-agent2.service
sudo systemctl restart zabbix-agent2



[详情代码可见我的github,有小改动]

install and remove nginx on ubuntu



- name: apt nginx
  hosts: evan
  become: yes
  tasks:

    - name: update
      apt: update_cache=yes

    - name: Install Nginx
      apt: name=nginx state=latest

      notify:
        - restart nginx

  handlers:
    - name: restart nginx
      service: name=nginx state=reloaded


---
- name: Remove Nginx from Ubuntu
  hosts: evan
  become: true
  tasks:
    - name: Stop Nginx service
      service:
        name: nginx
        state: stopped
    - name: Remove Nginx package
      apt:
        name: nginx
        state: absent
        purge: true
    - name: Remove Nginx configuration directories
      file:
        path: "{{ item }}"
        state: absent
      loop:
        - /etc/nginx
        - /var/log/nginx    

reboot playbook

---
- name: Reboot servers
  hosts: evan
  tasks:
    - name: Reboot the servers
      ansible.builtin.reboot:
        msg: "Rebooting the server for system updates"
        connect_timeout: 5
        reboot_timeout: 300
        pre_reboot_delay: 0
        post_reboot_delay: 30
        test_command: uptime

https://docs.ansible.org.cn/ansible/latest/collections/ansible/builtin/reboot_module.html

refer

https://docs.ansible.com/ansible/latest/playbook_guide/playbooks_roles.html#dynamic-versus-static-includes

Ansible之Playbook详解、案例

通过ansible安装中间件(jdk,nginx,mysql,etcd集群)

(playbook ins zbx还不错) ansible自动化运维详细教程及playbook详解


How to Install Nginx using Ansible Playbook


Ansible Loop循环控制

官网参考文档:

loops: https://docs.ansible.com/ansible/latest/user_guide/playbooks_loops.html

filters: https://docs.ansible.com/ansible/latest/user_guide/playbooks_filters.html