• playbook 基本使用


    相对Ad-Hoc模式下的命令方式,Playbook功能更灵活强大。使用playbook可以非常简单的配置管理多个主机系统,通过编写YAML格式文件来定制配置内容,配置内容可存储和长久使用。本节将通过案例逐步了解playbook使用方法。

    本节内容都是在远程服务器sandboxMP(172.16.3.100)中完成,请使用CRT工具连接到sandboxMP(172.16.3.100)。同时需要开启server1server2虚拟机。

    1 YAML基本使用

    Ansible playbook配置文件使用YAML格式,在文档前面章节已经使用过YAML配置文件,这里简单介绍下YAML的基本语法格式。

    1.1 YAML语法

    1. 使用缩进来表示层级;
    2. 只能使用空格缩进,禁止使用Tab缩进;
    3. 对字母大小写敏感;
    4. 可以使用---来标记开头,使用...来标记结尾;
    5. 使用#表示注释内容;
    6. 字符串可以不用引号标注;
    7. 针对不同数据类型有特定标记模型(后面会用实例演示)。

    1.2 使用实例

    1.2.1 列表

    YAML列表内容:列表内的成员是以相同缩进开始,短线加空格开头(- ):

    ---

    (sandboxMP) [root@sandboxmp ~]$ touch test.yaml

    (sandboxMP) [root@sandboxmp ~]$ vim test.yaml

    # 将下面内容写入test.yaml文件,保存退出vim

    hosts:  
      - 172.16.3.100  
    
      - 172.16.3.101  
    
      - 172.16.3.102
    ...
    

      

     

    在系统中做代码演示的时候,请注意命令提示符内容:

    • (sandboxMP):当前是进入了python的虚拟环境,可以使用虚拟环境中的python环境和安装的程序包;
    • [root@sandboxmp ]表示当前位于家目录,使用root登陆的,当前目录就是/root/,这时我们创建的test.yaml就存放在/root/目录。

    python虚拟环境中使用yaml来读取test.yaml文件内容:

    (sandboxMP) [root@sandboxmp ~]$ ipython
    Python 3.6.6 (default, Nov 26 2018, 20:00:58) Type 'copyright', 'credits' or 'license' for more information
    
    IPython 7.1.1 -- An enhanced Interactive Python. Type '?' for help.
    
    In [1]: import yaml  
    
    In [2]: f = open('/root/test.yaml')
    
    In [3]: yaml.load(f)Out[3]: {'hosts': ['172.16.3.100', '172.16.3.101', '172.16.3.102']}

    可以看到从test.yaml文件中读取的hosts内容是一个列表。

    1.2.2 字典

    YAML字典是使用key: value来表示,冒号后面必须加上一个空格:

    (

    sandboxMP) [root@sandboxmp ~]$ echo '' > test.yml
    (sandboxMP) [root@sandboxmp ~]$ vim test.yml
    
    # 将下面内容写入test.yaml文件,保存退出vim
    
    ---
    
    hosts:  
    
      hostname: sandboxMP    
    
      ipaddress: 172.16.3.100   
    
      username: root  
    
      password: 1234@abcd.com
    
     ...
    

      

     

    python虚拟环境中使用yaml来读取test.yaml文件内容:

    (sandboxMP) [root@sandboxmp ~]# ipython
    Python 3.6.6 (default, Nov 26 2018, 20:00:58) Type 'copyright', 'credits' or 'license' for more information
    
    IPython 7.1.1 -- An enhanced Interactive Python. Type '?' for help.
    
    In [1]: import yaml  
    
    In [2]: f = open('/root/test.yml')
    
    In [3]: yaml.load(f)Out[3]:
    
    {'hosts': {'hostname': 'sandboxMP',
    
      'ipaddress': '172.16.3.100',
    
      'username': 'root',
    
      'password': '1234@abcd.com'}}

    hosts内容是一个字典。

    1.2.3 字典和列表混合使用

    字典和列表是可以混合使用的:

    (sandboxMP) [root@sandboxmp ~]$ echo '' > test.yml
    (sandboxMP) [root@sandboxmp ~]$ vim test.yml
    
    # 将下面内容写入test.yml文件,保存退出vim
    
    ---
    
    hosts:
    
      username: root
    
      password: 1234@abcd.com
    
      ipaddress:
    
        - 172.16.3.100
    
        - 172.16.3.101
    
        - 172.16.3.102
    
    ...
    

      

     

    读取test.yaml内容:

    (sandboxMP) [root@sandboxmp ~]# ipython
    Python 3.6.6 (default, Nov 26 2018, 20:00:58) Type 'copyright', 'credits' or 'license' for more information
    
    IPython 7.1.1 -- An enhanced Interactive Python. Type '?' for help.
    
    In [1]: import yaml  
    
    In [2]: f = open('/root/test.yml')
    
    In [3]: yaml.load(f)
    
    {'hosts': {'username': 'root',
    
      'password': '1234@abcd.com',
    
      'ipaddress': ['172.16.3.100', '172.16.3.101', '172.16.3.102']}}
    

      

     

    hosts是一个字典,字典中ipaddress是一个列表,除了上面用法外,列表中也是可以混合字典的。

    2 使用playbook来执行任务

    2.1 playbook基础

    在定义playbook任务时常会用到的一些基础组件如下:

    • hosts:任务执行的远程目标主机;
    • remote_user:在远程主机上执行任务的用户;
    • tasks:需要在远程主机上执行的任务列表;
    • variables:变量,变量可以在hosts中定义,可以在playbook中定义,也可以直接使用setup模块获取的变量内容,进行变量替换使用{{ variables }}
    • handlers:任务处理器,当满足某些条件时才会触发任务操作;
    • templates:使用模板语言的文本文件。

    接下来我们通过一些案例来理解一些组建的使用:

    2.1.1 案例1:重启远程服务

    sandboxMP(172.16.3.100)远程服务器上定义一个playbook文件用来重启远程服务:

    (sandboxMP) [root@sandboxmp ~]$ mkdir tasks   # 接下来测试用的文件都临时放在这个目录下
    
    (sandboxMP) [root@sandboxmp ~]$ vim tasks/restart_sshd.yml  # 写入如下内容,保存退出
    
    ---- hosts: server             # 指定远程执行主机,默认从/etc/ansible/hosts文件中读取server主机组内容  
    
    remote_user: root        # 制定任务执行使用的用户  
    
    tasks:                     # 定义任务列表    
    
      - name: restart sshd      # 任务名称      
    
      command: 'systemctl restart sshd'    # 调用command模块来执行ssd重启命令

     

     

    在执行重启任务之前,先来登陆到server组中的远程主机,server是上一节在hosts中定义的主机组,包含了server01(172.16.3.101)server02(172.16.3.102),使用CRT登陆server01,查看ssh服务状态:

    [root@server01 ~]$ systemctl status sshd
    ● sshd.service - OpenSSH server daemon
    
       Loaded: loaded (/usr/lib/systemd/system/sshd.service; enabled; vendor preset: enabled)
    
       Active: active (running) since Wed 2019-02-13 10:28:18 CST; 11min ago
    
         Docs: man:sshd(8)
    
               man:sshd_config(5)
    
     Main PID: 1058 (sshd)
    
       CGroup: /system.slice/sshd.service
    
               └─1058 /usr/sbin/sshd -D

     

    可以看到当前sshd服务启动时间是:2019-02-13 10:28:18

    执行restart_sshd.yml 

    ansible提供了一个命令行工具:ansible-playbook用来执行playbook,回到sandboxMP(172.16.3.100)远程服务器:

     1 (sandboxMP) [root@sandboxmp ~]$ ansible-playbook --help # 查看帮助
     2 '''帮助内容省略'''
     3 
     4 (sandboxMP) [root@sandboxmp ~]$ ansible-playbook tasks/restart_sshd.yml
     5 
     6 PLAY [server] ***************************************************************************************************************************************************************************************
     7 
     8 TASK [Gathering Facts] ******************************************************************************************************************************************************************************
     9 
    10 ok: [192.168.31.101]
    11 
    12 ok: [192.168.31.102]
    13 
    14 TASK [restart sshd] *********************************************************************************************************************************************************************************
    15 
    16 changed: [192.168.31.101]
    17 
    18 changed: [192.168.31.102]
    19 
    20 PLAY RECAP ******************************************************************************************************************************************************************************************
    21 
    22 192.168.31.101             : ok=2    changed=1    unreachable=0    failed=0   
    23 
    24 192.168.31.102             : ok=2    changed=1    unreachable=0    failed=0   
    25 
    26 (sandboxMP) [root@sandboxmp ~]$

     

    这时登陆server01(172.16.3.101)系统,使用systemctl status sshd查看服务状态,可以看到服务的启动时间已经发生了变化。

    2.1.2 ansible-playbook

    前面已经介绍了两个命令行工具:ansible ansible-docansible-playbook也是一个命令行工具,用来执行playbook文件。

    ansible-playbook基本语法:nsible-playbook test.yml [options]
    ansible-playbook常用命令参数:

    参数

    描述

    -C, --check

    加上该参数后,模拟执行playbook文件,输出执行结果,不会在远程主机正真正执行

    -e EXTRA_VARS, --extra-vars=EXTRA_VARS

    设置额外变量

    -f FORKS, --forks=FORKS

    设置进程并发,默认5

    -i INVENTORY, --inventory=INVENTORY

    指定hosts文件路径,默认/etc/ansible/hosts

    -l SUBSET, --limit=SUBSET

    对主机进行过滤

    --list-hosts

    列出远程执行的主机列表

    --list-tasks

    列出playbook文件中定义的task列表

    --syntax-check

    检测playbook语法配置

    --step

    同一时间只执行一个task,在执行前需要进行确认

    -t TAGS, --tags=TAGS

    只有匹配tags内容的远程主机才会执行任务,多个tag用逗号分隔

    除了上面介绍到的参数外还有一些认证相关设置的参数,具体内容可以通过ansible-playbook --help查看帮助。

    你也可以使用上面参数来执行任务查看具体效果。

    2.1.3 案例2:创建文件

    接下来再写一个playbook案例,来加深理解,这次使用file模块来创建一个文件:

    (sandboxMP) [root@sandboxmp ~]$ vim tasks/touchfile.yml
    
    ---
    
    - hosts: server  
    
      remote_user: root  
    
      tasks:    
    
        - name: touch file      
    
          file:   # 使用file模块        
    
          path: /tmp/touch_file.txt        
    
          state: touch        
    
          mode: 0600

     

    保存文件后,先来检测下文件语法,并模拟运行下touchfile.yml

    (sandboxMP) [root@sandboxmp ~]$ ansible-playbook tasks/touchfile.yml --syntax-check

     

    playbook: tasks/touchfile.yml  # 语法检测通过,没有报错

    (sandboxMP) [root@sandboxmp ~]$ ansible-playbook tasks/touchfile.yml --check

    # 以下输出结果是模拟运行的结果,远程主机上并没有真正的创建文件

    PLAY [server] ***************************************************************************************************************************************************************************************
    
    TASK [Gathering Facts] ******************************************************************************************************************************************************************************
    
    ok: [172.16.3.102]
    
    ok: [172.16.3.101]
    
    TASK [touch file] ***********************************************************************************************************************************************************************************
    
    ok: [172.16.3.101]
    
    ok: [172.16.3.102]
    
    PLAY RECAP ******************************************************************************************************************************************************************************************
    
    192.168.31.101             : ok=2    changed=0    unreachable=0    failed=0   
    
    192.168.31.102             : ok=2    changed=0    unreachable=0    failed=0  
    

      

     

    这时候登陆到server01server02上是没有/tmp/touch_file.txt这个文件的。 运行touchfile.yml来创建文件:

     

    (sandboxMP) [root@sandboxmp ~]$ ansible-playbook tasks/touchfile.yml
     
    
    PLAY [server] ***************************************************************************************************************************************************************************************
    
     
    
    TASK [Gathering Facts] ******************************************************************************************************************************************************************************
    
    ok: [192.168.31.101]
    
    ok: [192.168.31.102]
    
     
    
    TASK [touch file] ***********************************************************************************************************************************************************************************
    
    changed: [192.168.31.101]
    
    changed: [192.168.31.102]
    
     
    
    PLAY RECAP ******************************************************************************************************************************************************************************************
    
    192.168.31.101             : ok=2    changed=1    unreachable=0    failed=0   
    
    192.168.31.102             : ok=2    changed=1    unreachable=0    failed=0
    

      

    登陆server01或者server02查看文件已经被创建:

    [root@server02 ~]$ ls -l /tmp
    total 8
    drwxr-xr-x 2 root root 4096 Feb 12 22:45 dir_test
    drwx------ 3 root root 4096 Feb 13  2019 systemd-private-5a409c6e1b194765b83da9cfb3756967-ntpd.service-39S38P
    -rw------- 1 root root    0 Feb 13 12:40 touch_file.txt

    task中使用模块时,可以通过使用key-value方式给模块复制,案例中使用的是冒号方式。也可以使用等号方式,多个参数用空格隔开:

    ---
    
    - hosts: server  remote_user: root
    
      tasks:
    
        - name: touch file
    
          file: path=/tmp/touch_file.txt state=touch mode=0600
    

      

    2.1.4 案例3:安装软件

    利用playbook来给server01 server02安装nginx

    (sandboxMP) [root@sandboxmp ~]$ vim tasks/install_nginx.yml
    
    ---
    
    - hosts: server  remote_user: root
    
      tasks:
    
        - name: add nginx repository
    
          yum: name=epel-release state=present # 确保扩展源已经安装
    
        - name: ensure nginx is at the latest version
    
          yum: name=nginx state=latest # 确保当前安装的是最新版本
    
        - name: ensure nginx is running
    
          service: name=nginx state=started # 确保服务已经启动
    

      

          

    在上面的playbook中,定义了三个任务:

    1. add nginx repositorycentos默认是没有nginx安装源的,所以这里使用yum模块了安装扩展源;
    2. ensure nginx is at the latest version:使用yum模块来安装最新版的ngxin,如果ngxin服务已经存在,则会进行更新;
    3. ensure nginx is running:使用service模块来确保nginx服务已启动。

    以上使用到的模块都可以通过命令行工具来获取帮助:

    (sandboxMP) [root@sandboxmp ~]$ ansible-doc -s yum

    以后写playbook使用到新的模块时,大家都可以通过命令行工具:ansible-doc来了解模块的用法,养成习惯。

    运行playbook执行批量安装任务,运行结果,如下图:

     

    细心的朋友可能会发现,在前面几个案例中,我都是直接复制的运行结果,为什么这次也放一张运行结果的截图?
    这是因为ansible-playbook在任务运行的输出结果中,会用不同的颜色来标识运行结果状态:

    • [add nginx repository]:在执行任务前我已经在server01server02中提前安装好了扩展源,任务中设置的state=present,因为已经安装了,所以状态是OK的,该条任务不会在远程主机中重新安装扩展源;
    • [ensure nginx is at the latest version]server01中提前安装好了最新版本的nginx,匹配state=latest,状态也是ok的,不会再重复安装;server02中没有安装nginx,所以通过该条任务会完成最新版本的nginx安装,状态发生的变化:changed
    • [ensure nginx is running]server01server02上的nginx服务都没有启动,所以通过该条任务启动了nginx服务,状态都是changed
    • PLAY RECAP:最后统计并输出任务执行的状态结果。

    除了要知道如何写playbook来完成自动化管理工作外,还要了解playbook的不同运行状态。

    2.1.5 案例4:修改配置文件

    ansible还提供了一个模块:lineinfile,该模块可以用来确保某一行文本存在指定的文件中,或者用来从文件中删除指定的文本,当然可以通过正则表达式来替换某一行内容。

    当我提到这个新的模块的时候你应该保持一个惯性思维,使用命令行工具ansible-doc -s lineinfile 查看下这个模块的基本用法和常用参数。因为任何一份文档都不可能面面俱到,详细介绍每一个知识点,所以你需要真正掌握的是如何在有需求的时候去自主学习。

    在上一个案例中已经成功安装了nginx并运行了nginx服务,这时通过浏览器访问下面地址,可以看到nginx欢迎页面:

    http://172.16.3.101
    
    http://172.16.3.102

    nginx服务默认配置实用的是80端口,登陆server01查看当前服务运行端口:

    [root@server01 ~]# netstat -tnpl |grep nginx
    
    tcp  0 0 0.0.0.0:80  0.0.0.0:*   LISTEN  1591/nginx: master
    
    接下来使用playbook利用lineinfile模块来批量修改nginx默认监听端口:
    
    (sandboxMP) [root@sandboxmp ~]$ vim tasks/modify_nginx.yml
    
    ---
    
    - hosts: server  
    
    remote_user: root  
    
    tasks:    
    
      - name: Modify the default port      
    
        lineinfile:        
    
          path: /etc/nginx/nginx.conf # 指定需要修改的文件        
    
          regexp: "(.*)listen(.*) 80 (.*)" # 使用正则表达式查找需要修改的内容        
    
          line: '1listen2 8080 3'  # 替换后的内容,包含向后引用内容,注意这里是单引号        
    
          backrefs: yes # 启用向后引用        
    
          state: present # 使用 backrefs时需要设置state=present    
    
      - name: restart nginx      
    
        service: name=nginx 
    
        state: restarted 
    

      

     

    playbook说明:

    • 使用了lineinfile模块和一些参数配置,配置内容在注释中已经做了说明;
    • 在进行文本查找替换时,使用到了正则表达式、表达式分组、向后替换,这些知识都属于正则表达式的基础,如果你不理解,可以去扩展学习下;
    • 同时定义了一个任务用来重启nginx服务,因为配置文件修改后要重启服务才能生效。

    执行playbook

    (sandboxMP) [root@sandboxmp ~]$ ansible-playbook tasks/modify_nginx.yml   
    
     
    
    PLAY [server] ***************************************************************************************************************************************************************************************
    
     
    
    TASK [Gathering Facts] ******************************************************************************************************************************************************************************
    
    ok: [172.16.3.101]
    
    ok: [172.16.3.102]
    
     
    
    TASK [Modify the default port] **********************************************************************************************************************************************************************
    
    changed: [172.16.3.101]
    
    changed: [172.16.3.102]
    
     
    
    TASK [restart nginx] ********************************************************************************************************************************************************************************
    
    changed: [172.16.3.101]
    
    changed: [172.16.3.102]
    
     
    
    PLAY RECAP ******************************************************************************************************************************************************************************************
    
    172.16.3.101               : ok=3    changed=2    unreachable=0    failed=0   
    
    172.16.3.102               : ok=3    changed=2    unreachable=0    failed=0
    

      

    任务执行完成,登陆server01 server02查看当前nginx监听端口:

    "/etc/nginx/nginx.conf" 90L, 2467C written
    
    [root@server01 ~]$ netstat -tnpl
    
    Active Internet connections (only servers)
    
    Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name    
    
    tcp        0      0 0.0.0.0:8080            0.0.0.0:*               LISTEN      3529/nginx: master  
    

      

    可以看到,nginx默认监听端口已经变成了8080,端口已经生效,这时候访问http://172.16.3.101:8080就可以看到nginx的欢迎页面了。

    这个案例中实际上是存在一个问题的,由于相关的知识点还未介绍到,所以这里先预留一下问题,等到介绍到对应知识点的时候,再回过头来分析这个案例中的问题,聪明的你也可以思考下,想想是什么问题呢?

    到这里你可以,根据实际工作需求,结合ansible提供的模块,多练习下playbook的编写。

    2.2 使用tags

    使用tags标签处理任务,通过tags和任务对象进行捆绑,控制部分任务按照指定tags来执行;在执行任务的时候通过 -t 来指定使用的标签, 通过 --skip-tags 来排除使用的标签。

    (sandboxMP) [root@sandboxmp ~]$ vim tasks/tag_test.yml# 新建一个playbook文件 tag_test.yml,写入下面内容保存退出
    
    ---
    
    - hosts: server  remote_user: root
    
      tasks:
    
       - name: touch file1
    
         file: path=/tmp/file1.txt state=touch
    
         tags: tf1
    
       - name: touch file2
    
         file: path=/tmp/file2.txt state=touch
    
         tags: tf1
    
       - name: touch file3
    
         file: path=/tmp/file3.txt state=touch
    
         tags: tf3
    

      

    在上面tag_test.yml文件中,定义了三个任务,分别创建了三个文件,同时给任务定义了tags,如果使用ansible-playbook /tmp/tag_test.yml执行playbook任务,三个任务都会被执行,如果只想执行第三个任务创建file3.txt,在执行playbook的时候制定tags即可:

    (sandboxMP) [root@sandboxmp ~]# ansible-playbook tasks/tag_test.yml -t tf3
    
     
    
    PLAY [server] ***************************************************************************************************************************************************************************************
    
     
    
    TASK [Gathering Facts] ******************************************************************************************************************************************************************************
    
    ok: [192.168.31.101]
    
    ok: [192.168.31.102]
    
    # 在执行结果中可以看到只有 name为touch file3 的任务被执行了
    
    TASK [touch file3]  **********************************************************************************************************************************************************************************
    
    changed: [192.168.31.102]
    
    changed: [192.168.31.101]
    
     
    
    PLAY RECAP ******************************************************************************************************************************************************************************************
    
    192.168.31.101             : ok=2    changed=1    unreachable=0    failed=0   
    
    192.168.31.102             : ok=2    changed=1    unreachable=0    failed=0

    登陆server01 或者 server02可以看到/tmp/目录下只创建了一个file3.txt的文件。

    作者:james

    -------------------------------------------

    个性签名:独学而无友,则孤陋而寡闻。做一个灵魂有趣的人!

    如果觉得这篇文章对你有小小的帮助的话,记得在右下角点个“推荐”哦,博主在此感谢!

  • 相关阅读:
    微信公共服务平台开发(.Net 的实现)5-------解决access_token过期的问题
    微信公共服务平台开发(.Net 的实现)4-------语音识别
    微信公共服务平台开发(.Net 的实现)3-------发送文本消息
    微信公共服务平台开发(.Net 的实现)2-------获得ACCESSTOKEN
    微信公共服务平台开发(.Net 的实现)1-------认证“成为开发者”
    checkboxlist 横向显示,自动换行
    VMware Workstation unrecoverable error: (vmx)虚拟机挂起后无法启动问题
    ASP.NET给DataGrid,Repeater等添加全选批量删除等功能
    redis 优缺点 使用场景
    redis消息队列
  • 原文地址:https://www.cnblogs.com/jameslove/p/10927067.html
Copyright © 2020-2023  润新知