剧本使Ansible变得比以前更强大。
老实说,如果Ansible除了它的ad-hoc模式之外什么都没有,它仍然是使大量计算机自动化的强大而有用的工具。实际上,如果不是一些功能,我可能会考虑采用即席模式,并将一堆这些即席命令添加到Bash脚本中,并通过学习来完成。但是,这几项附加功能使其值得继续努力。
Ansible竭尽全力使用易于阅读的配置文件来制作“剧本”,这些文件充满了单独的Ansible“任务”。任务基本上是在配置文件中写出的临时命令,它使命令更有条理且易于扩展。配置文件使用YAML,代表“另外一种标记语言”。这是一种易于阅读的标记语言,但它确实依赖于空白,这在大多数配置文件中并不常见。一个简单的剧本看起来像这样:
---- hosts: webservers become: yes tasks: - name: this installs a package apt: name=apache2 update_cache=yes state=latest - name: this restarts the apache service service: name=apache2 enabled=yes state=restarted
内容应该相当容易识别。基本上,这是两个临时命令,分解成一个YAML配置文件。有一些重要的注意事项。首先,每个文件名都以.yaml结尾,并且每个YAML文件都必须以三个连字符开头。同样,如上所述,空格很重要。最后,当连字符应在节之前,以及何时应将其适当地隔开时,经常会造成混淆。基本上,每个新部分都必须以-符号开头,但是通常很难说出应属于自己的部分。但是,随着您创建越来越多的剧本,它开始变得自然。
通过输入以下内容来执行上述剧本:
ansible-playbook filename.yaml
这等效于以下两个命令:
ansible webservers -b -m apt -a "name=apache2 ↪update_cache=yes state=latest"ansible webservers -b -m service -a "name=apache2 ↪enabled=yes state=restarted"
但是,一点点组织实际上只是剧本如此强大的开始。首先,是“处理程序”的概念,即仅在“通知”任务已进行更改时才执行的任务。究竟如何运作?让我们重写上面的YAML文件,使第二个任务成为处理程序:
---- hosts: webservers become: yes tasks: - name: this installs a package apt: name=apache2 update_cache=yes state=latest notify: enable apache handlers: - name: enable apache service: name=apache2 enabled=yes state=started
从表面上看,这看起来与仅执行多个任务非常相似。当执行第一个任务(安装Apache)时,如果进行了更改,它将通知“启用apache”处理程序,该处理程序确保Apache在启动时已启用并且当前正在运行。重要的是,如果已经安装了Apache,并且未进行任何更改,则永远不会调用该处理程序。这使代码更加高效,但也意味着不会不必要地中断已经在运行的Apache进程。
处理程序还存在其他一些节省时间的细微问题,例如,多个任务可以调用一个处理程序,但无论调用多少次,它都只能执行一次。但是要记住的真正重要的事情是,仅当Ansible任务在远程系统上进行更改时,才执行(通知)处理程序。
变量替换在剧本内部非常简单。这是一个简单的例子:
---- hosts: webservers become: yes vars: package_name: apache2 tasks: - name: this installs a package apt: "name={{ package_name }} update_cache=yes state=latest" notify: enable apache handlers: - name: enable apache service: "name={{ package_name }} enabled=yes state=started"
了解上面发生的事情应该相当容易。请注意,我确实将整个模块操作部分都用引号引起来。它并不总是必需的,但是有时Ansible对未引用的变量替换很有趣,因此当涉及到变量时,我总是尝试将其用引号引起来。
但是,关于变量真正有趣的是每个主机的“聚集事实”。您可能会在执行剧本时注意到Ansible所做的第一件事是“收集事实...”,它可以毫无错误地完成,但实际上似乎没有任何作用。真正发生的是,系统信息被填充到可在剧本内部使用的变量中。要查看“事实汇总”的整个列表,可以执行一个临时命令:
ansible webservers -m setup
您将获得从各个主机生成的大量事实。其中一些特别有用。例如,ansible_os_family
根据您使用的发行版, 将返回“ RedHat”或“ Debian”之类的信息。Ubuntu和Debian系统都返回“ Debian”,而Red Hat和CentOS将返回“ RedHat”。尽管这肯定是有趣的信息,但是当不同的发行版使用不同的工具(例如apt vs. yum)时,它确实很有用。
从Ansible临时命令转移到剧本的不便之一是,在剧本模式下,Ansible往往在输出方面保持相对安静。在临时模式下,您通常可以看到发生了什么,但是在剧本中,您仅知道它是否可以正常工作以及是否进行了更改。有两种简单的方法可以改变这种情况。第一种是-v
在执行时添加标志 ansible-playbook
。这增加了冗长性,并在执行操作时提供了大量反馈。不幸的是,它经常提供太多信息,以至于有用性在组合中丢失了。仍然,在紧要关头,仅添加-v
标志会有所帮助。
如果您要创建剧本并希望在此过程中收到任何通知,那么调试模块确实是您的朋友。在即席模式下,调试模块的使用意义不大,但在剧本中,它可以充当发生情况的“报告”工具。例如:
---- hosts: webservers tasks: - name: describe hosts debug: msg="Computer {{ ansible_hostname }} is running ↪{{ ansible_os_family }} or equivalent"
上面的内容将为您显示如图1所示的内容,当您试图弄清所使用的系统种类时,该功能非常有用。调试模块的好处是它可以显示所需的任何内容,因此,如果值发生变化,则可以在屏幕上显示它,以便对无法正常工作的剧本进行故障排除。重要的是要注意,调试模块除了为您在屏幕上显示信息外,不执行其他任何操作。它不是日志系统;相反,这只是在执行过程中显示信息(自定义信息,与详细标志不同)的一种方式。不过,随着您的剧本变得越来越复杂,它可能是无价的。
图1.调试模式是获取有关剧本内部发生情况的一些信息的最佳方法。
条件几乎是每种编程语言的一部分。Ansible YAML文件也可以利用条件执行的优势,但是格式有点古怪。通常情况是先出现条件,然后如果条件为真,则执行以下代码。使用Ansible,这有点落后。任务被完全阐明,然后when
在末尾添加一条语句。它使代码非常易读,但是作为一个在整个职业生涯中一直在使用if / then心态的人,感觉很可笑。这是一个稍微复杂的剧本。查看您是否可以解析在使用Debian / Ubuntu和Red Hat / CentOS系统的环境中会发生的情况:
---- hosts: webservers become: yes tasks: - name: install apache this way apt: name=apache2 update_cache=yes state=latest notify: start apache2 when: ansible_os_family == "Debian" - name: install apache that way yum: name=httpd state=latest notify: start httpd when: ansible_os_family == "RedHat" handlers: - name: start apache2 service: name=apache2 enabled=yes state=started - name: start httpd service: name=httpd enabled=yes state=started
希望YAML格式可以使它相当容易阅读。基本上,这是一部剧本,可根据安装的发行版类型使用yum或apt在主机上安装Apache。然后,处理程序确保新安装的软件包已启用并正在运行。
很容易看出,将收集到的事实和条件语句结合起来会很有用。幸运的是,Ansible并不止于此。与其他配置管理系统一样,它包括编程和脚本语言的大多数功能。例如,有循环。
如果Ansible有一件事情做得很好,那就是循环。坦率地说,它支持许多不同类型的循环,我无法在此处进行介绍。找出适合您情况的最佳循环的最佳方法是直接阅读Ansible文档。
对于简单列表,剧本使用熟悉且易于阅读的方法来执行多个任务。例如:
---- hosts: webservers become: yes tasks: - name: install a bunch of stuff apt: "name={{ item }} state=latest update_cache=yes" with_items: - apache2 - vim - chromium-browser
这个简单的手册将使用apt模块安装多个软件包。请注意,名为的特殊变量item
在本with_items
节中一次被一项替换。同样,这在您自己的剧本中非常容易理解和利用。其他循环以相似的方式工作,但是它们的格式不同。只需查看文档,了解Ansible可以重复执行类似任务的多种方式。
我发现自己经常使用的最后一个模块是模板模块。如果您曾经在文字处理器中使用过邮件合并,则模板的工作原理与此类似。基本上,您创建一个文本文件,然后使用变量替换来动态创建自定义版本。我最经常这样做是为了创建HTML文件或配置文件。Ansible使用Jinja2模板语言,该语言很方便地类似于剧本本身的标准变量替换。我几乎经常使用的示例是一个自定义HTML文件,该文件可以安装在远程批处理的Web服务器上。让我们看一个相当复杂的剧本和一个附带的HTML模板文件。
这是剧本:
---- hosts: webservers become: yes tasks: - name: install apache2 apt: name=apache2 state=latest update_cache=yes when: ansible_os_family == "Debian" - name: install httpd yum: name=httpd state=latest when: ansible_os_family == "RedHat" - name: start apache2 service: name=apache2 state=started enable=yes when: ansible_os_family == "Debian" - name: start httpd service: name=httpd state=started enable=yes when: ansible_os_family == "RedHat - name: install index template: src: index.html.j2 dest: /var/www/html/index.html
这是模板文件,必须以.j2结尾(这是上述最后一个任务中引用的文件):
<html><center><h1>This computer is running {{ ansible_os_family }},and its hostname is:</h1><h3>{{ ansible_hostname }}</h3>{# this is a comment, which won't be copied to the index.html file #}</center></html>
这也应该很容易理解。该剧本采用了一些它学到的东西,并将Apache安装在远程系统上,无论它们是基于Red Hat还是基于Debian的。然后,它启动Web服务器,并确保Web服务器在系统启动时启动。最后,剧本将获取模板文件index.html.j2,并在将文件复制到远程系统时替换变量。注意注释的{# #}
格式。这些注释将在远程系统上完全删除,并且仅在Ansible机器上的.j2文件中可见。
我将在下一篇文章中结束本系列文章,在该文章中,我计划涵盖如何利用您的剧本知识来创建整个角色并利用可用的社区贡献。Ansible是一个非常强大的工具,易于理解和使用。如果您一直在尝试临时命令,则建议您创建剧本,以使您可以轻松地在多台计算机上执行多个任务。至少,请尝试使用ansible-playbook应用收集的“事实”,因为这些是Ansible的临时模式所不具备的。直到下一次,学习,尝试,娱乐并尽情玩乐!
第一部分:Shawn Powers的 “ Ansible:像Sysadmin一样的自动化框架”
第二部分:Shawn Powers的“ Ansible:使事情发生”
评论专区