• Ansible 的 Playbook


    一、playbook 概述

    1.什么是playbook

    PlayBook即"剧本","兵书"之意,PlayBook是由以下部分组成的
    
    play(host): 定义的是主机的角色。(主角还是配角)
    Book(task): 定义的是具体执行的任务。(角色的台词和动作)
    playbook: 由一个或多个play(角色)组成,一个play(角色)可以包含多个task(台词,动作)。
    
    简单理解为: 使用很多不同的模块指定主机完成一系列动作
    
    在Ansible中"剧本文件"是以yml结尾的文件。
    在SaltStack中"剧本文件"是以sls结尾的文件。
    但是语法,使用的都是yaml语法
    

    2.playbook的组成

    playbooks是 一个不同于使用Ansible命令行执行方式的模式,其功能更强大灵活。简单来说,playbook是一个非常简单的配置管理和多主机部署系统,不同于任何已经存在的模式,可作为一个适合部署复杂应用程序的基础。Playbook可以定制配置,可以按照指定的操作步骤有序执行,支持同步和异步方式。值得注意的是playbook是通过YAML格式来进行描述定义的。

    [root@m01 ~]# vim touch.yml 
    - hosts: web_group          #定义要执行动作的主机或主机组
      remote_user: root         #定义远端操作的用户
      vars:                #开始定义变量
        file_name: lhd      #变量:变量的值
      tasks:              #指定主机的动作
        - name: Touch New File     #动作的注释
          shell: touch /tmp/{{ file_name }}    #使用shell模块执行动作
          
    #模拟执行
    [root@m01 ~]# ansible-playbook -C touch.yml
    
    #验证语法
    [root@m01 ~]# ansible-playbook --syntax-check touch.yml
    #注意:只能验证语法,验证不了逻辑
    

    playbook命令

    格式

    ansible-playbook <filename.yml> ... [options]Copy to clipboardErrorCopied
    

    常见选项

    --syntax-check      #语法检查
    -C --check                     #只检测可能会发生的改变,但不真正执行操作
    --list-hosts    #列出运行任务的主机
    --list-tags         #列出tag
    --list-tasks         #列出task
    --tags                     # 只run 一个tag
    --skip-tags        # 跳过某个task
    --limit 主机列表    #只针对主机列表中的特定主机执行
    -v -vv  -vvv    #显示过程Copy to clipboardErrorCopied
    

    3.PlayBook与ad-hoc

    特点 PlayBook ad-hoc
    完整性
    持久性
    执行效率
    变量 支持 不支持
    耦合度
    1.PlayBook功能比ad-hoc更全,是对ad-hoc的一种编排.
    2.PlayBook能很好的控制先后执行顺序,以及依赖关系.
    3.PlayBook语法展现更加的直观.
    4.playbook可以持久使用,ad-hoc无法持久使用.
    

    4. yaml 语法结构

    playbook使用yml标记语言,这是一种标记语言,这种标记语言在文件的最开始需要使用三个“-”来说明文件开始,然后使用缩进来说明代码块的范围。下面通过一个简易的实例,来说明playbook的语法。

    YAML 官方网站:http://www.yaml.org

    语法 描述
    缩进 YAML使用固定的缩进风格表示层级结构,每个缩进由两个空格组成, 不能使用TAB
    冒号 以冒号结尾的除外,其他所有冒号后面所有必须有空格
    短横线 表示列表项,使用一个短横杠加一个空格,多个项使用同样的缩进级别作为同一列表
    [root@m01 ~]# vim yufa.yaml
    ---                             #标记文件的开始
    - hosts: webservers             #指定该playbook在哪个服务器上执行
      vars:                         #表示下面是定义的变量,
        http_port: 80               #变量的形式,key: value,这里http_port是变量名,80是值
        max_clients: 200
      remote_user: root             #指定远程的用户名,这里缩进和vars保持了一致,说明变量的代码块已经结束。
      tasks:                        #下面构成playbook的tasks,每个task都有 - name: 开始,name指定该任务的名称。
      - name: ensure apache is at the latest version  #指定该任务的名称。
        yum: pkg=httpd state=latest                   #yum说明要是用的模板名称,后面指定对应的参数,这两行结合起来就相当于一个shell命令。
      - name: write the apache config file            #每个task之间可以使用空行来做区分。
        template: src=/srv/httpd.j2 dest=/etc/httpd.conf #需要说明的是缩进的意义和python中缩进的意义是一样,是来区分代码块的。
     
     # 检查语法
    [root@m01 ~]# ansible-playbook -C yufa.yaml
    

    yaml语言特性

    • YAML的可读性好
    • YAML和脚本语言的交互性好
    • YAML使用实现语言的数据类型
    • YAML有一个一致的信息模型
    • YAML易于实现
    • YAML可以基于流来处理
    • YAML表达能力强,扩展性好

    yaml语法简介

    • 在单一文件第一行,用连续三个连字号"-" 开始,还有选择性的连续三个点号( ... )用来表示文件的结尾
    • 次行开始正常写Playbook的内容,一般建议写明该Playbook的功能
    • 使用#号注释代码
    • 缩进必须是统一的,不能空格和tab混用
    • 缩进的级别也必须是一致的,同样的缩进代表同样的级别,程序判别配置的级别是通过缩进结合换行来实现的
    • YAML文件内容是区别大小写的,key/value的值均需大小写敏感
    • 多个key/value可同行写也可换行写,同行使用,分隔
    • key后面冒号要加一个空格 比如: key: value
    • value可是个字符串,也可是另一个列表
    • YAML文件扩展名通常为yml或yaml

    支持的数据类型

    YAML 支持以下常用几种数据类型:

    • 标量:单个的、不可再分的值 ;不可在分的量。包括字符串,布尔值,整数,浮点数,Null,时间,日期。ey对应value
    • 对象:键值对的集合,又称为映射(mapping)/ 哈希(hashes) / 字典(dictionary)
    • 数组:一组按次序排列的值,又称为序列(sequence) / 列表(list)

    三种常见的数据格式

    • XML:Extensible Markup Language,可扩展标记语言,可用于数据交换和配置
    • JSON:JavaScript Object Notation, JavaScript 对象表记法,主要用来数据交换或配置,不支持注释
    • YAML:YAML Ain't Markup Language YAML 不是一种标记语言, 主要用来配置,大小写敏感,不支持tab

    可以用工具互相转换,参考网站:

    https://www.json2yaml.com/

    http://www.bejson.com/json/json2yaml/

    playbook核心组件

    一个playbook 中由列表组成,其中所用到的常见组件类型如下:

    • Hosts 执行的远程主机列表

      Hosts:playbook中的每一个play的目的都是为了让特定主机以某个指定的用户身份执行任务。hosts用于指定要执行指定任务的主机,须事先定义在主机清单中。

      one.example.com
      one.example.com:two.example.com
      192.168.1.50
      192.168.1.*
      public:private     #或者,两个组的并集
      public:&private   #与,两个组的交集
      public:!private  #在public组,但不在private组Copy to clipboardErrorCopied
      
      • 案例
      - hosts: public:!private
      
    • Tasks 任务集,由多个task的元素组成的列表实现,每个task是一个字典,一个完整的代码块功能需最少元素需包括 name 和 task,一个name只能包括一个task

    • Variables 内置变量或自定义变量在playbook中调用

    • Templates 模板,可替换模板文件中的变量并实现一些简单逻辑的文件

    • Handlers 和 notify 结合使用,由特定条件触发的操作,满足条件方才执行,否则不执行

      handler用来执行某些条件下的任务,比如当配置文件发生变化的时候,通过notify触发handler去重启服务。
      在saltstack中也有类似的触发器,写法相对Ansible简单,只需要watch,配置文件即可。

      触发器使用注意事项:

      1.无论多少个task通知了相同的handlers,handlers仅会在所有tasks结束后运行一次。

      2.Handlers只有在其所在的任务被执行时,才会被运行;如果一个任务中定义了notify调用Handlers,但是由于条件判断等原因,该任务未被执行,那么Handlers同样不会被执行。

      3.Handlers只会在每一个play的末尾运行一次;如果想在一个playbook中间运行Handlers,则需要使用meta模块来实现。例如: -meta: flush_handlers。

      4.如果一个play在运行到调用Handlers的语句之前失败了,那么这个Handlers将不会被执行。我们可以使用meta模块的--force-handlers选项来强制执行Handlers,即使Handlers所在的play中途运行失败也能执行。

      5.不能使用handlers替代tasks

      [root@m01 ~]# cat nginx.yml 
      - hosts: nginx
      remote_user: root
      gather_facts: no
      tasks:
         - name: Install httpd
         yum: name=httpd state=present
         - name: Install configure file
         copy: src=httpd.conf dest=/etc/httpd/conf/
         notify: restart httpd
         - name: ensure apache is running
         service: name=httpd state=started enabled=yes
      
      handlers:
         - name: restart httpd
         service: name=httpd state=restarted
      
    • tags 标签 指定某条任务执行,用于选择运行playbook中的部分代码。ansible具有幂等性,因此会自动跳过没有变化的部分,即便如此,有些代码为测试其确实没有发生变化的时间依然会非常地长。此时,如果确信其没有变化,就可以通过tags跳过此些代码片断

      在playbook文件中,可以利用tags组件,为特定 task 指定标签,当在执行playbook时,可以只执行特定tags的task,而非整个playbook文件。

      打标签的方式:

      1.对一个task打一个标签
      2.对一个task打多个标签
      3.对多个task打一个标签

      - hosts: public 
      remote_user: root
      gather_facts: no
      
      tasks:
          - name: Install httpd
         yum: name=httpd state=present
         tags: install
          - name: Install configure file
         copy: src=httpd.conf dest=/etc/httpd/conf/
         notify: restart httpd
          - name: ensure apache is running
         service: name=httpd state=started enabled=yes
      
      handlers:
          - name: restart httpd
         service: name=httpd state=restarted
      
      ansible-playbook –t install httpd.yml
      
    Ansible facts
    是在被管理主机上通过Ansible自动采集发现的变量。facts包含每台特定的主机信息。比如:被控端的主机名、IP地址、系统版本、CPU数量、内存状态、磁盘状态等等。
    1.通过facts缓存检查CPU,来生成对应的nginx配置文件
    2.通过facts缓存检查主机名,生成不同的redis配置文件
    3.通过facts缓存检索物理机的内存大小来生成不通的mysql配置文件
    
    综上所述的Ansible facts类似于saltstack中的grains对于做自动化的小伙伴是非常有用滴。
    
    #关闭facts缓存
    [root@m01 ~]# vim facts.yml
    - hosts: web_group
      gather_facts: no   #关闭信息采集
      tasks:
      
    #如果不使用内置变量,可以关闭会提高剧本的执行速度,如果使用内置变量,那么不能关闭facts缓存
    
    remote_user组件

    remote_user: 可用于Host和task中。也可以通过指定其通过sudo的方式在远程主机上执行任务,其可用于play全局或某任务;此外,甚至可以在sudo时使用sudo_user指定sudo时切换的用户。

    - hosts: public
      remote_user: root
      gather_facts: no             #不收集对应主机的信息,这样运行会快点。
      
      tasks:
        - name: test connection
          ping:
          remote_user: dan
          sudo: yes                         #默认sudo为root
          sudo_user: xiaomian       #sudo为xiaomian
    
    task列表

    playbook的主体部分是task list,task list中有一个或多个task,各个task 按次序逐个在hosts中指定的所有主机上执行,即在所有主机上完成第一个task后,再开始第二个task。

    task的目的是使用指定的参数执行模块,而在模块参数中可以使用变量。模块执行是幂等的,这意味着多次执行是安全的,因为其结果均一致。

    每个task都应该有其name,用于playbook的执行结果输出,建议其内容能清晰地描述任务执行步骤。

    如果未提供name,则action的结果将用于输出

    ---
    - hosts: public
      remote_user: root
      gather_facts: no
      
      tasks:
        - name: install httpd
          yum: name=httpd 
        - name: start httpd
          service: name=httpd state=started enabled=yes
    

    5.实例

    创建mysql

    [root@m01 ~]# cat mysql.yaml 
    - hosts: web
      remote_user: root
      gather_facts: no
      tasks:
        - name: Create Group
          group: name=mysql system=yes gid=666
        - name: Create User
          user: name=mysql shell=/sbin/nologin system=yes group=mysql uid=666 home=/home/mysql create_home=no
    

    安装nginx

    [root@m01 ~]# cat nginx.yaml 
    - hosts: web
      remote_user: root
      gather_facts: no
      tasks:
        - name: Create Group
          group: name=nginx system=yes gid=666
        - name: Create User
          user: name=nginx shell=/sbin/nologin system=yes group=nginx uid=666 home=/home/nginx create_home=no
        - name: Install nginx
          yum: name=nginx state=present
        - name: Start Nginx
          service:  name=nginx state=started enabled=yes
    

    安装和卸载httpd

    [root@m01 ~]# cat httpd.yaml
    # 安装httpd
    - hosts: public
      remote_user: root
      gather_facts: no
      tasks:
        - name: Create Group
          group: name=www system=yes gid=777
        - name: Create User
          user: name=www shell=/sbin/nologin system=yes group=www uid=777 home=/home/www create_home=no
        - name: Install nginx
          yum: name=httpd state=present
        - name: Start Nginx
          service:  name=httpd state=started enabled=yes
    
    # 卸载httpd
    - hosts: public
      remote_user: root
      tasks:
        - name: remove httpd package
          yum: name=httpd state=absent
        - name: remove apache user
          user: name=www state=absent
        - name: remove config file
          file: name=/etc/httpd state=absent
        - name: remove web html
          file: name=/var/html/ state=absent
    

    playbook实战

    一.基础准备

    #1.安装ansible
    [root@m01 ~]# yum install -y ansible
    
    #2.配置ansible
    [root@m01 ~]# vim /etc/ansible/ansible.cfg
    host_key_checking = False
    
    #3.配置主机清单
    [root@m01 ~]# cat /etc/ansible/hosts 
    [web_group]
    web01 ansible_ssh_pass='1'
    web02 ansible_ssh_pass='1'
    
    [nfs_server]
    nfs ansible_ssh_pass='1'
    
    [rsync_server]
    backup ansible_ssh_pass='1'
    
    [lb_server]
    lb01 ansible_ssh_pass='1'
    lb02 ansible_ssh_pass='1'
    
    [db_server]
    db01 ansible_ssh_pass='1'
    
    [nginx:children]
    web_group
    lb_server
    
    #4.配置hosts
    [root@m01 ~]# vim /etc/hosts
    172.16.1.5 lb01
    172.16.1.6 lb02
    172.16.1.7 web01
    172.16.1.8 web02
    172.16.1.31 nfs
    172.16.1.41 backup
    172.16.1.51 db01
    172.16.1.61 m01
    
    #5.确定配置完能通
    [root@m01 ~]# ansible all -m ping
    
    #6.创建统一目录
    [root@m01 ~]# mkdir /dan
    [root@m01 ~]# cd /dan/
    

    二、编写剧本实例

    1.nginx部分

    1)安装方式

    #官方源方式
    1.配置官方源
    2.推送官方源
    copy
    3.安装nginx
    yum
    

    2)准备工作

    #1.准备nginx的官方文档 并下载nginx
    [root@m01 ~]# cat /etc/yum.repos.d/nginx.repo 
    [nginx-stable]
    name = nginx stable repo
    baseurl = http://nginx.org/packages/centos/$releasever/$basearch/
    gpgcheck = 1
    enabled = 1
    gpgkey = https://nginx.org/keys/nginx_signing.key
    module_hotfixes = true
    
    [nginx-mainline]
    name = nginx mainline repo
    baseurl = http://nginx.org/packages/mainline/centos/$releasever/$basearch/
    gpgcheck = 1
    enabled = 0
    gpgkey = https://nginx.org/keys/nginx_signing.key
    module_hotfixes = true
    
    [nginx.repo]
    baseurl = http://nginx.org/packages/centos/7/$basearch/
    enabled = 1
    gpgcheck = 1
    name = nginx stable repo
    
    #2.准备nginx配置文件 ,比创建id
    [root@m01 ~]# vim /etc/nginx/nginx.conf 
    user  www;
    [root@m01 ~]# groupadd www -g 666
    [root@m01 ~]# useradd www -u666 -g666
    
    #3.准备php的安装包,解压并安装
    [root@m01 ~] mkdir package
    [root@m01 package]# rz
    [root@m01 package]# ll
    -rw-r--r-- 1 root root 19889622 Apr 28 10:39 php.tar.gz
    
    #4.准备php配置文件
    [root@m01 dan]# mkdir conf
    [root@m01 dan]# mv /etc/php.ini conf/
    [root@m01 dan]# cp /etc/php-fpm.d/www.conf conf/
    [root@m01 dan]# vim conf/php.ini
    upload_max_filesize = 200M
    post_max_size = 300M
    [root@m01 dan]# vim conf/www.conf 
    user = www
    group = www
    
    #5.准备discuze包
    [root@m01 package]# ls Discuz-DiscuzX-master.zip 
    Discuz-DiscuzX-master.zip
    [root@m01 package]# mkdir /code
    [root@m01 package]# unzip -d /code/Discuz-DiscuzX-master.zip 
    
    #6.准备discuz配置文件
    [root@m01 dan]# vim conf/discuz.conf
    server {
        listen 80;
        server_name discuz.com;
        root /code/discuz;
        index index.php;
    
        location ~* .php$ {
            fastcgi_pass 127.0.0.1:9000;
            fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
            include fastcgi_params;
        }
    }
    

    3)编写剧本

    [root@m01 dan]# cat base.yml 
    ---
    - hosts: all
      tasks:
        - name: stop firewalld
          systemd: name=firewalld state=stopped enabled=no
        - name: stop selinux
          selinux: state=disabled
        - name: create www gruop
          group: name=www gid=666 state=present
        - name: create www user
          user: name=www uid=666 group=www shell=/bin/bash create_home=false state=present
    - hosts: nginx
      tasks:
        - name: scp nginx.repo
          copy: src=/etc/yum.repos.d/nginx.repo dest=/etc/yum.repos.d/nginx.repo
        - name: install nginx
          yum: name=nginx state=present
        - name: cfg nginx server
          copy: src=/etc/nginx/nginx.conf dest=/etc/nginx
        - name: start nginx server
          systemd: name=nginx state=started enabled=yes
    
    - hosts: web_group
      tasks:
        - name: tar php 
          unarchive: src=/package/php.tar.gz dest=/opt/
        - name: install php server
          shell: "yum localinstall -y /opt/*.rpm"
        - name: cfg php
          copy: src=/dan/conf/php.ini dest=/etc/
        - name: sfg php 
          copy: src=/dan/conf/www.conf dest=/etc/php-fpm.d/
        - name: start php
          systemd: name=php-fpm state=started
        - name: create code dir
          file: path=/code owner=www group=www  state=directoy recurse=yes
        - name: cfg nginx discuz
          copy: src=/dan/conf/discuz.conf dest=/etc/nginx/conf.d/
        - name: restart nginx
          systemd: name=nginx state=restarted
    
    - hosts: db01
      tasks:
        - name: install db
          yum: name=mariadb-server state=present
        - name: install mysql-py
          yum: name=MySQL-python state=present
        - name: start db
          systemd: name=mariadb state=stared enabled=yes
        - name: create discuz database
          mysql_db: name=discuz state=present
        - name: create discuz user
          mysql_user: name="discuz" host="172.16.1.%" password="111" priv='*.*:ALL' state=present
    
    
  • 相关阅读:
    Redis学习笔记——环境搭建
    SQL 记录
    路径“D:svn.....”的访问被拒绝问题处理
    去除浏览器自动给input赋值的问题
    获取用户IP
    JS对身份证号码进行验证方法
    JS 实现倒计时
    SQL 游标
    .net上传图片实例
    生成唯一码
  • 原文地址:https://www.cnblogs.com/caodan01/p/14859872.html
Copyright © 2020-2023  润新知