编写 Ansible Playbooks

03-06 1182阅读

简介

简而言之,服务器配置管理(也被广泛称为 IT 自动化)是将基础设施管理转化为代码库的解决方案,描述了部署服务器所需的所有流程,并将其转化为一组可以进行版本控制和轻松重复使用的配置脚本。它可以极大地提高任何服务器基础设施的完整性。

编写 Ansible Playbooks
(图片来源网络,侵删)

在之前的指南中,我们讨论了实施配置管理策略对服务器基础设施的主要好处,配置管理工具的工作原理以及这些工具通常具有的共同点。

本系列的这一部分将带领您通过使用 Ansible 自动化服务器配置的过程,Ansible 是一种提供完整自动化框架和编排能力的配置管理工具,同时保持了极致简单和极简的目标。我们将重点关注用于创建一个简化示例以完全自动化部署 Ubuntu 18.04 上的 Apache 的语言术语、语法和功能。

以下列表包含了我们需要自动化的所有步骤,以实现我们的目标:

  1. 更新 apt 缓存
  2. 安装 Apache
  3. 创建自定义文档根目录
  4. 在自定义文档根目录中放置一个 index.html 文件
  5. 应用模板以设置我们的自定义虚拟主机
  6. 重启 Apache

我们将首先查看 Ansible 使用的术语,然后概述可以用于编写 playbook 的主要语言特性。在指南结束时,您将找到一个完整的配置示例,用于自动化在 Ubuntu 18.04 上设置 Apache 的步骤的描述内容。

入门

在我们可以更深入地了解 Ansible 之前,重要的是我们要熟悉这个工具引入的重要术语和概念。

术语

以下列表包含了 Ansible 使用的最相关术语的快速概述:

  • 控制节点:安装了 Ansible 的机器,负责在您管理的服务器上运行配置。
  • 清单:包含有关您正在管理的服务器的信息的 INI 文件。
  • Playbook:包含一系列应该自动化的程序的 YAML 文件。
  • 任务:定义要执行的单个过程的块,例如:安装一个软件包。
  • 模块:模块通常抽象出系统任务,如处理软件包或创建和更改文件。Ansible 有多种内置模块,但您也可以创建自定义模块。
  • 角色:一组相关的 playbooks、模板和其他文件,以预定义的方式组织,以便促进重用和共享。
  • Play:从头到尾执行的配置称为 play
  • 事实:包含有关系统的信息的全局变量,如网络接口或操作系统。
  • 处理程序:用于触发服务状态更改,如重新启动或重新加载服务。

    任务格式

    任务定义了应该由 Ansible 执行的单个自动化步骤。它通常涉及使用模块或执行原始命令。以下是一个任务的样子:

    - name: 这是一个任务
      apt: name=vim state=latest
    

    name 部分实际上是可选的,但建议使用,因为在执行任务时会显示在配置的输出中。apt 部分是一个内置的 Ansible 模块,它抽象了基于 Debian 的发行版上的软件包管理。这个示例任务告诉 Ansible 要将软件包 vim 的状态更改为 latest,这将导致软件包管理器在尚未安装时安装此软件包。

    Playbook 格式

    Playbooks 是包含一系列指令以自动化服务器配置的 YAML 文件。以下示例是一个简单的 playbook,执行两个任务:更新 apt 缓存,然后安装 vim:

    ---
    - hosts: all
      become: true
      tasks:
         - name: 更新 apt 缓存 
           apt: update_cache=yes
         - name: 安装 Vim
           apt: name=vim state=latest
    

    YAML 依赖缩进来序列化数据结构。因此,在编写 playbooks 时,尤其是在复制示例时,您需要特别小心地保持正确的缩进。

    在本指南结束之前,我们将看到一个更真实的 playbook 示例,并对其进行详细解释。下一节将为您介绍可以用于编写 Ansible playbook 的最重要元素和功能的概述。

    编写 Playbooks

    现在您已经熟悉了 Ansible 的基本术语和 playbook 中的任务的格式,我们将学习一些 playbook 功能,这些功能可以帮助我们创建更多功能的自动化。

    使用变量

    在 Ansible 中,有多种定义变量的方式。最简单的方法是使用 playbook 的 vars 部分。下面的示例定义了一个名为 package 的变量,稍后在一个任务中使用:

    ---
    - hosts: all
      become: true
      vars:
         package: vim
      tasks:
         - name: 安装软件包
           apt: name={{ package }} state=latest
    

    package 变量具有全局作用域,这意味着它可以从配置的任何地方访问,甚至可以从包含的文件和模板中访问。

    使用循环

    循环通常用于使用不同的输入值重复执行任务。例如,您可以创建一个单一任务,并使用循环来重复执行该任务,以安装您想要安装的所有不同软件包,而不是为安装10个不同软件包创建10个任务。

    要在任务中创建循环,请在数组值中包含选项 with_items。内容可以通过循环变量 item 进行访问,如下例所示:

    - name: 安装软件包
      apt: name={{ item }} state=latest
      with_items:
         - vim
         - git
         - curl  
    

    您还可以使用数组变量来定义您的项目:

    ---
    - hosts: all
      become: true
      vars:
         packages: [ 'vim', 'git', 'curl' ]
      tasks:
         - name: 安装软件包
           apt: name={{ item }} state=latest
           with_items: "{{ packages }}"
    

    使用条件语句

    条件语句可用于根据变量或命令输出动态决定是否执行任务。

    以下示例仅会关闭基于 Debian 的系统:

    - name: 关闭基于 Debian 的系统
      command: /sbin/shutdown -t now
      when: ansible_os_family == "Debian"
    

    条件语句 when 接收一个要评估的表达式作为参数。只有在表达式评估为 true 时,任务才会执行。在我们的示例中,我们测试了一个事实,以检查操作系统是否来自 Debian 家族。

    在 IT 自动化中,条件语句的常见用例是任务的执行取决于命令的输出。使用 Ansible,我们实现这一点的方式是注册一个变量来保存命令执行的结果,然后在随后的任务中测试这个变量。我们可以测试命令的退出状态(成功或失败)。我们还可以检查输出中的特定内容,尽管这可能需要使用正则表达式和字符串解析命令。

    下面的示例展示了基于 php -v 命令输出的两个条件任务。我们将测试命令的退出状态,因为我们知道如果此服务器上未安装 PHP,则命令将无法执行。任务中的 ignore_errors 部分很重要,以确保在命令执行失败时继续进行配置。

    - name: 检查 PHP 是否已安装
      register: php_installed
      command: php -v
      ignore_errors: true
    - name: 仅当 PHP 已安装时执行此任务
      debug: var=php_install
      when: php_installed|success
      
    - name: 仅当 PHP 未安装时执行此任务
      debug: msg='PHP 未安装'
      when: php_installed|failed
    

    此处使用的 debug 模块是一个用于显示变量内容或调试消息的有用模块。它可以打印字符串(使用 msg 参数)或打印变量的内容(使用 var 参数)。

    使用模板

    模板通常用于设置配置文件,允许使用变量和其他旨在使这些文件更加灵活和可重用的功能。Ansible 使用 Jinja2 模板引擎。

    以下示例是一个用于设置 Apache 虚拟主机的模板,使用变量设置此主机的文档根目录:

        ServerAdmin webmaster@localhost
        DocumentRoot {{ doc_root }}
        { doc_root }}
            AllowOverride All
            Require all granted
        
    
    

    内置模块 template 用于从任务中应用模板。如果您将上述模板文件命名为 vhost.tpl,并将其放在与您的 playbook 相同的目录中,这是您将模板应用于替换默认 Apache 虚拟主机的方式:

    - name: 更改默认 Apache 虚拟主机
      template: 
        src: vhost.tpl
        dest: /etc/apache2/sites-available/000-default.conf
    

    定义和触发处理程序

    处理程序用于触发服务的状态更改,例如 重启停止。尽管它们看起来与常规任务非常相似,但处理程序仅在先前从任务的 notify 指令触发时执行。它们通常被定义为 playbook 的 handlers 部分中的数组,但也可以存在于单独的文件中。

    让我们考虑我们之前使用模板的示例,我们设置了一个 Apache 虚拟主机。如果您想要确保在虚拟主机更改后重新启动 Apache,您首先需要为 Apache 服务创建一个处理程序。这是如何在 playbook 中定义处理程序的方式:

    handlers:
        - name: 重启 apache
          service: name=apache2 state=restarted
        
        - name: 其他处理程序
          service: name=other state=restarted
    

    这里的 name 指令很重要,因为它将是此处理程序的唯一标识符。要从任务中触发此处理程序,您应该使用 notify 选项:

    - name: 更改默认 Apache 虚拟主机
      template: 
        src: vhost.tpl
        dest: /etc/apache2/sites-available/000-default.conf
      notify: 重启 apache
    

    我们已经看到了一些您可以用来开始编写 Ansible playbook 的最重要功能。在下一节中,我们将深入探讨一个更真实的 playbook 示例,该 playbook 将自动安装和配置 Ubuntu 上的 Apache。

    示例 Playbook

    现在让我们来看一个 Playbook,它将自动化安装 Apache web 服务器在 Ubuntu 18.04 系统中,正如本指南介绍中所讨论的那样。

    完整的示例,包括用于设置 Apache 和由 web 服务器提供的 HTML 文件的模板文件,可以在 Github 上找到。该文件夹还包含一个 Vagrantfile,让您可以使用由 Vagrant 管理的虚拟机在简化的设置中测试 Playbook。

    Playbook 内容

    以下是 Playbook 的完整内容,供您参考:

    ---
    - hosts: all
      become: true
      vars:
        doc_root: /var/www/example
      tasks:
        - name: Update apt
          apt: update_cache=yes
        - name: Install Apache
          apt: name=apache2 state=latest
        - name: Create custom document root
          file: path={{ doc_root }} state=directory owner=www-data group=www-data
        - name: Set up HTML file
          copy: src=index.html dest={{ doc_root }}/index.html owner=www-data group=www-data mode=0644
        - name: Set up Apache virtual host file
          template: src=vhost.tpl dest=/etc/apache2/sites-available/000-default.conf
          notify: restart apache
      handlers:
        - name: restart apache
          service: name=apache2 state=restarted
    

    让我们更详细地检查这个 Playbook 的每个部分:

    hosts: all

    Playbook 开始时指定应该应用于清单中的所有主机(hosts: all)。也可以将 Playbook 的执行限制为特定主机或主机组。这个选项可以在执行时被覆盖。

    become: true

    become: true 部分告诉 Ansible 在执行此 Playbook 中的所有任务时使用特权升级(sudo)。这个选项可以在任务级别上被覆盖。

    vars

    定义一个变量 doc_root,稍后在任务中使用。这个部分可以包含多个变量。

    tasks

    定义实际任务的部分。第一个任务更新 apt 缓存,第二个任务安装 apache2 软件包。

    第三个任务使用内置模块 file 创建一个目录作为我们的文档根目录。这个模块可以用来管理文件和目录。

    第四个任务使用模块 copy 将本地文件复制到远程服务器。我们正在复制一个简单的 HTML 文件,作为由 Apache 托管的网站。

    handlers

    最后,我们有 handlers 部分,声明了服务。我们定义了 restart apache 处理程序,它在第四个任务中被通知,那里应用了 Apache 模板。

    运行 Playbook

    一旦您将此 Playbook 的内容下载到您的 Ansible 控制节点,您可以使用 ansible-playbook 在清单中的一个或多个节点上执行它。以下命令将在默认清单文件中的所有主机上执行 Playbook,使用 SSH 密钥对身份验证连接为当前系统用户:

    ansible-playbook playbook.yml
    

    您还可以使用 -l 限制执行到清单中的单个主机或主机组:

    ansible-playbook -l host_or_group playbook.yml
    

    如果您需要指定不同的 SSH 用户连接到远程服务器,您可以在该命令中包含参数 -u user:

    ansible-playbook -l host_or_group playbook.yml -u remote-user
    

    有关如何运行 Ansible 命令和 Playbook 的更多信息,请参考我们的指南《在 Ubuntu 18.04 上安装和配置 Ansible》。

    结论

    Ansible 是一个极简的 IT 自动化工具,学习曲线低,使用 YAML 编写其配置脚本。它有大量内置模块,可用于抽象任务,如安装软件包和处理模板。它简化的基础设施要求和简单的语言对于刚开始使用配置管理的人来说可能是一个很好的选择。然而,它可能缺乏一些您可以在更复杂的工具如 Puppet 和 Chef 中找到的高级功能。

    在本系列的下一部分中,我们将看到 Puppet 的实际概述,Puppet 是一个流行且成熟的配置管理工具,它使用基于 Ruby 的表达性和强大的自定义 DSL 来编写配置脚本。

VPS购买请点击我

文章版权声明:除非注明,否则均为主机测评原创文章,转载或复制请以超链接形式并注明出处。

目录[+]