• Ansible-Playbook


    前置

    Playbook介绍
    1. playbook 剧本是由一个或多个“play”组成的列表
    2. Playbook 文件是采用YAML语言编写的
    3. 用户通过ansible命令直接调用yml语言写好的playbook,playbook由多条play组成,每条play都有一个任务(task)相对应的操作,然后调用模块modules,应用在主机清单上,通过ssh远程连接,从而控制远程主机或者网络设备
    YAMl 语言介绍

    YAML是一个可读性高的用来表达资料序列的格式。YAML 官方网站:http://www.yaml.org

    YAML 语言特性
    • YAML的可读性好
    • YAML和脚本语言的交互性好
    • YAML使用实现语言的数据类型
    • YAML有一个一致的信息模型
    • YAML易于实现
    • YAML可以基于流来处理
    • YAML表达能力强,扩展性好
    YAML语法简介
    • 在单一文件第一行,用连续三个连字号“-” 开始,还有选择性的连续三个点号( … )用来表示文件的结尾
    • 次行开始正常写Playbook的内容,一般建议写明该Playbook的功能
    • 使用#号注释代码
    • 缩进必须是统一的,不能空格和tab混用
    • 缩进的级别也必须是一致的,同样的缩进代表同样的级别,程序判别配置的级别是通过缩进结合换行来实现的
      YAML文件内容是区别大小写的,key/value的值均需大小写敏感
    • 多个key/value可同行写也可换行写,同行使用,分隔
    • v可是个字符串,也可是另一个列表
    • 一个完整的代码块功能需最少元素需包括 name 和 task
    • 一个name只能包括一个task
    • YAML文件扩展名通常为yml或yaml

    Playbook核心元素

    • Hosts 执行的远程主机列表
    • Tasks 任务集
    • Variables 内置变量或自定义变量在playbook中调用
    • Templates 模板,可替换模板文件中的变量并实现一些简单逻辑的文件
    • Handlers 和 notify 结合使用,由特定条件触发的操作,满足条件方才执行,否则不执行
    • tags 标签 指定某条任务执行,用于选择运行playbook中的部分代码。ansible具有幂等性,因此会自动跳过没有变化的部分,即便如此,有些代码为测试其确实没有发生变化的时间依然会非常地长。此时,如果确信其没有变化,就可以通过tags跳过此些代码片断

    handlers和notify结合使用触发条件

    task列表和action
    • play的主体部分是task list。task list中的各任务按次序逐个在hosts中指定的所有主机上执行,即在所有主机上完成第一个任务后再开始第二个。在运行自上而下某playbook时,如果中途发生错误,所有已执行任务都将回滚,因此再更正playbook后重新执行一次即可。
    • task的目的是使用指定的参数执行模块,而在模块参数中可以使用变量。模块执行是幂等的,这意味着多次执行是安全的,因为其结果均一致。
    • 每个task都应该有其name,用于playbook的执行结果输出,建议其内容尽可能清晰地描述任务执行步骤。如果未提供name,则action的结果将用于输出。
    Handlers

            用于当关注的资源发生变化时,才会采取一定的操作。Notify可用于在每个play的最后被触发,这样可避免多次有改变发生时每次都执行指定的操作,仅在所有的变化发生完成后一次性地执行指定操作。在notify中列出的操作成为handler,也即notify中调用handler中定义的操作。

    例如:方便直观看到变化,我们执行更新文件task(触发重启mysql服务的handler),然后执行关闭mysql服务task,最后观察重启的handler是否生效。

    1. - hosts: yzb
    2. remote_user: root
    3. tasks:
    4. - name: task1
    5. file: path=/opt/testfile
    6. state=touch
    7. notify: restart mysqld
    8. - name: task2
    9. systemd:
    10. name: mysqld
    11. state: stopped
    12. handlers:
    13. - name: restart mysqld
    14. systemd:
    15. name: mysqld
    16. state: restarted

    可以看到此时mysql启动时间为18号17:15

    我们使用ansible-playbook执行对应的playbook,可以看到连接成功,task对应颜色为黄色,表示执行成功且发生了变动。

    此时我们回到被控制端,查看mysql状态,可以看到启动时间已经变为最近时间

    由此我们可以得出结论,剧本是按照顺序执行的,但是handler仅在所有的变化发生完成后才会去一次性地执行指定操作。

    handlers也可以触发多个

    1. - hosts: yzb
    2. remote_user: root
    3. tasks:
    4. - name: task1
    5. file: path=/opt/testfile
    6. state=touch
    7. notify:
    8. - restart mysqld
    9. - restart nginx
    10. - name: task2
    11. systemd:
    12. name: mysqld
    13. state: stopped
    14. handlers:
    15. - name: restart mysqld
    16. systemd:
    17. name: mysqld
    18. state: restarted
    19. - name: restart nginx
    20. systemd:
    21. name: nginx
    22. state: restarted

    当然,也能实现立即执行对应handler,这要用到- meta: flush_handlers模块

    tags标签

    通过指定标签来执行特定的动作

            -t 指定执行某一标签对应的所有任务

            --skip-tags 表示要跳过的指定的标签任务

    1. ---
    2. - hosts: websrvs
    3. remote_user: root
    4. tasks:
    5. - name: install httpd package
    6. yum: name=httpd
    7. tags: inshttpd
    8. - name: copy conf file
    9. copy: src=files/httpd.conf dest=/etc/httpd/conf/ backup=yes
    10. notify: restart service
    11. - name: start service
    12. service: name=httpd state=started enabled=yes
    13. tags: rshttpd
    14. handlers:
    15. - name: restart service
    16. service: name=httpd state=restarted
    执行启动服务的tags
    [root@ansible145 ansible]# ansible-playbook -t rshttpd httpd.yml
    也可以针对多个标签执行脚本
    1. #执行多个tags
    2. [root@ansible145 ansible]# ansible-playbook -t inshttpd,rshttpd httpd.yml
    跳过某个标签执行脚本
    ansible-playbook httpd.yml --skip-tags rshttpd

    变量

    变量名:仅能由字母、数字和下划线组成,且只能以字母开头。

    调用:通过“{{ variable_name }}”调用变量,且变量名前后建议加空格

    批量操作
    1. [root@120 ansible]# cat task-restart.yml
    2. - hosts: yzb
    3. remote_user: root
    4. tasks:
    5. - name: task1
    6. systemd:
    7. name: "{{ item }}"
    8. state: restarted
    9. loop:
    10. - mysqld
    11. - nfs
    12. [root@120 ansible]#
    变量来源:
    1. 1.通过命令行指定变量,优先级最高
    2. ansible-playbook -e varname=value
    3. 2.在playbook文件中定义
    4. vars:
    5. - var1: value1
    6. - var2: value2
    7. 3.在独立的变量YAML文件中定义
    8. - hosts: all
    9. vars_files:
    10. - vars.yml
    11. 4.在 /etc/ansible/hosts 中定义
    12. 主机变量:主机组中主机单独定义,优先级高于组变量
    13. 组变量:针对主机组中所有主机定义统一变量
    在playbook 命令行中定义变量

    范例:

    1. vim var2.yml
    2. ---
    3. - hosts: websrvs
    4. remote_user: root
    5. tasks:
    6. - name: install package
    7. yum: name={{ pkname }} state=present
    8. ansible-playbook –e pkname=httpd var2.yml
    在playbook文件中定义变量

    范例:

    1. [root@120 ansible]# cat mysql-variables.yml
    2. - hosts: yzb
    3. remote_user: root
    4. vars:
    5. - service: mysqld
    6. tasks:
    7. - name: task1
    8. file: path=/opt/testfile
    9. state=touch
    10. notify: restart mysqld
    11. - name: task2
    12. systemd:
    13. name: "{{ service }}"
    14. state: stopped
    15. handlers:
    16. - name: restart mysqld
    17. systemd:
    18. name: "{{ service }}"
    19. state: restarted
    20. [root@120 ansible]# ansible-playbook mysql-variables.yml
    使用变量文件

    可以在一个独立的playbook文件中定义变量,在另一个playbook文件中引用变量文件中的变量,比playbook中定义的变量优化级高

    范例:

    1. [root@120 ansible]# cat mysql-variables-2.yml
    2. - hosts: yzb
    3. remote_user: root
    4. vars_files:
    5. - ./vars.yaml
    6. tasks:
    7. - name: task1
    8. file: path=/opt/testfile
    9. state=touch
    10. notify: restart mysqld
    11. - name: task2
    12. systemd:
    13. name: "{{ service }}"
    14. state: stopped
    15. handlers:
    16. - name: restart mysqld
    17. systemd:
    18. name: "{{ service }}"
    19. state: restarted
    20. [root@120 ansible]# cat vars.yaml
    21. service: mysqld
    22. [root@120 ansible]# ansible-playbook mysql-variables-2.yml
    主机清单文件中定义变量

    范例:

    1. vim /etc/ansible/hosts
    2. [websrvs]
    3. 192.168.0.101 hname=www1
    4. 192.168.0.102 hname=www2
    5. [websvrs:vars]
    6. mark=“-”
    7. domain=magedu.org
    8. ansible websvrs –m hostname –a ‘name={{ hname }}{{ mark }}{{ domain }}’

    templates

    即用一个文件作为模板,传送到远程的被控机上去,并且针对被控机的配置去改写文件,一般是配置文件。template不能作为命令行调用,只能写在playbook中进行调用。

    范例:以yum安装nginx为例

    1.创建templates文件
    [root@ansible ansible]# mkdir templates
    2.复制nginx的配置文件到templates中,并重命名
    [root@ansible ansible]# cp /etc/nginx/nginx.conf templates/nginx.conf.j2
    3.编辑脚本
    1. ---
    2. - hosts: websrvs
    3. remote_user: root
    4. tasks:
    5. - name: install package
    6. yum: name=nginx
    7. - name: copy template
    8. template: src=/nginx.conf.j2 dest=/ect/nginx/nginx.conf
    9. - name: start service
    10. service: name=nginx state=started enabled=yes

    注意:

    如果j2文件放在templates文件下,可以直接写template: src=nginx.conf.j2,ansible可以自动识别出来;

    如果j2文件没有放在templates文件下,需要加上绝对路径template: src=xx/xx/nginx.conf.j2

    4.检查并执行脚本
    1. [root@ansible145 ansible]# ansible-playbook -C testtempl.yml
    2. [root@ansible145 ansible]# ansible-playbook testtempl.yml

    when

    when 判断在用于控制在满足when所指定的条件的情况下 才执行相应的动作。

    在when关键字中引用变量时,变量名不需要加"{{ }}",我们可以使用when关键字为任务指定条件,条件成立,则执行任务,条件不成立,则不执行任务。

    示例1:

    根据不同操作系统,安装不同软件

    1. ansible_distribution 变量可以获取主机的发行版本
    2. [root@120 ansible]# ansible yzb -m setup -a 'filter=ansible_distribution'
    3. 192.168.255.123 | SUCCESS => {
    4. "ansible_facts": {
    5. "ansible_distribution": "CentOS",
    6. "discovered_interpreter_python": "/usr/bin/python"
    7. },
    8. "changed": false
    9. }
    10. playbook 如下
    11. [root@120 ansible]# cat when.yml
    12. - hosts: yzb
    13. remote_user: root
    14. tasks:
    15. - name: Centos install httpd
    16. yum:
    17. name: httpd
    18. state: installed
    19. when: ansible_distribution=="CentOS" <==判断版本语句,此处变量不需要{{ }}引用。
    20. # when也可以使用andor方式进行多项匹配。
    21. - name: Ubuntu install httpd2
    22. yum:
    23. name: httpd2
    24. state: present
    25. when: (ansible_distribution == "CentOS") <==判断版本语句,此处变量不需要{{ }}引用。
    示例2:

    判断kubelet.service 服务是否正常运行,运行就停止,不运行不作处理

    1. [root@k8s-master-1 test]# vim when.yaml
    2. ---
    3. - hosts: web
    4. remote_user: root
    5. tasks:
    6. - name: Check Nginx Status
    7. shell: systemctl status kubelet.service
    8. register: check_k8s
    9. - name: Print check_k8s
    10. debug:
    11. var:
    12. "check_k8s" <==#通过debug的var输出该变量的所有内容
    13. - name:
    14. service:
    15. name: kubelet.service
    16. state: stopped
    17. when: check_k8s.rc == 0 <==.rc是check_nginx变量中的执行结果,见下面的执行过程

    when_items

    迭代:当有需要重复性执行的任务时,可以使用迭代机制。对迭代项的引用,固定变量名为“item”,要在task中使用when_items给定要迭代的元素列表。

    示例1:

    批量下载程序(和变量里使用loop一样)

    1. [root@ansible ansible]# vim testitem.yml
    2. ---
    3. - hosts: yzb
    4. remote_user: root
    5. tasks:
    6. - name: create some files
    7. file: name=/data/{{ item }} state=touch
    8. when: ansible_distribution_major_version == "7"
    9. with_items:
    10. - file1
    11. - file2
    12. - file3
    13. - name: install some packages
    14. yum: name={{ item }}
    15. with_items:
    16. - htop
    17. - sl
    18. - hping3
    实例2:

    迭代嵌套子变量——批量创建用户名

    1. [root@ansible ansible]# vim testitem3.yml
    2. ---
    3. - hosts: yzb
    4. remote_user: root
    5. tasks:
    6. - name: create some group
    7. group: name={{ item }}
    8. when: ansible_distribution_major_version == "7"
    9. with_items:
    10. - g1
    11. - g2
    12. - g3
    13. - name: create some user
    14. user: name={{ item.name }} group {{ item.group }}
    15. with_items:
    16. - { name: 'user1', group: 'g1' }
    17. - { name: 'user2', group: 'g2' }
    18. - { name: 'user3', group: 'g3' }

    ansible中的条件判断和tests

    1、条件判断和tests

    tests会将判断后的布尔值返回,如果条件成立,则返回true,如果条件不成立,tests会返回false,我们通常会在条件判断时使用到tests

    示例:

    1. ---
    2. - hosts: web
    3. remote_user: root
    4. vars:
    5. testpath: /tmp
    6. tasks:
    7. - name: test
    8. debug:
    9. msg: "file exist"
    10. when: testpath is exists
    11. "is exists"中的"exists"就是tests的一种,判断ansible主机中的对应路径是否存在(注意:是ansible控制主机中的路径,与目标主机没有关系),当对应的路径存在于ansible控制节点时,"is exists"为真。
    12. "is not exists"表示对应路径不存在时返回真。
    2、判断变量的tests
    • defined:判断变量是否已经定义,已经定义返回真
    • undefind:判断变量是否已经定义,没定义就返回真
    • none:判断变量值是否为空,如果变量已经定义,但变量值为空,则返回真

    示例:

    1. ---
    2. - hosts: web
    3. remote_user: root
    4. vars:
    5. test1: vl
    6. test2:
    7. tasks:
    8. - debug:
    9. msg: "test1 is defined"
    10. when: test1 is defined
    11. - debug:
    12. msg: "test1 is undefind"
    13. when: test2 is undefined
    3、判断执行结果的一些tests

    success或者succeeded:通过任务的返回信息判断任务的执行状态,任务执行成功则返回真

    failure 或 failed:通过任务的返回信息判断任务的执行状态,任务执行失败则返回真

    change 或 changed:通过任务的返回信息判断任务的执行状态,任务执行状态为changed则返回真

    skip 或 skipped:通过任务的返回信息判断任务的执行状态,当任务没有满足条件,而被跳过执行时,则返回真

  • 相关阅读:
    主流开发环境和开发语言介绍
    试编写算法(用C语言)打印值为x的结点的所有祖先,假设值为x的结点不多于一个。(递归实现和非递归实现)
    自适应螺旋飞行麻雀搜索算法
    Revit中【管线倒角】自定义长度
    【vue 原理相关】
    ResNet网络的改进版:ResNeXt
    山东2024年高企申报条件
    在VB类模块中使用计时器
    linux的基本工具【yum和vim】
    Flutter快学快用15 服务通信:Flutter 中常见的网络协议
  • 原文地址:https://blog.csdn.net/ArrogantB/article/details/139865093