您好,欢迎来到站长目录(28sn.com)!


Ansible之Playbook

来源:网络整理 浏览:341次 时间:2021-03-03
Playbook简介

palybook 是由一个或多个paly组成的列表。play的主要功能在于将事先归并为一组的主机装扮成事先通过ansible 中的 task 定义好的角色。从根本上来讲,所谓 task 无非是调用 ansible 的一个 module。将多个 play组织在一个 playbook 中,即可以让它们联同起来按事先编排好的机制同唱一台大戏。

一个playbook由以下几个部分组成:

  • Inventory
  • Modules
  • Ad Hoc Commands
  • Playbooks
    • tasks:即调用模块完成的操作
    • variables:变量
    • templates:模板
    • handlers:触发器,由某子任务触发执行操作
    • roles:角色

免费在线学习 https://ke.magedu.com

Inventory

ansible的主要功能在于批量主机操作,为了便捷地使用其中的部分主机,可以在inventory file中将其分组命名。默认的inventory file为/etc/ansible/hosts

inventory文件遵循INI文件风格,中括号中的字符为组名。可以将同一个主机同时归并到多个不同的组中;此外,当如若目标主机使用了非默认的SSH端口,还可以在主机名称之后使用冒号加端口号来标明。

[webservers]www1.magedu.com:2222www2.magedu.com[dbservers]db1.magedu.comdb2.magedu.comdb3.magedu.com

如果主机名称遵循相似的命名模式,还可以使用列表的方式标识各主机,例如:

[webservers]www[01:50].example.com[databases]db-[a:f].example.com

inventory file 中也可以设置 变量 ,方便后期 ansible 执行调用。

node2 ansible_ssh_host=192.168.118.15 ansible_ssh_user=root http_port=80node3 ansible_ssh_host=192.168.118.16 ansible_ssh_user=root http_port=8080

上面配置中 http_port 就是自定义的变量。当然在组中也可以设置该组所有主机相同的变量:

[webservers]www1.magedu.comwww2.magedu.com[webservers:vars]ntp_server=ntp.magedu.comnfs_server=nfs.magedu.com

注意:这里 webservers:vars 中 vars 是固定关键字写法。

Inventory 常用参数

这里只是列举常用参数:

ansible_ssh_host: 被管理主机及ipansible_ssh_port: 被管理主机端口ansible_ssh_pass: 如果没有设置密钥认证,则需要填写密码ansible_sudo_pass: linux sudo 切换用户时密码ansible_shell_type: shell 类型 bash 还是 xsh
Modules

ansible modules 有很多,之后会专门写一篇关于 modules 总结的文档。

Ad Hoc Commands

什么是 ad-hoc ?
当我们需要敲一些命令去快速的查看或者完成一项工作时,而不需要持久的存储这些命令,这样的命令就叫做 ad-hoc
ansible 就提供了两种方式去完成任务,一是 ad-hoc 命令,另一种是 ansible playbook ,前者可以解决一些简单的任务,后者解决较复杂的任务。
比如,当需要马上查看主机端口时,使用 ad-hoc 就是很高效的,
如:ansible [hostname] -m shell -a 'netstat -ntplu'

免费在线学习 https://ke.magedu.com

Playbook

playbook 核心元素:

  1. hosts:执行的远程主机列表
  2. tasks:任务集
  3. variables:内置变量或自定义变量在 playbook中使用
  4. notify 和 handlers 结合使用,由特定的条件触发操作,满足条件执行,否则不执行
  5. tags:标签,指定某条件执行,用于选择运行 playbook 中的部分代码
Playbook 语法

playbook 使用 yaml 语法格式,后缀为 yaml 也可以是 yml 要求及格式如下:

  1. 在单一一个playbook文件中,可以连续三个连子号(---)区分多个play。还有选择性的连续三个点好(...)用来表示play的结尾,也可省略。
  2. 次行开始正常写playbook的内容,一般都会写上描述该playbook的功能。
  3. 使用#号注释代码。
  4. 缩进必须统一,不能空格和tab混用。
  5. 缩进的级别也必须是一致的,同样的缩进代表同样的级别,程序判别配置的级别是通过缩进结合换行实现的。
  6. YAML文件内容和Linux系统大小写判断方式保持一致,是区分大小写的,k/v的值均需大小写敏感
  7. k/v的值可同行写也可以换行写。同行使用:分隔。
  8. v可以是个字符串,也可以是一个列表
  9. 一个完整的代码块功能需要最少元素包括 name: task
下面通过一个安装维护 httpd 服务来逐步引出 playbook中知识点

通过一个简单的示例查看 playbook 语法及格式:
首先在 /etc/ansible/hosts 中定义主机及主机组

[root@localhost ~]#cat /etc/ansible/hosts[test_hosts]node2 ansible_ssh_host=192.168.118.15 ansible_ssh_user=rootnode3 ansible_ssh_host=192.168.118.16 ansible_ssh_user=root

编写 playbook 脚本:

[root@localhost ~]#cat test.yml - hosts: test_hosts  remote_user: root  tasks:  - name: "echo hello hukey."    debug:      msg: "hello, hukey."

前三行基本是固定格式:

  1. hosts: [hostname | groupname] 要执行任务的主机或主机组
  2. remote_user: [username] 在主机组中执行任务的用户名
  3. tasks: 所有需要执行的任务集

示例1:在 test_hosts 主机上安装 httpd 服务 然后启动服务。

- hosts: test_hosts  remote_user: root  tasks:  - name: install httpd    yum: name=httpd state=latest  - name: start httpd    systemd: name=httpd enabled=yes state=started

上面的这个 playbook 就是安装 httpd 并启动服务,前三行是固定模式,在 tasks 中,每一个以 name 开头的就是一个小任务。所以 tasks中就是由一个一个小任务组成的。

Playbook 中的变量

如果要在 playbook 中使用变量,则需要 vars 关键字来定义:

- hosts: test_hosts  remote_user: root  vars:  - package: httpd  - service: httpd  tasks:  - name: install {{ package }}    yum: name={{ package }} state=latest  - name: start {{ service }}    systemd: name={{ service }} enabled=yes state=started

这里定义了两个变量 package=httpd 和 service=httpd
在引用变量时,用两个大括号:{{ variable_name }}

执行 Playbook

编写好 playbook 后,就需要通过 ansible-playbook 执行,常用参数如下:

--check  or -C    #只检测可能会发生的改变,但不真正执行操作--syntax-check    # 语法检查,不执行--list-hosts      #列出运行任务的主机--list-tags       #列出playbook文件中定义所有的tags--list-tasks      #列出playbook文件中定义的所以任务集--limit           #主机列表 只针对主机列表中的某个主机或者某个组执行-f                #指定并发数,默认为5个-t                #指定tags运行,运行某一个或者多个tags。(前提playbook中有定义tags)-v                #显示过程  -vv  -vvv更详细

通常,直接使用 ansible-playbook apache.yml 执行:

[root@localhost ~]#ansible-playbook apache.yml PLAY [test_hosts] ***********************************************************TASK [Gathering Facts] ******************************************************ok: [node3]ok: [node2]TASK [install httpd] ********************************************************changed: [node3]changed: [node2]TASK [start httpd] **********************************************************changed: [node3]changed: [node2]PLAY RECAP ******************************************************************node2: ok=3    changed=2    unreachable=0    failed=0    skipped=0    rescued=0 ignored=0 node3: ok=3    changed=2    unreachable=0    failed=0    skipped=0    rescued=0 ignored=0

执行 playbook 时

  1. 发现主机是否存在或连通
  2. 开始执行tasks 中的子任务

上面的 playbook中只有2个子任务,通过执行过程可以看出,ansible 在执行 playbook 时,是按照任务为中心的思想来执行的, 也就是 第一个任务,在所有的主机上执行完毕,然后在将第二个任务在所有主机上执行。其中 ok 表示每一步执行的是否成功,而 changed 则表示执行该playbook 被管理主机是否发生了更改,如果被管理主机没有发生更改则不会有 changed,再次执行该playbook:

[root@localhost ~]#ansible-playbook apache.yml PLAY [test_hosts] *************************************************************TASK [Gathering Facts] ********************************************************ok: [node3]ok: [node2]TASK [install httpd] ********************************************************ok: [node3]ok: [node2]TASK [start httpd] *******************************************************ok: [node3]ok: [node2]PLAY RECAP **************************************************************node2: ok=3    changed=0    unreachable=0    failed=0    skipped=0    rescued=0 ignored=0node3: ok=3    changed=0    unreachable=0    failed=0    skipped=0    rescued=0 ignored=0

因为第一次已经安装启动了, 再次执行 playbook 则不发生任何更改。
需求又来了, 要修改主机的 httpd 端口为 8080
思路:ansible 主机需要有一份 修改好端口的配置文件,将配置文件推送到被管理主机,然后重启服务。
修改如下:

- hosts: test_hosts  remote_user: root  vars:  - package: httpd  - service: httpd  tasks:  - name: install {{ package }}    yum: name={{ package }} state=latest  - name: copy configuration file    copy: src=/root/conf/httpd.conf dest=/etc/httpd/conf/httpd.conf  - name: restart {{ service }}    systemd: name={{ service }} enabled=yes state=restarted

copy: src=/root/conf/httpd.conf dest=/etc/httpd/conf/httpd.conf
/root/conf/httpd.conf 为 ansible 主机本地路径,在该配置文件中修改端口为: 8080 覆盖到被管理主机的 /etc/httpd/conf/httpd.conf
对比刚开始的 playbook 做了改动,加入了-name: copy configration file 并将 start httpd 修改为 restart 执行如下:

[root@localhost ~]#ansible-playbook apache.yml PLAY [test_hosts] **********************************************************TASK [Gathering Facts] *****************************************************ok: [node2]ok: [node3]TASK [install httpd] *******************************************************ok: [node3]ok: [node2]TASK [copy configuration file] *********************************************changed: [node3]changed: [node2]TASK [restart httpd] *******************************************************changed: [node2]changed: [node3]PLAY RECAP *****************************************************************node2: ok=4    changed=2    unreachable=0    failed=0    skipped=0    rescued=0 ignored=0node3: ok=4    changed=2    unreachable=0    failed=0    skipped=0    rescued=0 ignored=0

OK,执行没有任何问题,以后每次修改端口都可以直接在本地修改,然后执行下 playbook 推送再重启就好了,但是上面的写法并不完美。就算配置文件没有修改依然会重启服务,这是没有必要的。有没有一种方法,当修改了配置文件才重启服务, 如果没有修改则不重启呢?这就需要用到 notify + handlers 处理机制。

notify + handlers

Handlers 和 notify 结合使用,由特定条件触发的操作,满足条件才执行,否则不执行。这里需要满足的条件是,当配置文件修改,playbook 如下:

- hosts: test_hosts  remote_user: root  vars:  - package: httpd  - service: httpd  tasks:  - name: install {{ package }}    yum: name={{ package }} state=latest  - name: copy configuration file    copy: src=/root/conf/httpd.conf dest=/etc/httpd/conf/httpd.conf    notify:    - restart httpd  - name: start {{ service }}    systemd: name={{ service }} enabled=yes state=started  handlers:  - name: restart httpd    systemd: name=httpd state=restarted

在 copy 下一行加入了 notify 然后在最后添加 handlers 注意格式!
修改配置文件:/root/conf/httpd.conf Listen:8000 然后执行 playbook

[root@localhost ~]#ansible-playbook apache.yml PLAY [test_hosts] **********************************************************TASK [Gathering Facts] *****************************************************ok: [node2]ok: [node3]TASK [install httpd] *******************************************************ok: [node3]ok: [node2]TASK [copy configuration file] *********************************************changed: [node2]changed: [node3]TASK [start httpd] *********************************************************ok: [node2]ok: [node3]RUNNING HANDLER [restart httpd] ********************************************changed: [node2]changed: [node3]PLAY RECAP *****************************************************************node2: ok=5    changed=2    unreachable=0    failed=0    skipped=0    rescued=0 ignored=0node3: ok=5    changed=2    unreachable=0    failed=0    skipped=0    rescued=0 ignored=0

配置文件修改,在执行子任务时触发了 notify 定义触发器,执行了 restart ,再次执行 playbook 试试:

[root@localhost ~]#ansible-playbook apache.yml PLAY [test_hosts] **********************************************************TASK [Gathering Facts] *****************************************************ok: [node2]ok: [node3]TASK [install httpd] *******************************************************ok: [node3]ok: [node2]TASK [copy configuration file] *********************************************ok: [node2]ok: [node3]TASK [start httpd] *********************************************************ok: [node3]ok: [node2]PLAY RECAP *****************************************************************node2: ok=4    changed=0    unreachable=0    failed=0    skipped=0    rescued=0 ignored=0node3: ok=4    changed=0    unreachable=0    failed=0    skipped=0    rescued=0 ignored=0

再次执行时,配置文件并没有发生任何变化,所以这里没有触发 restart httpd 这样比上面 每次执行都重启要智能很多了吧?但是依然不完美。每次执行 playbook 都会执行一些没必要的子任务,比如:TASK [install httpd] 和 TASK [start httpd] 这两个子任务在安装执行之后一般不会在用到了, 但是删除了又不能保证 playbook 的完整性,这时候就需要 tags 出马了。

Tags

tags 便签的意思,也就是为子任务打一个标签,然后就可以通过 ansible-playbook 执行打标签的部分,其他子任务不予执行,如下:

- hosts: test_hosts  remote_user: root  vars:  - package: httpd  - service: httpd  tasks:  - name: install {{ package }}    yum: name={{ package }} state=latest  - name: copy configuration file    copy: src=/root/conf/httpd.conf dest=/etc/httpd/conf/httpd.conf    notify:    - restart httpd    tags:    - updateConf  - name: start {{ service }}    systemd: name={{ service }} enabled=yes state=started  handlers:  - name: restart httpd    systemd: name=httpd state=restarted

[name: copy configuration file] 子任务最后加入了 tags: updateConf ,然后修改配置文件 /root/conf/httpd.conf端口为 9090
通过 --list-tags 查看标签

[root@localhost ~]#ansible-playbook apache.yml --list-tagsplaybook: apache.yml  play #1 (test_hosts): test_hosts  TAGS: []      TASK TAGS: [updateConf]

通过 ansible-playbook apache.yml -t updateConf 执行打标签的子任务:

[root@localhost ~]#ansible-playbook apache.yml -t updateConfPLAY [test_hosts] **********************************************************TASK [Gathering Facts] *****************************************************ok: [node2]ok: [node3]TASK [copy configuration file] *********************************************changed: [node3]changed: [node2]RUNNING HANDLER [restart httpd] ********************************************changed: [node2]changed: [node3]PLAY RECAP *****************************************************************node2: ok=3    changed=2    unreachable=0    failed=0    skipped=0    rescued=0 ignored=0node3: ok=3    changed=2    unreachable=0    failed=0    skipped=0    rescued=0 ignored=0

可以看到,所有子任务中,只是执行了 TASK [copy configuration file] 子任务,这样的 playbook 就趋近完美了。可以再次执行,再次执行时由于httpd.conf 没有发生修改,所以不会触发 restart httpd,如下:

[root@localhost ~]#ansible-playbook apache.yml -t updateConfPLAY [test_hosts] **********************************************************TASK [Gathering Facts] *****************************************************ok: [node2]ok: [node3]TASK [copy configuration file] *********************************************ok: [node2]ok: [node3]PLAY RECAP *****************************************************************node2: ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0 ignored=0 node3: ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0 ignored=0
总结一下:
  1. 通过上面的安装、维护 httpd 服务编写的 playbook 中,使用到了:
  2. 变量:通过 vars 关键字定义变量;
  3. notify + handlers 子任务触发器,触发执行,不触发则不执行;
  4. tags:标签,使用 ansible-playbook xxx.yml -t [tag_name] 只执行打标签的子任务,其他任务不予执行。

除了上面,还有一些功能也是非常使用的。

条件判断

很多文中这里都是 流程控制,我觉得用 条件判断 来定义更简单易懂。
playbook 中使用 when 关键字来进行条件判断,这里的 when 相当于 shell 中的 if ,它是 jinja2 的语法。
有这样一个需求:如果主机的 IP 为: 192.168.118.15 则打印它的主机名,实现如下:

有这样一个需求:如果主机的 IP 为: 192.168.118.15 则打印它的主机名,实现如下:

- hosts: all  remote_user: root  tasks:  - name: IP -> Host    debug: msg={{ ansible_fqdn }}    when: ansible_all_ipv4_addresses[0] == '192.168.118.15'

关键字: when 定义条件判断, 当 ip 为:192.168.118.15 的时候打印 主机的 fqdn 否则跳过,执行如下:

[root@localhost ~]#ansible-playbook hosts.yml PLAY [all] *****************************************************************TASK [Gathering Facts] *****************************************************ok: [node3]ok: [node2]TASK [IP -> Host] **********************************************************ok: [node2] => {    "msg": "node2.super.com"}skipping: [node3]PLAY RECAP *****************************************************************node2: ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0 ignored=0 node3: ok=1    changed=0    unreachable=0    failed=0    skipped=1    rescued=0 ignored=0

定义了两台主机,其中 node3 不满足条件, 则跳过 skip

循环

在playbook中使用循环的场景还是很多的, 比如安装一些 程序包,处理一堆文件,创建一批用户等。
playbook 中还有循环功能,关键字: item 和 with_items

需求:为 test_hosts 主机组创建一批新用户

- hosts: test_hosts  remote_user: root  tasks:  - name: add users    user: name={{ item }}    with_items:    - user10    - user20    - user30

item 为固定变量关键字,循环内容为 with_items 中的值,执行结果如下

[root@localhost ~]#ansible-playbook adduser.yml PLAY [test_hosts] **********************************************************TASK [Gathering Facts] *****************************************************ok: [node3]ok: [node2]TASK [add users] ***********************************************************changed: [node3] => (item=user10)changed: [node2] => (item=user10)changed: [node3] => (item=user20)changed: [node2] => (item=user20)changed: [node2] => (item=user30)changed: [node3] => (item=user30)PLAY RECAP *****************************************************************node2: ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0 ignored=0 node3: ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0 ignored=0
reigster

在 playbook 中 task 之间 可以通过 register 接收结果并传递

- hosts: node2  remote_user: root  tasks:  - name: register hostname    shell: "hostname"    register: info  - name: display vars    debug: msg="{{ info.stdout }}"

执行结果:

[root@localhost ~]#ansible-playbook host.yml PLAY [node2] ***************************************************************TASK [Gathering Facts] *****************************************************ok: [node2]TASK [register hostname] ***************************************************changed: [node2]TASK [display vars] ********************************************************ok: [node2] => {    "msg": "node2.super.com"}PLAY RECAP *****************************************************************node2: ok=3    changed=1    unreachable=0    failed=0    skipped=0    rescued=0 ignored=0 

通过上面的示例,可以观察出 子任务1通过 register获取到执行结果,在子任务2中通过 变量名 info 打印出来。这样的方式可以通过执行命令来判断结果是否是想要的结果。

点击领取免费在线学习资料 https://ke.magedu.com

推荐站点

  • 我爱发烧音乐我爱发烧音乐

    我爱发烧音乐囊括了从流行音乐到古典音乐多个类型的音乐作品,专栏推荐最新的音乐,提供音乐排名榜单!可供免费线上收听音乐,歌曲流畅,音效极佳! 网站提供的钢琴以及二胡专栏,可供收听者,陶冶情操,改善心情,是难得的轻音乐典藏!

    www.520fs.com
  • 世纪音乐网世纪音乐网

    世纪音乐网是专业的在线音乐试听MP3下载网站。歌曲总计30余万首,收录了网上最新歌曲和流行音乐,DJ舞曲,非主流音乐,经典老歌,劲舞团歌曲,搞笑歌曲,儿童歌曲,英文歌曲等。是您上网听歌的最佳网站。

    www.ssjj.com
  • 杭州网杭州网

      杭州网是杭州地区唯一的新闻门户网站,由中共杭州市委宣传部、杭州日报报业集团和杭州广播电视集团共同组建的杭州网络传媒有限公司运营。

    www.hangzhou.com.cn
  • 深圳在线深圳在线

      深圳在线 www.szol.net是深圳本地最大、最早的地方生活资讯网站之一,网站名“深圳在线www.szol.net”由南方报业传媒集团编辑委员会总编辑、南方日报社总编辑、南方都市报总编辑、南方书画院名誉院长王春芙亲笔题名,深圳在线www.szol.net团队与深圳热线www.szonline.net、奥一网www.oeeee.com都源于全国最早成立于1996年的知名网络公司——深圳万用网。

    www.szol.net
  • 今题网今题网

     今题网- 中国领先的社区服务网,提供社区服务, 在线交友和商家推广服务,于2004年创建上线,公司现有员工超过百名。今题网自成立以来,凭借其独特的定位和丰富的社区交友功能, 凭借其团队超强的搜索引擎优化技术吸引超过千万的用户成为今题网的注册会员。

    www.jinti.com

鄂公网安备 42062502000001号