如何在 Ubuntu 16.04 上利用 Ansible 2.0 使用 DigitalOcean API v2

金钱(警告)

** 状态:** 被贬值

此文章已被删除,不再保留。

理由

本文依赖于一个项目, dopy,不再维护。

相反,看

本文可能仍然有用作为参考,但可能无法工作或遵循最佳实践. 我们强烈建议使用最近为您正在使用的操作系统撰写的一篇文章。

介绍

Ansible 2.0 支持 DigitalOcean API 版本 2,这意味着您可以使用 Ansible 不仅提供您的 Web 应用程序,还可以自动提供和管理您的 Droplets。

虽然DigitalOcean为设置SSH密钥和创建Droplets提供了一个简单的Web界面,但它是一个手动过程,您需要每次想要提供一个新的服务器时进行。

使用 Ansible 等配置工具的好处在于它允许您完全自动化此过程,并且启动它就像运行单个命令一样简单。

特别是,本教程将涵盖在 DO 帐户上设置一个新的 SSH 密钥的过程,并提供两个不同的 Droplets,以便它们准备好用于部署您的 Web 应用程序。

前提条件

本教程建立在基本的Ansible知识的基础上,所以如果你是Ansible的新人,你可以先阅读Ansible安装教程的本节(https://andsky.com/tech/tutorials/how-to-install-and-configure-ansible-on-ubuntu-16-04#how-does-ansible-work)。

要遵循本教程,您将需要:

步骤 1 – 配置 Ansible

在此步骤中,我们将配置 Ansible 以与 DigitalOcean API 进行通信。

通常,Ansible只使用SSH连接到不同的服务器并运行命令,这意味着使用Ansible开始所需的配置通常是所有模块的标准。然而,由于与DigitalOcean API通信不仅仅是SSH壳命令,我们需要做一些额外的设置。

要安装dopy,先安装Python包管理器pip

1sudo apt-get install python-pip

然后,使用pip安装dopy

1sudo pip install dopy

接下来,我们将创建一个新的目录,以保持事物干净,我们将设置一个基本的 Ansible 配置文件。

默认情况下,Ansible使用位于/etc/ansible/hosts的主机文件,其中包含它管理的所有服务器. 虽然该文件对某些用例是好的,但它是全球性的。 这是一个全球性的配置,在某些用例中是好的,但我们将在本教程中使用本地主机文件。

创建并移动到一个新的目录,我们将用于本教程的其余部分。

1mkdir ~/ansible-do-api
2cd ~/ansible-do-api/

當您執行 Ansible 時,它會在執行目錄中尋找一個「ansible.cfg」檔案,如果找到一個,它會適用這些配置設定,這意味著我們可以很容易地為每個個別使用情況取代選項,例如「hostfile」選項。

创建一个名为ansible.cfg的新文件,并使用nano或您最喜欢的文本编辑器打开它进行编辑。

1nano ansible.cfg

将下列内容粘贴到ansible.cfg,然后保存并关闭文件。

1[label Updated ansible.cfg]
2[defaults]
3hostfile = hosts

[默认]组中设置hostfile选项会告诉 Ansible使用特定的主机文件,而不是全球文件。

接下来,我们将创建主机文件。

1nano hosts

由于我们将在本教程中只处理DigitalOcean API,我们可以告诉Ansible在localhost上运行,这使事情变得简单,并将消除连接到远程主机的需要。

1[label Updated hosts file]
2[digitalocean]
3localhost ansible_connection=local

最后,我们将使用在前提条件下创建的API代币来允许Ansible与DigitalOcean API进行通信,有三种方式可以告诉Ansible有关API代币:

  1. 直接在每个 DigitalOcean 任务上提供它,使用「api_token」参数
  2. 将其定义为播放簿或主机文件中的变量,并将该变量用于「api_token」参数
  3. 将其导出为环境变量,作为「DO_API_TOKEN」或「DO_API_KEY」。

选项 1 是最直接的方法,如果您不想创建变量,可能听起来很有吸引力,但这意味着 API 标记必须被复制到所使用的每个任务中。

选项2允许我们直接在我们的播放簿中设置API代币,如选项1不同于选项1,我们只通过使用变量在一个地方定义它,这更方便,更容易更新。

然而,选择3是保护 API 代币的最佳方法,因为它使您更难意外将 API 代币委托到一个存储库(可以与任何人共享)。

创建一个名为digitalocean.yml的基本播放簿。

1nano digitalocean.yml

将以下代码粘贴到文件中,确保在您的 API 代码中取代。

1[label Updated digitalocean.yml]
2---
3- hosts: digitalocean
4
5  vars:
6    do_token: your_API_token
7
8  tasks:

您可以在您的编辑器中打开此文件,我们将在下一步继续使用它。

第2步:设置一个SSH密钥

在此步骤中,我们将在您的服务器上创建一个新的 SSH 密钥,并使用 Ansible 将其添加到您的 DigitalOcean 帐户中。

我们需要做的第一件事是确保用户有一个SSH密钥对,我们可以将其推到DigitalOcean,以便在您的新Droplets上默认安装。尽管通过命令行很容易做到这一点,但我们可以在Ansible中使用用户(http://docs.ansible.com/ansible/user_module.html)模块轻松做到这一点。使用Ansible也有确保密钥在使用之前存在的优点,这可以避免在不同主机上运行播放簿时的问题。

在您的播放簿中,添加下面的用户任务,我们可以使用它来确保SSH密钥存在,然后保存并关闭文件。

 1[label Updated digitalocean.yml]
 2---
 3- hosts: digitalocean
 4
 5  vars:
 6    do_token: your_API_token
 7
 8  tasks:
 9
10  - name: ensure ssh key exists
11    user: >
12      name={{ ansible_user_id }}
13      generate_ssh_key=yes
14      ssh_key_file=.ssh/id_rsa

<$>[注] 您可以更改密钥的名称,如果您想使用其他东西,而不是 ~/.ssh/id_rsa

运行你的Playbook。

1ansible-playbook digitalocean.yml

输出应该是这样的:

 1[label Output]
 2PLAY ***************************************************************************
 3
 4TASK [setup] *******************************************************************
 5ok: [localhost]
 6
 7TASK [ensure ssh key exists] ***************************************************
 8changed: [localhost]
 9
10PLAY RECAP *********************************************************************
11localhost                  : ok=2 changed=1 unreachable=0 failed=0

完成后,您可以通过运行手动验证存在的密钥:

1ls -la ~/.ssh/id_rsa*

它会列出所有匹配 id_rsa* 的文件. 您应该看到 id_rsaid_rsa.pub 列出,表示您的 SSH 密钥存在。

接下来,我们将把密钥推到你的DigitalOcean帐户中,然后再打开播放簿以进行编辑。

1nano digitalocean.yml

我们将使用 digital_ocean Ansible 模块上传您的 SSH 密钥,我们还将将任务的输出注册为 my_ssh_key 变量,因为我们将需要它进行后续操作。

将任务添加到文件的底部,然后保存和关闭文件。

 1[label Updated digitalocean.yml]
 2---
 3. . .
 4  - name: ensure ssh key exists
 5    user: >
 6      name={{ ansible_user_id }}
 7      generate_ssh_key=yes
 8      ssh_key_file=.ssh/id_rsa
 9
10  - name: ensure key exists at DigitalOcean
11    digital_ocean: >
12      state=present
13      command=ssh
14      name=my_ssh_key
15      ssh_pub_key={{ lookup('file', '~/.ssh/id_rsa.pub') }}
16      api_token={{ do_token }}
17    register: my_ssh_key

<$>[注] 如果您命名你的密钥与 id_rsa 不同,请确保在此任务中更新名称为 ssh_pub_key 行。

我们在这里使用了从digital_ocean模块中的一些不同的选项:

在这种情况下,我们想要现在,因为我们希望SSH密钥在帐户中存在

  • command – 这要么是滴滴,要么是 ssh. 我们想要ssh,这使我们能够管理帐户中的SSH密钥的状态
  • name – 这是存储SSH密钥的名称,这必须是唯一的,并将用于通过API和Web接口识别您的密钥
  • ssh_pub_key – 这是您的SSH公共密钥,这将是我们使用用户模块 *api_token_en**的存在。

现在,运行你的Playbook。

1ansible-playbook digitalocean.yml

输出应该是这样的:

1[label Output]
2. . .
3
4TASK [ensure key exists at digital ocean] **************************************
5changed: [localhost]
6
7PLAY RECAP *********************************************************************
8localhost                  : ok=3 changed=1 unreachable=0 failed=0

一旦完成,您可以手动检查您的SSH密钥是否存在于您的DigitalOcean帐户中,通过进入控制面板,点击 设置(从齿轮菜单中),然后 安全性(在左侧栏的 用户类别中)。

步骤3 - 创建一个新的滴滴

在此步骤中,我们将创建一个新的Dropplet。

我们在步骤 2 中简要触及了digital_ocean模块,我们将在此步骤中使用不同的选项集:

  • command — 我们在上一步使用了这个选项,用ssh;这次,我们将使用它与dropplet来管理Dropplets通过这个模块
  • state — 我们在上一步也使用了这个选项;在这里,它代表了Dropplet的状态,我们希望它是现有的 image_id* — 这是用于新Dropplet的图像,如ubuntu-16-04-x64
  • name — 这是在创建Dropplet时使用的主机名称
  • region_id — 这是创建Dropplet的区域,如NYC3
  • size_id — 这是我们

除了我们在本教程中所涵盖的选项之外,还有更多的选项(所有这些选项都可以在 Ansible 文档页面上找到),但使用这些选项作为指南,我们可以写下你的新任务。

打开你的剧本来编辑。

1nano digitalocean.yml

更新您的播放簿到下方以红色突出的新任务,然后保存并关闭文件. 您可以更改尺寸,区域和图像等选项以适应您的应用程序. 下面的选项将创建一个名为 droplet-one的 512MB Ubuntu 16.04 服务器,使用我们在上一步创建的 SSH 键。

 1[label Updated digitalocean.yml]
 2. . .
 3      api_token={{ do_token }}
 4    register: my_ssh_key
 5
 6  - name: ensure droplet one exists
 7    digital_ocean: >
 8      state=present
 9      command=droplet
10      name=droplet-one
11      size_id=512mb
12      region_id=sgp1
13      image_id=ubuntu-16-04-x64
14      ssh_key_ids={{ my_ssh_key.ssh_key.id }}
15      api_token={{ do_token }}
16    register: droplet_one
17
18  - debug: msg="IP is {{ droplet_one.droplet.ip_address }}"

请注意,我们正在使用 { my_ssh_key.ssh_key.id }} 来检索以前设置的 SSH 密钥的 ID,并将其传输到您的新 Droplet。

现在,运行您的播放簿. 这将比以前更长的时间来执行,因为它将创建一个Droplet。

1ansible-playbook digitalocean.yml

输出应该是这样的:

 1. . .
 2
 3TASK [ensure key exists at DigitalOcean] **************************************
 4ok: [localhost]
 5
 6TASK [ensure droplet one exists] ******************************************************
 7changed: [localhost]
 8
 9TASK [debug] *******************************************************************
10ok: [localhost] => {
11"msg": "IP is 111.111.111.111"
12}
13
14PLAY RECAP *********************************************************************
15localhost                  : ok=5 changed=1 unreachable=0 failed=0

Ansible 在返回消息中向我们提供了新 Droplet 的 IP 地址. 要验证它正在运行,您可以直接使用 SSH 登录。

这应该将您连接到新服务器(使用我们在步骤 2 中在您的 Ansible 服务器上创建的 SSH 密钥)。

步骤4 - 确保一滴存在

在此步骤中,我们将讨论idempotence的概念以及如何与使用Ansible提供Dropplets相关。

Ansible 旨在使用 idempotence 的概念运行,这意味着您可以执行相同的任务多次,并且只有在需要时才会进行更改,这通常是第一次运行。

如果您再次运行播放簿(尚未执行!),考虑到当前配置,它将继续提供第二个Dropplet,也称为dropplet-one。 再次运行它,它将创建第三个Dropplet。

独一无二_name参数告诉Ansible和DigitalOcean,您想要为您的服务器提供独特的主机名称,这意味着当您再次运行播放簿时,它将尊重idempotence并考虑已经提供的Droplet,因此不会创建具有相同名称的第二个服务器。

打开你的剧本来编辑:

1nano digitalocean.yml

在「unique_name」参数中添加:

 1[label Updated digitalocean.yml]
 2. . .
 3  - name: ensure droplet one exists
 4    digital_ocean: >
 5      state=present
 6      command=droplet
 7      name=droplet-one
 8      unique_name=yes
 9      size_id=512mb
10. . .

保存并运行您的 Playbook:

1ansible-playbook digitalocean.yml

输出应该不会导致更改的任务,但你会注意到排除输出与 IP 地址仍然显示. 如果你检查你的 DigitalOcean 帐户,你会注意到只提供一个 droplet-one Droplet。

步骤5 - 创建第二滴

在此步骤中,我们将复制我们现有的配置,以提供单独的 Droplet。

为了提供一个单独的Droplet,我们所需要做的就是从我们的第一个Droplet复制Ansible任务. 为了使我们的演示本更强大一点,然而,我们将将它转换为使用一份Droplets列表提供,这使我们能够根据需要轻松扩展我们的车队。

首先,我们需要定义我们的滴滴列表。

打开你的剧本来编辑:

1nano digitalocean.yml

vars部分中提供的 Droplet 名称列表中添加。

 1[label Updated digitalocean.yml]
 2---
 3- hosts: digitalocean
 4
 5  vars:
 6    do_token: <digitalocean_token>
 7    droplets:
 8    - droplet-one
 9    - droplet-two
10
11  tasks:
12. . .

接下来,我们需要更新我们的任务,通过滴滴列表循环,检查它们是否存在,然后将结果保存为变量。

要做到这一点,请如下更新 Playbook 中的 assure droplet one exists 任务:

 1[label Updated digitalocean.yml]
 2. . .
 3  - name: ensure droplets exist
 4    digital_ocean: >
 5      state=present
 6      command=droplet
 7      name={{ item }}
 8      unique_name=yes
 9      size_id=512mb
10      region_id=sgp1
11      image_id=ubuntu-16-04-x64
12      ssh_key_ids={{ my_ssh_key.ssh_key.id }}
13      api_token={{ do_token }}
14    with_items: droplets
15    register: droplet_details
16
17  - debug: msg="IP is {{ item.droplet.ip_address }}"
18    with_items: droplet_details.results

保存并运行您的Playbook。

1ansible-playbook digitalocean.yml

结果应该是这样的:

 1[label Output]
 2. . .
 3TASK [ensure droplets exists] **************************************************
 4ok: [localhost] => (item=droplet-one)
 5changed: [localhost] => (item=droplet-two)
 6
 7TASK [debug] *******************************************************************
 8
 9. . .
10
11"msg": "IP is 111.111.111.111"
12
13. . .
14
15"msg": "IP is 222.222.222.222"
16}
17
18PLAY RECAP *********************************************************************
19localhost                  : ok=5 changed=1 unreachable=0 failed=0

您可能会注意到调试输出中比第一次有更多的信息,这是因为调试模块打印了额外的信息以帮助调试;这是使用该模块注册变量的一个小缺点。

除此之外,您还会看到,我们的第二个Droplet已经提供,而我们的第一个已经运行了。

删除您的 Droplets 同样简单. 任务中的状态参数告诉 Ansible该 Droplet 应该处于什么状态. 将其设置为存在确保 Droplet 存在,并且如果它已经不存在,它将被创建;将其设置为不存在确保指定名称的 Droplet **不存在,并且将删除与指定名称匹配的任何 Droplets (只要设置为独特_名称)。

如果您想删除您在本教程中创建的两个示例滴滴,只需在创建任务中更改状态为缺席,然后重新启动播放簿。

1[label Updated digitalocean.yml]
2. . .
3  - name: ensure droplets exist
4    digital_ocean: >
5      state=absent
6      command=droplet
7. . .

如果你没有,你的Dropplets仍然会被删除,但你会看到一个错误从调试命令(因为没有IP地址返回)。

1ansible-playbook digitalocean.yml

现在你的两个示例滴将被删除。

结论

Ansible是一个非常强大和非常灵活的配置工具,你已经看到使用DigitalOcean API提供(和删除)Dropplets是多么容易,只使用标准的Ansible概念和内置的模块。

状态参数被设置为当前,告诉 Ansible该 Droplet 应该处于什么状态。将其设置为当前确保 Droplet 存在,并且如果它已经不存在,它将被创建;将其设置为不存在告诉 Ansible 确保指定名称 **不存在的 Droplet,并将删除与指定名称匹配的任何 Droplets (只要设置为独特_名称)。

随着您管理的 Droplets 数量的增加,自动化流程的能力将节省您在创建、设置和摧毁 Droplets 作为自动化流程的一部分的时间。

Published At
Categories with 技术
comments powered by Disqus