Playbook简介 playbook是ansible用于配置,部署,和管理被控节点的剧本。 通过playbook的详细描述,执行其中的一系列tasks,可以让远端主机达到预期的状态。playbook就像Ansible控制器给被控节点列出的的一系列to-do-list,而被控节点必须要完成。 也可以这么理解,playbook 字面意思,即剧本,现实中由演员按照剧本表演,在Ansible中,这次由计算机进行表演,由计算机安装,部署应用,提供对外服务,以及组织计算机处理各种各样的事情。
Playbook的使用优势 功能比ansible命令更强大 能很好的控制先后执行顺序, 以及依赖关系 语法展现更加的直观 ansible命令无法持久使用, playbook 可以持久使用 剧本的书写格式要求 语法格式 ansible剧本格式:遵循yaml语法格式(类似python脚本编写格式) rsync配置文件格式:ini语法格式 sersync配置文件格式:xml语法格式(标签格式)
注意缩进 合理的信息缩进,两个空格表示一个缩进关系 一定不要使用tab
冒号 所有冒号后面都要加上空格
1 2 3 - hosts: 10.1 .1 .20 tasks: yum: name=rsync state=installed
短横线 - 列表功能 使用短横线构成列表信息,短横线后面需要有空格
剧本书写 文件名格式 剧本文件拓展名为xxx.yaml
方便识别文件是一个剧本文件 文件编写时会有颜色提示 练习: 写一个剧本,使用yum/copy/service模块安装部署启动rsync服务
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 --- - hosts: rsync remote_user: root gather_facts: no tasks: - name: "01-add-user" user: name=rsync create_home=no shell=/sbin/nologin uid=2021 - name: "02-installed-rsync" yum: name=rsync state=installed - name: "03-copy rsync.conf" copy: src=/playbook/rsync/rsyncd.conf dest=/etc/ - name: "04-create passwd conf" copy: content="rsync_backup:123456" dest=/etc/rsync.passwd mode=0600 - name: "05-create rsync dir" file: path=/backup state=directory owner=rsync group=rsync - name: "06-started rsync service" service: name=rsyncd state=started - name: "07-enabled rsync service" service: name=rsyncd enabled=yes
剧本检查模拟 1 2 3 4 5 6 7 8 # ansible-playbook --syntax-check rsync.yaml # ansible-playbook -C rsync.yaml # ansible-playbook rsync.yaml
nfs服务剧本 服务端 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 - hosts: nfs_server tasks: - name: 01 -add user user: name: www shell: /sbin/nologin create_home: no state: present uid: 1010 - name: 02 -installed nfs server yum: name=nfs-utils state=latest - name: 03 -copy nfs exports copy: src=/playbook/exports dest=/etc/ - name: 04 -create data dir file: path=/nfs-data state=directory owner=www group=www - name: 05 -start rpcbind service: name=rpcbind state=started enabled=yes - name: 06 -start nfs service: name=nfs state=started enabled=yes
客户端 1 2 3 4 5 6 7 8 9 10 - hosts: nfs_client tasks: - name: 01 -add user user: name=www create_home=no shell=/sbin/nologin uid=1010 - name: 02 -installed nfs-client yum: name=nfs-utils state=latest - name: 03 -create mount data file: path=/mnt/data state=directory owner=www - name: 04 -mount data mount: path=/mnt/data src=10.1.1.60:/nfs-data fstype=nfs opts=defaults state=mounted
剧本高级特性 我们已经体验了使用剧本来安装服务,但是上述的简单ansible剧本存在一定的局限性
全部写成一行虽然看起来整洁,但是有一些特性没办法使用 比如同时需要创建多个目录,启动多个服务,需要重复写多条语句 参数不直观,不好修改 剧本里写的是启动服务,如果配置文件发生变化,重复执行不会重启服务 不过没有关系,等学习了下面的高级特性,然后我们可以换一种写法
循环(loop) 官方文档:https://docs.ansible.com/ansible/latest/user_guide/playbooks_loops.html
使用情景:
需要创建多个目录 需要启动多个服务 具体实现: 同时创建2个目录/data和/backup
1 2 3 4 5 6 7 8 9 10 11 - hosts: 10.1 .1 .20 tasks: - name: 01 -create dir data and backuo file: path: "{{ item }} " state: directory owner: www group: www loop: - /data - /backup
同时创建多个用户(字典类型)
1 2 3 4 5 6 7 8 9 10 11 --- - name: create user hosts: 10.1 .1 .20 tasks: - name: create user and group user: name: "{{ item.name }} " group: "{{ item.groups }} " loop: - {name: 'user01' , groups: 'wheel' } - {name: 'user02' , groups: 'root' }
变量(vars) 官方文档:https://docs.ansible.com/ansible/latest/user_guide/playbooks_variables.html 使用情景:
自定义某个名称,在任务中会多次引用 从主机收集的系统信息中提取某个变量并引用,例如网卡信息 具体实现:
自定义一个文件名变量,创建文件时引用:
1 2 3 4 5 6 7 8 9 10 - hosts: 10.1 .1 .20 vars: file_name: boysec tasks: - name: 01 -create vars dir file: path: "/data/{{ file_name }} " state: directory owner: www group: www
使用变量获取主机的eth1地址:
1 2 3 4 - hosts: 10.1 .1 .20 tasks: - name: 01 -get ip address shell: "echo {{ ansible_facts.eth0.ipv4.address }} " >/root/ip.txt
在主机hosts中指定变量:
1 2 3 4 5 6 tail -5 /etc/ansible/hosts [backup ] 10.1 .1 .30 [backup:vars ] file_name="boysec"
软件安装:
1 2 3 4 5 6 7 8 9 10 11 12 - hosts 10.1 .1 .20 vars: - web_packages: nginx-1.15.2 - ftp_packages: vsftp tasks: - name: Installed {{ web_packages }} and {{ ftp_packages }} yum: name: - "{{ web_packages }} " - "{{ ftp_packages }} " state: present
注册变量(register) 使用情景:将配置文件的状态注册成一个变量,方便其他任务引用 具体实现: 1.将配置文件的状态注册成一个服务变量并打印出来
1 2 3 4 5 6 7 8 - hosts: 10.1 .1 .20 tasks: - name: 01 -register nginx status shell: netstat -lnpt|grep nginx register: nginx_port - name: 02 -out nginx status debug: msg: "{{ nginx_port.stdout_lines }} "
2.打印多个信息:
1 2 3 4 5 6 7 8 9 10 11 12 - hosts: rsync tasks: - name: 01 -echo hostname shell: echo $(hostname) register: rsync_hostname - name: debug rsync_hostname debug: msg: "{{ item }} " loop: - "{{ rsync_hostname.stdout }} " - "{{ rsync_hostname.cmd }} "
服务管理(service) 官方文档:https://docs.ansible.com/ansible/latest/user_guide/playbooks_intro.html?highlight=handlers 使用情景:如果配置文件发生了变化,就重启服务,否则什么都不操作 具体实现:
1 2 3 4 5 6 7 8 9 10 11 12 - hosts: 10.1 .1 .80 tasks: - name: 01 -if nfs conf changed,then restart nfs service copy: src: /playbook/exports dest: /etc/ notify: Restart_nfs handlers: - name: Restart_nfs service: name: nfs state: restarted
官方文档:https://docs.ansible.com/ansible/latest/user_guide/playbooks_tags.html 使用情景:从我们指定的任务开始执行,而不是从头到尾执行一遍
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 - hosts: rsync tasks: - name: "01-add-user" user: name=rsync create_home=no shell=/sbin/nologin uid=2021 tags: 01 -add-user - name: "02-installed-rsync" yum: name=rsync state=installed tags: 02 -install-rsync - name: "03-copy rsync.conf" copy: src=/playbook/rsync/rsyncd.conf dest=/etc/ tags: 03 -copy-rsync.conf - name: "04-create passwd conf" copy: content="rsync_backup:123456" dest=/etc/rsync.passwd mode=0600 tags: 04 -create passwd conf - name: "05-create rsync dir" file: path=/backup state=directory owner=rsync group=rsync tags: 05 -create dir - name: "06-started rsync service" service: name=rsyncd state=started enabled=yes tags: 06 -start rsync
调用标签: 1.打印出playbook里要执行的所有标签
1 ansible-playbook --list-tags tags.yaml
2.指定运行某个标签
1 ansible-playbook -t "04-create passwd conf" tags.yaml
3.指定运行多个标签,使用逗号隔开
1 ansible-playbook -t "04-create passwd conf","06-start rsync" tags.yaml
4.指定不运行某个标签
1 ansible-playbook --skip-tags="04-create passwd conf" tags.yaml
5.指定不运行多个标签
1 ansible-playbook --skip-tags="04-create passwd conf","06-start rsync" tags.yaml
触发器(handlers) 官方文档:https://docs.ansible.com/ansible/latest/user_guide/playbooks_handlers.html
handlers(触发器) : 定义一些task列表,与之前剧本中task没有关系,只有资源发送变化才会采取一定的操作;
**notify(告警器)**:notify中调用handler中定义的操作;
例如: 我们来试试,此处我们使用httpd作为示例,虽然httpd可以使用systemctl restart httpd命令重载配置,但是此处的示例中并不会使用这个命令,而是用httpd类比那些需要重启生效的应用。
假设我们想要将httpd的端口从80改成8088,并且在修改配置以后重启httpd,那么我们可以编写如下剧本。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 --- - hosts: webserver remote_user: root tasks: - name: Modif the configuration lineinfile: path=/etc/httpd/conf/httpd.conf regexp="^Listen 80 " line=" Linsten 8080 " backrefs=yes backup=yes notify: - restart httpd handlers: - name: restart httpd service: name=httpd state=restarted
注意: 无论多少个task通知相同的handlers,handlers仅会在tasks
结束后运行一次。
条件判断(when) 官方文档:https://docs.ansible.com/ansible/latest/user_guide/playbooks_conditionals.html#basic-conditionals-with-when 通常,您希望根据事实执行或跳过任务。事实是单个主机的属性,包括 IP 地址、操作系统、文件系统的状态等等。基于事实的条件:
只有在操作系统是特定版本时,才能安装特定包。 您可以跳过在具有内部 IP 地址的主机上配置防火墙。 只有在文件系统已满时,才能执行清理任务。 实例: 1.只关闭关闭Debian系统
1 2 3 4 tasks: - name: Shut down Debian flavored systems ansible.builtin.command: /sbin/shutdown -t now when: ansible_facts['os_family'] == "Debian"
2.关闭系统为CentOS系统版本为6的
1 2 3 4 5 6 tasks: - name: Shut down CentOS 6 systems ansible.builtin.command: /sbin/shutdown -t now when: - ansible_facts['distribution'] == "CentOS" - ansible_facts['distribution_major_version'] == "6"
回顾运行检查规范与补充 00.检查剧本拼写规范
1 ansible-playbook --syntax-check check.yaml
01.检查这个任务执行的主机对象
1 ansible-playbook --list-host check.yaml
02.检查这个剧本需要执行哪些任务
1 ansible-playbook --list-tasks check.yaml
03.检查这个剧本执行哪些tag
1 ansible-playbook --list-tags check.yaml
04.模拟执行剧本
1 ansible-playbook -C check.yaml
05.针对某台主机执行剧本
1 ansible-playbook --limit 10.1.1.60 check.yaml
template 模板 模板是一个文本文件,可以做为生成文件的模版,并且模板文件中还可嵌套jinja语法
jinja2语言 网站:https://jinja.palletsprojects.com/en/2.11.x/
jinja2 语言使用字面量,有下面形式:
1 2 3 4 5 6 7 8 9 10 字符串:使用单引号或双引号 数字:整数,浮点数 列表:[item1, item2, …] 元组:(item1, item2, …) 字典:{key1:value1, key2:value2, …} 布尔型:true/false 算术运算:+, -, *, /, //, %, ** 比较操作:==, !=, >, >=, <, <= 逻辑运算:and,or,not 流表达式:For,If,When
字面量:
表达式最简单的形式就是字面量。字面量表示诸如字符串和数值的 Python 对象。如“Hello World” 双引号或单引号中间的一切都是字符串。无论何时你需要在模板中使用一个字符串(比如函数调用、过滤器或只是包含或继承一个模板的参数),如42,42.23 数值可以为整数和浮点数。如果有小数点,则为浮点数,否则为整数。在 Python 里, 42 和 42.0 是不一样的
算术运算:
Jinja 允许用计算值。支持下面的运算符
1 2 3 4 5 6 7 +:把两个对象加到一起。通常对象是素质,但是如果两者是字符串或列表,你可以用这 种方式来衔接它们。无论如何这不是首选的连接字符串的方式!连接字符串见 ~ 运算符。 {{ 1 + 1 }} 等于 2 -:用第一个数减去第二个数。 {{ 3 – 2 }} 等于 1 /:对两个数做除法。返回值会是一个浮点数。 {{ 1 / 2 }} 等于 {{ 0.5 }} //:对两个数做除法,返回整数商。 {{ 20 // 7 }} 等于 2 % :计算整数除法的余数。 {{ 11 % 7 }} 等于 4 *:用右边的数乘左边的操作数。 {{ 2* 2 }} 会返回 4 。也可以用于重 复一个字符串多次。 {{ ‘=’ *80 }} 会打印 80 个等号的横条\ **:取左操作数的右操作数次幂。 {{ 2**3 }} 会返回 8
比较操作符
1 2 3 4 5 6 7 == 比较两个对象是否相等 != 比较两个对象是否不等 如果左边大于右边,返回 true = 如果左边大于等于右边,返回 true < 如果左边小于右边,返回 true <= 如果左边小于等于右边,返回 true
逻辑运算符
1 2 3 4 5 6 对于 if 语句,在 for 过滤或 if 表达式中,它可以用于联合多个表达式 and 如果左操作数和右操作数同为真,返回 true or 如果左操作数和右操作数有一个为真,返回 true not 对一个表达式取反 (expr)表达式组 true / false true 永远是 true ,而 false 始终是 false
template template功能:可以根据和参考模块文件,动态生成相类似的配置文件 template文件必须存放于templates目录下,且命名为 .j2 结尾 yaml/yml 文件需和templates目录平级,目录结构如下示例:
1 2 3 4 ./ ├── temnginx.yml └── templates └── nginx.conf.j2
范例:利用template 同步nginx配置文件
1 2 3 4 5 6 7 8 9 10 11 vim temnginx.yml --- - hosts: websrvs remote_user: root tasks: - name: template config to remote hosts template: src=nginx.conf.j2 dest=/etc/nginx/nginx.conf ansible-playbook temnginx.yml
template变更替换 范例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 # 修改文件nginx.conf.j2 mkdir templates vim templates/nginx.conf.j2 worker_processes {{ ansible_processor_vcpus }}; vim temnginx2.yml --- - hosts: websrvs remote_user: root tasks: - name: install nginx yum: name=nginx - name: template config to remote hosts template: src=nginx.conf.j2 dest=/etc/nginx/nginx.conf - name: start service service: name=nginx state=started enable=yes ansible-playbook temnginx2.yml
template算术运算 范例:
1 2 3 vim nginx.conf.j2 worker_processes {{ ansible_processor_vcpus**2 }}; worker_processes {{ ansible_processor_vcpus+2 }};
template中使用流程控制for和if for单一值范例:
1 2 3 4 5 6 vim nginx.conf2.j2 {% for vhost in nginx_vhosts %} server { listen {{ vhost }} } {% endfor %}
for键值对范例:
1 2 3 4 5 6 vim nginx.conf3.j2 {% for vhost in nginx_vhosts %} server { listen {{ vhost.listen }} } {% endfor %}