使用 Ansible 安装 NGINX 和 NGINX Plus
在生产环境中,我会更喜欢做与自动化相关的所有事情。如果计算机能完成你的任务,何必需要你亲自动手呢?但是,在不断变化并存在多种技术的环境中,创建和实施自动化是一项艰巨的任务。这就是为什么我喜欢 Ansible 的原因。Ansible 是一个用于 IT 配置管理,部署和业务流程的开源工具,使用起来非常方便。
我最喜欢 Ansible 的一个特点是,它是完全无客户端的。要管理一个系统,通过 SSH 建立连接,它使用Paramiko(一个 Python 库)或本地的 OpenSSH。Ansible 另一个吸引人的地方是它有许多可扩展的模块。这些模块可被系统管理员用于执行一些的常见任务。特别是,它们使用 Ansible 这个强有力的工具可以跨多个服务器、环境或操作系统安装和配置任何程序,只需要一个控制节点。
在本教程中,我将带你使用 Ansible 完成安装和部署开源 NGINX 和我们的商业产品 NGINX Plus。我将在 CentOS 服务器上演示,但我也在下面的“在 Ubuntu 上创建 Ansible Playbook 来安装 NGINX 和 NGINX Plus”小节中包含了在 Ubuntu 服务器上部署的细节。
在本教程中我将使用 Ansible 1.9.2 版本,并在 CentOS 7.1 服务器上部署运行。
<span class="pln">$ ansible </span><span class="pun">--</span><span class="pln">version</span>
<span class="pln">ansible </span><span class="lit">1.9</span><span class="pun">.</span><span class="lit">2</span>
<span class="pln">$ </span><span class="kwd">cat</span><span class="pun">/</span><span class="pln">etc</span><span class="pun">/</span><span class="pln">RedHat</span><span class="pun">-</span><span class="pln">release</span>
<span class="typ">CentOS</span><span class="typ">Linux</span><span class="pln"> release </span><span class="lit">7.1</span><span class="pun">.</span><span class="lit">1503</span><span class="pun">(</span><span class="typ">Core</span><span class="pun">)</span>
如果你还没有 Ansible,可以在 Ansible 网站 查看说明并安装它。
如果你使用的是 CentOS,安装 Ansible 十分简单,只要输入以下命令。如果你想使用源码编译安装或使用其他发行版,请参阅上面 Ansible 链接中的说明。
<span class="pln">$ </span><span class="kwd">sudo</span><span class="kwd">yum</span><span class="pln"> install </span><span class="pun">-</span><span class="pln">y epel</span><span class="pun">-</span><span class="pln">release </span><span class="pun">&&</span><span class="kwd">sudo</span><span class="kwd">yum</span><span class="pln"> install </span><span class="pun">-</span><span class="pln">y ansible</span>
根据环境的不同,在本教程中的命令有的可能需要 sudo 权限。文件路径,用户名和目标服务器取决于你的环境的情况。
创建一个 Ansible Playbook 来安装 NGINX (CentOS)
首先,我们要为 NGINX 的部署创建一个工作目录,包括子目录和部署配置文件。我通常建议在你的主目录中创建该目录,在文章的所有例子中都会有说明。
<span class="pln">$ </span><span class="kwd">cd</span><span class="pln"> $HOME</span>
<span class="pln">$ </span><span class="kwd">mkdir</span><span class="pun">-</span><span class="pln">p ansible</span><span class="pun">-</span><span class="pln">nginx</span><span class="pun">/</span><span class="pln">tasks</span><span class="pun">/</span>
<span class="pln">$ </span><span class="kwd">touch</span><span class="pln"> ansible</span><span class="pun">-</span><span class="pln">nginx</span><span class="pun">/</span><span class="pln">deploy</span><span class="pun">.</span><span class="pln">yml</span>
<span class="pln">$ </span><span class="kwd">touch</span><span class="pln"> ansible</span><span class="pun">-</span><span class="pln">nginx</span><span class="pun">/</span><span class="pln">tasks</span><span class="pun">/</span><span class="pln">install_nginx</span><span class="pun">.</span><span class="pln">yml</span>
目录结构看起来是这样的。你可以使用 tree 命令来查看。
<span class="pln">$ tree $HOME</span><span class="pun">/</span><span class="pln">ansible</span><span class="pun">-</span><span class="pln">nginx</span><span class="pun">/</span>
<span class="str">/home/</span><span class="pln">kjones</span><span class="pun">/</span><span class="pln">ansible</span><span class="pun">-</span><span class="pln">nginx</span><span class="pun">/</span>
<span class="pun">├──</span><span class="pln"> deploy</span><span class="pun">.</span><span class="pln">yml</span>
<span class="pun">└──</span><span class="pln"> tasks</span>
<span class="pun">└──</span><span class="pln"> install_nginx</span><span class="pun">.</span><span class="pln">yml</span>
<span class="lit">1</span><span class="pln"> directory</span><span class="pun">,</span><span class="lit">2</span><span class="pln"> files</span>
如果你没有安装 tree 命令,使用以下命令去安装。
<span class="pln">$ </span><span class="kwd">sudo</span><span class="kwd">yum</span><span class="pln"> install </span><span class="pun">-</span><span class="pln">y tree</span>
创建主部署文件
接下来,我们在文本编辑器中打开 deploy.yml。我喜欢在命令行上使用 vim 来编辑配置文件,在整个教程中也都将使用它。
<span class="pln">$ </span><span class="kwd">vim</span><span class="pln"> $HOME</span><span class="pun">/</span><span class="pln">ansible</span><span class="pun">-</span><span class="pln">nginx</span><span class="pun">/</span><span class="pln">deploy</span><span class="pun">.</span><span class="pln">yml</span>
deploy.yml 文件是 Ansible 部署的主要文件,在“使用 Ansible 部署 NGINX”小节中,我们运行 ansible‑playbook 命令时会使用此文件。在这个文件中,我们指定 Ansible 运行时使用的库以及其它配置文件。
在这个例子中,我使用 include 模块来指定配置文件一步一步来安装NGINX。虽然可以创建一个非常大的 playbook 文件,我建议你将其分割为小文件,让它们更有条理。include 的示例中可以复制静态内容,复制配置文件,为更高级的部署使用逻辑配置设定变量。
在文件中输入以下行。我在顶部的注释包含了文件名用于参考。
<span class="com">#</span><span class="pun">./</span><span class="pln">ansible</span><span class="pun">-</span><span class="pln">nginx</span><span class="pun">/</span><span class="pln">deploy</span><span class="pun">.</span><span class="pln">yml</span>
<span class="pun">-</span><span class="pln"> hosts</span><span class="pun">:</span><span class="pln"> nginx</span>
<span class="pln">tasks</span><span class="pun">:</span>
<span class="pun">-</span><span class="kwd">include</span><span class="pun">:</span><span class="str">'tasks/install_nginx.yml'</span>
hosts 语句说明 Ansible 部署 nginx 组的所有服务器,服务器在 /etc/ansible/hosts 中指定。我们会在下面的“创建 NGINX 服务器列表”小节编辑此文件。
include 语句说明 Ansible 在部署过程中从 tasks 目录下读取并执行 install_nginx.yml 文件中的内容。该文件包括以下几步:下载,安装,并启动 NGINX。我们将在下一节创建此文件。
为 NGINX 创建部署文件
现在,先保存 deploy.yml 文件,并在编辑器中打开 install_nginx.yml 。
<span class="pln">$ </span><span class="kwd">vim</span><span class="pln"> $HOME</span><span class="pun">/</span><span class="pln">ansible</span><span class="pun">-</span><span class="pln">nginx</span><span class="pun">/</span><span class="pln">tasks</span><span class="pun">/</span><span class="pln">install_nginx</span><span class="pun">.</span><span class="pln">yml</span>
该文件包含有指令(使用 YAML 格式写的), Ansible 会按照指令安装和配置我们的 NGINX 部署过程。每个节(过程中的步骤)起始于一个描述此步骤的 name
语句(前面有连字符)。 name
后的字符串是 Ansible 部署过程中输出到标准输出的,可以根据你的意愿来修改。YAML 文件中的节的下一行是在部署过程中将使用的模块。在下面的配置中,���用了 yum
和 service
模块。yum
模块用于在 CentOS 上安装软件包。service
模块用于管理 UNIX 的服务。在这个节的最后一行或几行指定了几个模块的参数(在本例中,这些行以 name
和 state
开始)。
在文件中输入以下行。就像 deploy.yml,在我们文件的第一行是用于参考的文件名的注释。第一个节告诉 Ansible 在CentOS 7 上从 NGINX 仓库安装该 .rpm 文件。这让软件包管理器直接从 NGINX 仓库安装最新最稳定的版本。根据你的 CentOS 版本修改路径。所有可用的包的列表可以在 开源 NGINX 网站 上找到。接下来的两节告诉 Ansible 使用 yum
模块安装最新的 NGINX 版本,然后使用 service
模块启动 NGINX。
注意: 在第一个节中,CentOS 包中的路径名可能由于宽度显示为连着的两行。请在一行上输入其完整路径。
<span class="com">#</span><span class="pun">./</span><span class="pln">ansible</span><span class="pun">-</span><span class="pln">nginx</span><span class="pun">/</span><span class="pln">tasks</span><span class="pun">/</span><span class="pln">install_nginx</span><span class="pun">.</span><span class="pln">yml</span>
<span class="pun">-</span><span class="pln"> name</span><span class="pun">:</span><span class="pln"> NGINX </span><span class="pun">|</span><span class="typ">Installing</span><span class="pln"> NGINX repo rpm</span>
<span class="kwd">yum</span><span class="pun">:</span>
<span class="pln">name</span><span class="pun">:</span><span class="pln"> http</span><span class="pun">:</span><span class="com">//nginx.org/packages/centos/7/noarch/RPMS/nginx-release-centos-7-0.el7.ngx.noarch.rpm</span>
<span class="pun">-</span><span class="pln"> name</span><span class="pun">:</span><span class="pln"> NGINX </span><span class="pun">|</span><span class="typ">Installing</span><span class="pln"> NGINX</span>
<span class="kwd">yum</span><span class="pun">:</span>
<span class="pln">name</span><span class="pun">:</span><span class="pln"> nginx</span>
<span class="pln">state</span><span class="pun">:</span><span class="pln"> latest</span>
<span class="pun">-</span><span class="pln"> name</span><span class="pun">:</span><span class="pln"> NGINX </span><span class="pun">|</span><span class="typ">Starting</span><span class="pln"> NGINX</span>
<span class="pln">service</span><span class="pun">:</span>
<span class="pln">name</span><span class="pun">:</span><span class="pln"> nginx</span>
<span class="pln">state</span><span class="pun">:</span><span class="pln"> started</span>
创建 NGINX 服务器列表
现在,我们设置好了 Ansible 部署的所有配置文件,我们需要告诉 Ansible 部署哪个服务器。我们需要在 Ansible 中指定 hosts 文件。先备份现有的文件,并新建一个新文件来部署。
<span class="pln">$ </span><span class="kwd">sudo</span><span class="kwd">mv</span><span class="pun">/</span><span class="pln">etc</span><span class="pun">/</span><span class="pln">ansible</span><span class="pun">/</span><span class="pln">hosts </span><span class="pun">/</span><span class="pln">etc</span><span class="pun">/</span><span class="pln">ansible</span><span class="pun">/</span><span class="pln">hosts</span><span class="pun">.</span><span class="pln">backup</span>
<span class="pln">$ </span><span class="kwd">sudo</span><span class="kwd">vim</span><span class="pun">/</span><span class="pln">etc</span><span class="pun">/</span><span class="pln">ansible</span><span class="pun">/</span><span class="pln">hosts</span>
在文件中输入(或编辑)以下行来创建一个名为 nginx 的组并列出安装 NGINX 的服务器。你可以通过主机名、IP 地址、或者在一个范围,例如 server[1-3].domain.com 来指定服务器。在这里,我通过 IP 地址指定一台服务器。
<span class="com"># /etc/</span><span class="pln">ansible</span><span class="pun">/</span><span class="pln">hosts</span>
<span class="pun">[</span><span class="pln">nginx</span><span class="pun">]</span>
<span class="lit">172.16</span><span class="pun">.</span><span class="lit">239.140</span>
设置安全性
接近完成了,但在部署之前,我们需要确保 Ansible 已被授权通过 SSH 访问我们的目标服务器。
首选并且最安全的方法是添加 Ansible 所要部署服务器的 RSA SSH 密钥到目标服务器的 authorized_keys 文件中,这给予 Ansible 在目标服务器上的不受限制 SSH 权限。要了解更多关于此配置,请参阅 wiki.centos.org 上 安全加固 OpenSSH。这样,你就可以自动部署而无需用户交互。
另外,你也可以在部署过程中要求输入密码。我强烈建议你只在测试过程中使用这种方法,因为它是不安全的,没有办法跟踪目标主机的身份(fingerprint)变化。如果你想这样做,将每个目标主机 /etc/ssh/ssh_config 文件中 StrictHostKeyChecking 的默认值 yes 改为 no。然后在 ansible-playbook 命令中添加 --ask-pass 参数来让 Ansible 提示输入 SSH 密码。
在这里,我将举例说明如何编辑 ssh_config 文件来禁用在目标服务器上严格的主机密钥检查。我们手动连接 SSH 到我们将部署 NGINX 的服务器,并将 StrictHostKeyChecking 的值更改为 no。
<span class="pln">$ </span><span class="kwd">ssh</span><span class="pln"> kjones@172</span><span class="pun">.</span><span class="lit">16.239</span><span class="pun">.</span><span class="lit">140</span>
<span class="pln">kjones@172</span><span class="pun">.</span><span class="lit">16.239</span><span class="pun">.</span><span class="lit">140</span><span class="str">'s password:***********</span>
<span class="str">[kjones@nginx ]$ sudo vim /etc/ssh/ssh_config</span>
当你更改后,保存 ssh_config,并通过 SSH 连接到你的 Ansible 服务器。保存后的设置应该如下所示。
<span class="com"># /etc/</span><span class="kwd">ssh</span><span class="pun">/</span><span class="pln">ssh_config</span>
<span class="typ">StrictHostKeyChecking</span><span class="kwd">no</span>
运行 Ansible 部署 NGINX
如果你一直照本教程的步骤来做,你可以运行下面的命令来使用 Ansible 部署 NGINX。(再次提示,如果你设置了 RSA SSH 密钥认证,那么 --ask-pass 参数是不需要的。)在 Ansible 服务器运行命令,并使用我们上面创建的配置文件。
<span class="pln">$ </span><span class="kwd">sudo</span><span class="pln"> ansible</span><span class="pun">-</span><span class="pln">playbook </span><span class="pun">--</span><span class="pln">ask</span><span class="pun">-</span><span class="kwd">pass</span><span class="pln"> $HOME</span><span class="pun">/</span><span class="pln">ansible</span><span class="pun">-</span><span class="pln">nginx</span><span class="pun">/</span><span class="pln">deploy</span><span class="pun">.</span><span class="pln">yml</span>
Ansible 提示输入 SSH 密码,输出如下。recap 中显示 failed=0 这条信息,意味着部署成功了。
<span class="pln">$ </span><span class="kwd">sudo</span><span class="pln"> ansible</span><span class="pun">-</span><span class="pln">playbook </span><span class="pun">--</span><span class="pln">ask</span><span class="pun">-</span><span class="kwd">pass</span><span class="pln"> $HOME</span><span class="pun">/</span><span class="pln">ansible</span><span class="pun">-</span><span class="pln">nginx</span><span class="pun">/</span><span class="pln">deploy</span><span class="pun">.</span><span class="pln">yml</span>
<span class="pln">SSH password</span><span class="pun">:</span>
<span class="pln">PLAY </span><span class="pun">[</span><span class="pln">all</span><span class="pun">]</span><span class="pun">********************************************************************</span>
<span class="pln">GATHERING FACTS </span><span class="pun">***************************************************************</span>
<span class="pln">ok</span><span class="pun">:</span><span class="pun">[</span><span class="lit">172.16</span><span class="pun">.</span><span class="lit">239.140</span><span class="pun">]</span>
<span class="pln">TASK</span><span class="pun">:</span><span class="pun">[</span><span class="pln">NGINX </span><span class="pun">|</span><span class="typ">Installing</span><span class="pln"> NGINX repo rpm</span><span class="pun">]</span><span class="pun">*************************************</span>
<span class="pln">changed</span><span class="pun">:</span><span class="pun">[</span><span class="lit">172.16</span><span class="pun">.</span><span class="lit">239.140</span><span class="pun">]</span>
<span class="pln">TASK</span><span class="pun">:</span><span class="pun">[</span><span class="pln">NGINX </span><span class="pun">|</span><span class="typ">Installing</span><span class="pln"> NGINX</span><span class="pun">]</span><span class="pun">**********************************************</span>
<span class="pln">changed</span><span class="pun">:</span><span class="pun">[</span><span class="lit">172.16</span><span class="pun">.</span><span class="lit">239.140</span><span class="pun">]</span>
<span class="pln">TASK</span><span class="pun">:</span><span class="pun">[</span><span class="pln">NGINX </span><span class="pun">|</span><span class="typ">Starting</span><span class="pln"> NGINX</span><span class="pun">]</span><span class="pun">************************************************</span>
<span class="pln">changed</span><span class="pun">:</span><span class="pun">[</span><span class="lit">172.16</span><span class="pun">.</span><span class="lit">239.140</span><span class="pun">]</span>
<span class="pln">PLAY RECAP </span><span class="pun">********************************************************************</span>
<span class="lit">172.16</span><span class="pun">.</span><span class="lit">239.140</span><span class="pun">:</span><span class="pln"> ok</span><span class="pun">=</span><span class="lit">4</span><span class="pln"> changed</span><span class="pun">=</span><span class="lit">3</span><span class="pln"> unreachable</span><span class="pun">=</span><span class="lit">0</span><span class="pln"> failed</span><span class="pun">=</span><span class="lit">0</span>
如果你没有得到一个成功的 play recap,你可以尝试用 -vvvv 参数(带连接调试的详细信息)再次运行 ansible-playbook 命令来解决部署过程的问题。
当部署成功(假如我们是第一次部署)后,你可以在远程服务器上运行基本的 cURL 命令验证 NGINX 。在这里,它会返回 200 OK。Yes!我们使用 Ansible 成功安装了 NGINX。
<span class="pln">$ curl </span><span class="pun">-</span><span class="typ">Is</span><span class="lit">172.16</span><span class="pun">.</span><span class="lit">239.140</span><span class="pun">|</span><span class="kwd">grep</span><span class="pln"> HTTP</span>
<span class="pln">HTTP</span><span class="pun">/</span><span class="lit">1.1</span><span class="lit">200</span><span class="pln"> OK</span>