侧边栏壁纸
博主头像
小周的知识站 博主等级

行动起来,活在当下

  • 累计撰写 80 篇文章
  • 累计创建 12 个标签
  • 累计收到 8 条评论

目 录CONTENT

文章目录

Ansible Playbook——1

Administrator
2024-12-14 / 0 评论 / 1 点赞 / 19 阅读 / 0 字

1 Ansible Playbook简介

前面我们都是通过ansible命令形式管理被控节点:
- 此方式适合执行一些临时性的简单任务

Playbook剧本:
- 将需要执行的任务写入剧本文件,看起来简洁清晰
- 剧本文件中可以包含多个任务
- 剧本能够实现流程控制,比如:判断、循环、变量、标签
- 剧本写好后,随时调用剧本,执行相关的任务
- 适用于经常执行的复杂任务
- 剧本提供语法检查以及模拟执行功能

电影剧本:
	电影名
	场景
	演员
	事件
	   事件1
	   事件2
	   事件3

Ansible剧本:
	剧本名
	被控节点
	管理被控节点时使用的用户
	任务(事件)
	   任务1
	   任务2
	   任务3

2 Playbook书写格式

2.1 YAML简介

YAML是一个可读性高、用来表达数据序列的格式语言;YAML以数据为中心,重点描述数据的关系和结构。

2.2 YAML格式特点

YAML语法官方文档:https://docs.ansible.com/ansible/latest/reference_appendices/YAMLSyntax.html

1."#"代表注释,第一行一般为三个横杠表示开头
2.严格的缩进表示层级关系,缩进一般为2个空格
3.缩进必须使用空格,不能使用tab键
4.字符串通常不需要放在引号里,即使字符串中包含空格
5.支持字典,字典以简单的形式表示 key: value;字典也可以使用{}括起来
6.支持列表,列表的内容使用"-"表示;列表也可用[]括起来
7.":"和"-"后面必须要有一个空格
8.跨行数据可以使用">"来换行
9.剧本文件后缀名必须为yaml或yml

2.3 剧本编写格式

Playbook剧本必不可少的三个部分:name,hosts,tasks。
name 剧本名称
hosts 被控节点,主机或主机组
tasks 要执行的任务

become:表示是否要以特权用户(通常是root)身份执行任务。如果设置为yes,则任务会以特权身份执行。
playbook: 由一个或多个play组成,一个play可以包含多个task任务

---                             #第一行一般为三个横杠,可以省略
- name: Update web servers      #剧本名称
  hosts: webservers             #被控节点,主机或主机组
  remote_user: root             #管理被控节点时使用哪个用户

  tasks:                        #要执行的任务
  - name: apache_install        #第一个任务的名称
    tags: t1                    #该任务的标签
    yum:                        #该任务使用的模块,也就是该任务要做的事情
      name: httpd               #yum模块的参数,表示httpd包
      state: latest             #yum模块的参数,表示安装最新版
  - name: apache_config_file    #第二个任务的名称
    tags: t2                    #该任务的标签
    template:                   #该任务使用的模块,也就是该任务要做的事情
      src: /srv/httpd.j2        #模块参数
      dest: /etc/httpd.conf     #模块参数

- name: Update db servers       #第二个剧本名称,第二种格式
  hosts: databases
  remote_user: root

  tasks:
  - name: Ensure postgresql is at the latest version
    yum: name=postgresql state=latest
  - name: Ensure that postgresql is started
    service: name=postgresql state=started

示例:安装host1节点 httpd 服务并且在host3节点上重启nginx并且检查他们的服务状态

[root@server ~]# vi httpd.yml
[root@server ~]# cat httpd.yml
---
 - hosts: node1
   become: yes
   tasks:
   # 使用yum模块在node1主机上安装httpd服务  
     - name: Install httpd Server
       yum:
         name: httpd
         state: present

name:定义一个Playbook的名称,用于标识Playbook的用途;

hosts:指定要在哪个主机上执行,也是写主机或主机组名,

需要提前在/etc/ansible/hosts中配置好;

become:yes表示使用特权用户;

tasks:属于是一个任务列表,主要写具体执行什么的(可以有多个);

name:每个任务的名称,用于描述干什么的;上述yml中则是安装httpd服务;

yum:表示使用哪个模块来进行操作;

name:要安装的服务名称,我们这里是httpd:

state:要进行的操作,可以是安装、卸载、更新;

其实tasks就是Ansible的模块以YAML语法写入到playbook中。

生产环境中为了可读性与可维护性通常一个playbook中只编写一个play,如果某些主机需要执行多个play,那么可以使用include关键字在一个playbook中导入其他的playbook。

3 剧本执行命令

#命令格式
ansible-playbook [选项] 剧本文件

#选项
-C        #模拟执行
-i        #指定主机清单hosts文件路径,默认是/etc/ansible/hosts
-v        #显示过程,-vv、-vvv更详细
--list-hosts    #查看哪些主机会执行该剧本
--list-tasks    #列出剧本中所有任务
--start-at-task #指定从剧本中某个任务开始运行
--list-tags	    #列出剧本文件中任务中定义的所有tags
-t              #只运行剧本文件中定义的某些tags任务,多个标签用逗号隔开
--skip-tags     #跳过剧本中某些标签的任务

#示例
#执行某剧本
[root@manager-18 ~/projects/Rsync_configure_project]# ansible-playbook Rsync_configure_project.yaml 

#模拟执行某剧本
[root@manager-18 ~/projects/Rsync_configure_project]# ansible-playbook -C Rsync_configure_project.yaml

#查看哪些主机会执行该剧本
[root@manager-18 ~/projects/Rsync_configure_project]# ansible-playbook --list-hosts Rsync_configure_project.yaml 

playbook: Rsync_configure_project.yaml

  play #1 (backup): Rsync configure     TAGS: []
    pattern: [u'backup']
    hosts (1):
      10.0.0.16

#列出剧本中所有任务
[root@manager-18 ~/projects/Rsync_configure_project]# ansible-playbook --list-tasks Rsync_configure_project.yaml 

playbook: Rsync_configure_project.yaml

  play #1 (backup): Rsync configure     TAGS: []
    tasks:
      01 install rsync  TAGS: [t1]
      02 copy config file       TAGS: [t2]
      03 rsync groupadd TAGS: [t3]
      04 rsync useradd  TAGS: [t4]
      05 make backup directory  TAGS: [t5]
      06 copy password file     TAGS: [t6]
      07 stop firewalld service TAGS: [t7]
      08 close the selinux      TAGS: [t8]
      09 start rsyncd service   TAGS: [t9]

#指定从剧本中第7个任务开始运行
[root@manager-18 ~/projects/Rsync_configure_project]# ansible-playbook --start-at-task "07 stop firewalld service" Rsync_configure_project.yaml 

#列出剧本文件中任务中定义的所有tags
[root@manager-18 ~/projects/Rsync_configure_project]# ansible-playbook --list-tags Rsync_configure_project.yaml 

playbook: Rsync_configure_project.yaml

  play #1 (backup): Rsync configure     TAGS: []
      TASK TAGS: [t1, t2, t3, t4, t5, t6, t7, t8, t9]

#只运行剧本文件中定义的tags为t2,t6,t9的任务
[root@manager-18 ~/projects/Rsync_configure_project]# ansible-playbook -t t2,t6,t9 Rsync_configure_project.yaml

#跳过剧本中标签为t3,t4,t5的任务
[root@manager-18 ~/projects/Rsync_configure_project]# ansible-playbook --skip-tags t3,t4,t5 Rsync_configure_project.yaml

3.1 权限

remote_user指定playbook运行时的用户身份,可以写在hosts下,也可以每个tasks做定义;
become 该选项为布尔值,当等于yes表示以管理员身份通常与become_method一起使用;
become_method:su或sudo


# 指定使用哪个用户执行此任务
remote_user: root
# 是否使用特权用户
become: yes

3.2 通知与触发

 notify: 如果指定的操作执行了,会触发handlers的操作,指定的是handler的名称;
handlers和notify指定的名称必须相同,否则无法触发。
handlers 中需要- name指定名称 ,handlers只会在所有的tasks执行完后执行,
并且,即便一个handlers被触发多次,也只会执行一次。 handlers是一种特殊的tasks。

使用上场景:一般都是修改配置文件时
正常情况时handlers是不会执行的,除非触发任务,才会执行
任务导致系统状态发生变化(例如,配置文件被修改),则将触发名为restart的处理器。

- hosts: node1
  tasks:
  - name: installredis
    yum: name=redis
    
  - name: copyfile
    template: src=redis.conf dest=/etc/redis.conf
    tags: copyfile
    notify: restart   # 触发:触发名称
    
  - name: start
     service:
       name: redis
       state: started
       enabled: yes
    
  handlers:       # 触发动作
  - name: restart
    service:
      name: redis
      state: restarted

例:下载nginx并启动,启动成功后会自动执行关闭防火墙并且检查运行状态

[root@server ~]# cat nginx3.yml 
---
 - hosts: node3
   become: yes
   tasks:
     - name: install_nginx
       yum:
         name: nginx 
         state: present
      
     - name: Start_nginx
       service:
         name: nginx
         state: started
       notify: 
         - stop_firewalld
         - check_status_nginx  
         - display nginx status      
       changed_when: true  # 强制标记任务为已改变  
    
   handlers:
     - name: stop_firewalld
       service: 
         name: firewalld
         state: stopped
         enabled: no
 
     - name: check_status_nginx
       command: systemctl status nginx
       register: nginx_status
       changed_when: false
       
     - name: display nginx status
       debug:
         var: nginx_status.stdout_lines

在Ansible中,处理器(handlers)只有在任务状态发生变化时才会被触发。例如,如果Nginx服务之前已经是运行状态,那么Start_nginx任务不会被视为“改变”系统状态,因此不会触发处理器。

为了确保处理器能够被触发,你可以使用changed_when参数来强制标记任务为已改变,或者使用meta: flush_handlers来强制执行所有处理器。

4 Ansible变量应用

Ansible支持很多种定义变量的方式;在此简单列举几种,根据优先级排序:
1.Inventory变量
2.Host Facts变量
3.Register变量
4.Playbook变量
5.变量文件

除了以上变量之外还有"命令行定义的变量"和ansible内置的"magic魔法变量"

变量的调用方式:

通过 {{ variable_name }} 调用变量,且变量名前后建议加空格,有时使用 "{{ variable_name }}" 才能生效

4.1 变量的定义方式

1.通过命令行进行变量定义
2.在play文件中进行变量定义
3.通过Inventory主机信息文件中进行变量定义

变量读取的优先级为: 命令行 > playbook文件 > Inventory文件

4.1.1 通过vars定义变量

---
- name: LAMP
  hosts: node1
  vars:
    packages_name:
      - httpd
      - mariadb-server
      - php
      - php-mysql
 
  tasks:
    - name: install LAMP
      yum:
         name: "{{packages_name}}"
         state: present

4.1.2 通过vars_files定义变量

当变量较少时,使用vars定义没有问题,当变量较多时,可以将变量保存到一个独立的文件中;
需要多个yml文件,一个主文件,需要调用其他yml独立文件,主要是最后运行的;其他是定义包名的yml文件。

[root@server ansible]# cat rzc.yml 
---
httpd_package: httpd
mariadb_package: mariadb-server
[root@server ansible]# vi nginx4.yml
[root@server ansible]# cat nginx4.yml 
---
 - name: nginx
   hosts: node3
   become: yes
   vars_files:
     - rzc.yml
 
   tasks:
     - name: Install httpd
       yum:
         name: "{{ httpd_package }}"
         state: present
 
     - name: Install mariadb-server
       yum:
         name: "{{ mariadb_package }}"
         state: present

4.1.3 命令行定义变量

ansible-playbook命令提供-e选项,用于在命令行定义变量,命令行定义变量的优先级最高

# 执行:命令行定义变量
[root@localhost yml]# vi test.yml
---
- name: apache 
  hosts: web
  become: yes
  vars: 
    httpd_package:
       - httpd
 
  tasks:
    - name: install httpd service
      yum:
        name: "{{ httpd_package }}"
        state: present
#定义阶段
[root@ansible ~]# ansible-playbook test.yml -e "httpd_package=httpd"

命令行指定多个变量

ansible-playbook test.yml -e "file=command" -e "file2=command2"

4.1.4 官方推荐的定义变量方法(推荐)

之前的几种变量定义都不是很好用,比较好用的是在Ansible项目目录下创建两个变量目录:

host_vars

group_vars

目录名字一定要一致,不能做任何修改。

  理解如何设置和使用host_vars和group_vars可以使你的Ansible管理更加灵活和有组织。以下是更详细的步骤,从设置目录结构到创建Playbook的执行:

1.目录结构

your_ansible_project/

├── group_vars/

│ └── web-servers.yml

├── host_vars/

│ └── web-server.yml

├── playbook.yml

└── inventory.ini

group_vars目录用于存放组级别的变量定义。

host_vars目录用于存放主机级别的变量定义。

playbook.yml是你的Ansible Playbook。

inventory.ini是Ansible的主机清单文件,其中列出了你的主机和主机组。

2.清单文件(inventory.ini):

在这里添加你的主机和主机组

[root@server ~]# cat /etc/ansible/inventory.ini 

[node1]

host1

[node2]

host2

[node3]

host3

[node4]

host1

host3

3.组级别变量

group_vars/web-servers.yml

[root@server ~]# cd /etc/ansible/

[root@server ~]# mkdir -p /etc/ansible/group_vars

[root@server group_vars]# vi node4.yml

[root@server group_vars]# cat node4.yml 

---

httpd_package: httpd

mariadb_package: mariadb-server

nginx_package: nginx

4.主机级别变量

host_vars/web-server.yml

在host_vars目录下创建一个YAML文件,例如node1.yml,并在其中定义主机级别的变量,如:

[root@server ~]# cd /etc/ansible/

[root@server ~]# mkdir -p /etc/ansible/host_vars

[root@server ansible]# cd host_vars/

[root@server host_vars]# vi node3.yml

[root@server host_vars]# cat node3.yml 

---

nginx_package= nginx

5.Playbook(playbook.yml)

创建你的Ansible Playbook,例如:

[root@server ansible]# vi nginx4.yml 

[root@server ansible]# cat nginx4.yml 

---

 - name: nginx

   hosts: node3

   become: yes

 

   tasks:

     - name: Install nginx

       yum:

         name: "{{ nginx_package }}"

         state: present

6.运行playbook:

格式:

ansible-playbook -i inventory.ini playbook.yml

inventory.ini : 这里面表示你设置的主机分组

playbook.yml:你创造的脚本名称

此时,Ansible会自动加载group_vars和host_vars目录中的变量,你的Playbook将使用这些变量来配置主机。

通过这种方式,你可以更加有组织地管理变量,特别是对于多主机和多组的环境。你可以为不同的组或主机设置特定的变量,而不必在Playbook中硬编码这些值,提高了可维护性和可读性。

4.2 Host Facts变量

#事实变量就是setup模块获取到的被控节点的主机信息

#示例一
[root@manager-18 ~]# vim facts_variable_test.yml
---
- name: facts variable test
  hosts: backup

  tasks:
  - name: print
    debug:
      msg: "the backup host ip address is {{ ansible_ens33.ipv4.address }}"

[root@manager-18 ~]# ansible-playbook facts_variable_test.yml 

PLAY [facts variable test] **********************************************************************************************************

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

TASK [test01] ***********************************************************************************************************************
ok: [10.0.0.16] => {
    "msg": "the backup host ip address is 172.16.1.16"
}

PLAY RECAP **************************************************************************************************************************
10.0.0.16                  : ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   


#示例二
[root@manager-18 ~]# vim facts_variable_test.yml
---
- name: facts variable test
  hosts: backup

  tasks:
  - name: test01
    shell: echo "{{ ansible_ens33.ipv4.address }}" > /tmp/{{ ansible_ens33.ipv4.address }}

[root@manager-18 ~]# ansible-playbook facts_variable_test.yml 

PLAY [facts variable test] **********************************************************************************************************

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

TASK [test01] ***********************************************************************************************************************
changed: [10.0.0.16]

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

[root@backup-16 ~]# cat /tmp/172.16.1.16 
172.16.1.16

#注意:若使用不到事实变量,可以关闭获取被控主机的事实变量
# 配置如下:
---
- name: facts variable test
  hosts: backup
  gather_facts: false

4.3 Register变量

#register语句可以将某个命令的执行结果保存至某变量中,该变量就是注册变量

#示例
[root@manager-18 ~]# vim register_variable_test.yml
---
- name: register variable test
  hosts: backup

  tasks:
  - name: test01
    shell: echo "hello world"
    register: hi        #将此任务的结果保存到一个名为"hi"的变量中
  - name: print
    debug:
      var: hi           #在此使用debug模块,输出hi变量内容
      #var: hi.stdout   #输出hi变量中stdout该部分内容

[root@manager-18 ~]# ansible-playbook register_variable_test.yml 

PLAY [register variable test] *******************************************************************************************************

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

TASK [test01] ***********************************************************************************************************************
changed: [10.0.0.16]

TASK [debug] ************************************************************************************************************************
ok: [10.0.0.16] => {
    "hi": {
        "changed": true, 
        "cmd": "echo \"hello world\"", 
        "delta": "0:00:00.002149", 
        "end": "2021-12-03 11:12:50.385688", 
        "failed": false, 
        "rc": 0, 
        "start": "2021-12-03 11:12:50.383539", 
        "stderr": "", 
        "stderr_lines": [], 
        "stdout": "hello world", 
        "stdout_lines": [
            "hello world"
        ]
    }
}

PLAY RECAP **************************************************************************************************************************
10.0.0.16                  : ok=3    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

1
  1. 支付宝打赏

    qrcode alipay
  2. 微信打赏

    qrcode weixin

评论区