介绍
Ansible 2.0提供支持的API DigitalOcean第2版 ,这意味着你可以使用Ansible不仅提供Web应用程序,而且还提供和自动管理Droplet。
虽然DigitalOcean为设置SSH密钥和创建Droplet提供了一个简单的Web界面,但它是一个手动过程,每次您需要配置新服务器时需要经过。 当您的应用程序扩展到包含更大数量的服务器,并且需要根据需要增长和缩减时,您不需要手动处理为每个服务器创建和配置应用程序部署脚本。
使用像Ansible这样的配置工具的好处是,它允许你完全自动化这个过程,启动它就像运行单个命令一样简单。 本教程将通过示例演示如何使用Ansible对DigitalOcean API v2的支持。
特别是,本教程将介绍在DO帐户上设置新的SSH密钥并提供两个不同的Droplet的过程,以便它们可以用于部署Web应用程序。 完成本教程后,您将能够修改这些任务并将其集成到现有的应用程序部署脚本中。
先决条件
本教程建立在基础知识Ansible,所以如果你是新来Ansible,你可以阅读的Ansible安装教程本节第一。
要遵循本教程,您需要:
一个Ubuntu的16.04Droplet与Sudo非root用户 。
安装在服务器,您可以通过以下设置上Ansible 从以前的Ansible教程这一步 。
读和写个人访问令牌的API。 确保你在安全的地方写下令牌; 你将需要它在本教程的后面。
第1步 - 配置Ansible
在这一步中,我们将配置Ansible与DigitalOcean API通信。
通常,Ansible仅使用SSH连接到不同的服务器并运行命令。 这意味着必须开始使用Ansible的配置通常是所有模块的标准配置。 但是,因为与DigitalOcean API的通信不是简单的SSH shell命令,我们需要做一些额外的设置。 该dopy
(DigitalOcean API的Python包装 )Python模块是将允许Ansible与API通信。
为了安装dopy
,首先安装Python包管理器pip
。
sudo apt-get install python-pip
然后,安装dopy
使用pip
。
sudo pip install dopy
接下来,我们将创建一个新目录以保持整洁,我们将设置一个基本的Ansible配置文件。
默认情况下,Ansible使用位于主机文件/etc/ansible/hosts
,其中包含所有它管理的服务器。 虽然该文件在一些用例是罚款,它是全球的。 这是一个全局配置,在一些用例中是很好的,但是我们将在本教程中使用本地hosts文件。 这样,我们不会意外破坏您在学习和测试Ansible的DO API支持时可能存在的任何现有配置。
创建并移动到一个新目录,我们将在本教程的其余部分使用。
mkdir ~/ansible-do-api
cd ~/ansible-do-api/
当你运行Ansible,它会寻找一个ansible.cfg
在它运行的目录下的文件,如果找到一个,它会应用这些配置设置。 这意味着我们可以很容易地覆盖选项,如hostfile
选项,每个用例。
创建一个新的文件名为ansible.cfg
并打开它使用编辑nano
或您喜爱的文本编辑器。
nano ansible.cfg
以下内容粘贴到ansible.cfg
,然后保存并关闭文件。
[defaults]
hostfile = hosts
设置hostfile
中选择[defaults]
组告诉Ansible使用一个特定的hosts文件,而不是全球性的。 这ansible.cfg
告诉Ansible寻找一个叫HOSTFILE hosts
在同一目录下。
接下来,我们将创建hosts
文件。
nano hosts
因为我们将只处理本教程中的DigitalOcean API,我们可以告诉Ansible上运行localhost
,这使事情变得简单,并会删除需要连接到远程主机。 这可以通过告诉Ansible用做localhost
,并指定ansible_connection
为local
。 下面的代码粘贴到hosts
,然后保存并关闭文件。
[digitalocean]
localhost ansible_connection=local
最后,我们将使用在先决条件中创建的API令牌,以允许Ansible与DigitalOcean API进行通信。 有三种方式我们可以告诉Ansible有关API令牌:
- 直接在每个DigitalOcean任务提供它,使用
api_token
参数。 - 把它定义为在剧本或主机文件的变量,并使用该变量对于
api_token
参数。 - 导出它作为一个环境变量,无论是
DO_API_TOKEN
或DO_API_KEY
。
选项1是最直接的方法,如果您不想创建变量,可能听起来很吸引人。 但是,这意味着API令牌将需要复制到它正在使用的每个任务中。 更重要的是,这意味着如果它发生变化,你需要找到它的所有实例,并替换它们。
选项2允许我们直接在我们的剧本中设置API令牌,如选项1.与选项1不同,我们只使用一个变量来定义它在一个地方,这更方便,更容易更新。 我们将使用本教程的选项2,因为它是最简单的方法。
然而,值得一提的是,选项3是用于保护您的API令牌的最佳方法,因为它使您难以将API令牌意外提交到存储库(可能与任何人共享)。 它允许在系统级别配置令牌,并在不同的剧本中工作,而不必在每个剧本中包含令牌。
创建一个名为一个基本的剧本digitalocean.yml
。
nano digitalocean.yml
将以下代码粘贴到文件中,确保替换为您的API令牌。
---
- hosts: digitalocean
vars:
do_token: your_API_token
tasks:
您可以在编辑器中打开此文件,我们将在下一步继续使用它。
第2步 - 设置SSH密钥
在此步骤中,我们将在服务器上创建一个新的SSH密钥,并使用Ansible将其添加到您的DigitalOcean帐户。
我们需要做的第一件事是确保用户有一个SSH密钥对,我们可以推送到DigitalOcean,以便它可以默认安装在新的Droplet上。 虽然这是很容易通过命令行来做到这一点,我们可以用很容易地做到这一点用户在Ansible模块。 使用Ansible还具有确保密钥在使用之前存在的好处,这可以避免在不同主机上运行剧本时的问题。
在你的剧本,加入了user
下面的任务,我们可以用它来确保SSH密钥存在,然后保存并关闭文件。
---
- hosts: digitalocean
vars:
do_token: your_API_token
tasks:
- name: ensure ssh key exists
user: >
name={{ ansible_user_id }}
generate_ssh_key=yes
ssh_key_file=.ssh/id_rsa
您可以更改键的名称,如果你想使用比其他东西~/.ssh/id_rsa
。
运行您的手册。
ansible-playbook digitalocean.yml
输出应如下所示:
PLAY ***************************************************************************
TASK [setup] *******************************************************************
ok: [localhost]
TASK [ensure ssh key exists] ***************************************************
changed: [localhost]
PLAY RECAP *********************************************************************
localhost : ok=2 changed=1 unreachable=0 failed=0
完成后,您可以通过运行以下步骤手动验证密钥是否存在:
ls -la ~/.ssh/id_rsa*
它会列出所有匹配的文件id_rsa*
。 您应该看到id_rsa
和id_rsa.pub
上市,这说明你的SSH密钥存在。
接下来,我们会将钥匙推入您的DigitalOcean帐户,因此请重新打开您的剧本进行编辑。
nano digitalocean.yml
我们将使用digital_ocean Ansible模块上传您的SSH key.We也将注册任务为输出my_ssh_key
变量,因为我们需要它后面的步骤。
将任务添加到文件的底部,然后保存并关闭文件。
---
. . .
- name: ensure ssh key exists
user: >
name={{ ansible_user_id }}
generate_ssh_key=yes
ssh_key_file=.ssh/id_rsa
- name: ensure key exists at DigitalOcean
digital_ocean: >
state=present
command=ssh
name=my_ssh_key
ssh_pub_key={{ lookup('file', '~/.ssh/id_rsa.pub') }}
api_token={{ do_token }}
register: my_ssh_key
如果你的命名比其它关键的东西id_rsa
,确保更新名称是ssh_pub_key
在这个任务线。
我们使用了一些来自不同的选项digital_ocean
这里模块:
- 状态 -这可以是本,活跃,不存在,或删除。 在这种情况下,我们希望
present
,因为我们希望SSH密钥存在于该帐户。 - 命令 -这是不是Droplet或ssh。 我们希望
ssh
,这使我们能够在帐户中管理SSH密钥的状态。 - 名称 -这是保存SSH密钥下,这必须是唯一的,将被用于通过API和Web界面来确定你的关键的名称。
- ssh_pub_key -这是你的SSH公共密钥,这将是它的存在,我们放心使用的用户模块的关键。
- api_token -这是你DigitalOcean API令牌,这对我们作为一个变量访问(
do_token
,在定义vars
部分)。
现在,运行你的手册。
ansible-playbook digitalocean.yml
输出应如下所示:
. . .
TASK [ensure key exists at digital ocean] **************************************
changed: [localhost]
PLAY RECAP *********************************************************************
localhost : ok=3 changed=1 unreachable=0 failed=0
当完成后,您可以手动检查您的SSH密钥在您的帐户DigitalOcean通过转到控制面板,单击设置 (从齿轮菜单)存在,那么安全性 (在用户类别左侧边栏)。 您应该看到在SSH密钥列入新的密钥。
第3步 - 创建新的点Droplet
在这一步中,我们将创建一个新的Droplet。
我们简要介绍了上digital_ocean
在第2步模块我们将使用一组不同的选项,这个模块在这个步骤:
- 命令 -我们使用与'上一步中这个选项
ssh
; 这一次,我们将用它来与droplet
通过该模块来管理Droplet。 - 状态 -我们在前面的工序中,也用这种; 在这里,它代表的Droplet,这是我们希望的状态
present
。 - image_id -这是使用新Droplet,像图像
ubuntu-16-04-x64
。 - 名称 -这是创建Droplet时使用的主机名。
- REGION_ID -这是在创造Droplet,像区域
NYC3
。 - size_id -这是我们要创建,如Droplet的大小
512mb
。 - SSH 密钥的标识 -这是SSH密钥ID(或ID)到服务器上创建时进行设置。
有更多的选项,而不仅仅是我们在本教程中覆盖的(所有这些都可以在Ansible文档页面上找到),但使用这些选项作为指南,我们可以编写您的新任务。
打开您的剧本进行编辑。
nano digitalocean.yml
将您的剧本更新为下面以红色突出显示的新任务,然后保存并关闭文件。 您可以更改大小,区域和图像等选项以适合您的应用程序。 下面的选项将创建一个使用我们在上一步中创建的SSH密钥一个512MB的Ubuntu命名Droplet一 16.04服务器。
. . .
api_token={{ do_token }}
register: my_ssh_key
- name: ensure droplet one exists
digital_ocean: >
state=present
command=droplet
name=droplet-one
size_id=512mb
region_id=sgp1
image_id=ubuntu-16-04-x64
ssh_key_ids={{ my_ssh_key.ssh_key.id }}
api_token={{ do_token }}
register: droplet_one
- debug: msg="IP is {{ droplet_one.droplet.ip_address }}"
请注意,我们使用{{ my_ssh_key.ssh_key.id }}
检索前面设置SSH密钥的ID,并将它传递到新的Droplet。 如果SSH密钥是新创建的或者如果它已经存在,这个工作。
现在,运行你的手册。 这将需要一段时间来执行,因为它将创建一个Droplet。
ansible-playbook digitalocean.yml
输出应如下所示:
. . .
TASK [ensure key exists at DigitalOcean] **************************************
ok: [localhost]
TASK [ensure droplet one exists] ******************************************************
changed: [localhost]
TASK [debug] *******************************************************************
ok: [localhost] => {
"msg": "IP is 111.111.111.111"
}
PLAY RECAP *********************************************************************
localhost : ok=5 changed=1 unreachable=0 failed=0
Ansible在返回消息中为我们提供了新的Droplet的IP地址。 要验证它是否正在运行,您可以使用SSH直接登录。
ssh root@111.111.111.111
这应该将您连接到您的新服务器(使用我们在第2步中在您的Ansible服务器上创建的SSH密钥)。 然后,您可以通过按退回到您的Ansible服务器CTRL+D
。
第4步 - 确保Droplet存在
在这一步中,我们将讨论幂等性的概念,以及如何与Ansible配置Droplets相关。
Ansible旨在使用幂等性的概念进行操作。 这意味着您可以多次运行相同的任务,并且只有在需要时才进行更改 - 这通常是第一次运行。 这个想法很好地映射到配置服务器,安装软件包和其他服务器管理。
如果再次(不这样做呢!)运行你的剧本,鉴于目前的配置,它会继续前进,准备第二Droplet也叫droplet-one
。 再次运行它,它会使第三个Droplet。 这是由于DigitalOcean允许具有相同名称的多个Droplet的事实。 为了避免这种情况,我们可以使用unique_name
参数。
该unique_name
参数告诉Ansible和DigitalOcean你想为你的服务器的主机名的独特。 这意味着,当您再次运行您的手册时,它将遵循幂等性,并考虑已经配置的Droplet,因此不会创建具有相同名称的第二个服务器。
打开您的剧本进行编辑:
nano digitalocean.yml
添加在unique_name
参数:
. . .
- name: ensure droplet one exists
digital_ocean: >
state=present
command=droplet
name=droplet-one
unique_name=yes
size_id=512mb
. . .
保存并运行您的剧本:
ansible-playbook digitalocean.yml
输出应该导致没有更改的任务,但您会注意到仍然显示带有IP地址的调试输出。 如果你检查你的帐户DigitalOcean,你会发现只有一个Droplet一Droplet被提供。
第5步 - 创建第二Droplet
在此步骤中,我们将复制现有配置以配置单独的Droplet。
为了提供单独的Droplet,我们需要做的是从我们的第一个Droplet复制Ansible任务。 然而,为了使我们的剧本更健壮,我们将它转换为使用Droplets的列表供应,这使我们能够根据需要轻松扩展我们的Fleet。
首先,我们需要定义我们的Droplets列表。
打开您的剧本进行编辑:
nano digitalocean.yml
加在Droplet名称的列表,以在被供应vars
部分。
---
- hosts: digitalocean
vars:
do_token: <digitalocean_token>
droplets:
- droplet-one
- droplet-two
tasks:
. . .
接下来,我们需要更新任务以遍历Droplet列表,检查它们是否存在,然后将结果保存到变量中。 之后,我们还需要修改我们的debug
任务,以输出存储在每个项目的变量中的信息。
要做到这一点,更新确保在你的剧本Droplet存在一个任务如下:
. . .
- name: ensure droplets exist
digital_ocean: >
state=present
command=droplet
name={{ item }}
unique_name=yes
size_id=512mb
region_id=sgp1
image_id=ubuntu-16-04-x64
ssh_key_ids={{ my_ssh_key.ssh_key.id }}
api_token={{ do_token }}
with_items: droplets
register: droplet_details
- debug: msg="IP is {{ item.droplet.ip_address }}"
with_items: droplet_details.results
保存并运行您的剧本。
ansible-playbook digitalocean.yml
结果应如下所示:
. . .
TASK [ensure droplets exists] **************************************************
ok: [localhost] => (item=droplet-one)
changed: [localhost] => (item=droplet-two)
TASK [debug] *******************************************************************
. . .
"msg": "IP is 111.111.111.111"
. . .
"msg": "IP is 222.222.222.222"
}
PLAY RECAP *********************************************************************
localhost : ok=5 changed=1 unreachable=0 failed=0
您可能会注意到,在debug
输出中有一个更多的信息比它做了第一次。 这是因为, debug
模块打印用于与调试帮助的附加信息; 这是使用此模块注册变量的一个小缺点。
除此之外,你会看到我们的第二个Droplet已经配置,而我们的第一个已经运行。 你现在只使用Ansible配置了两个DigitalOcean Droplet!
删除你的Droplet也很简单。 任务的状态参数告诉Ansible处于何种状态飞沫应该在设置它。 present
确保Droplet存在,如果它不存在将创建它; 它设置为absent
确保了指定名称的Droplet不存在的 ,(因为只要它会删除匹配的指定名称的任何Dropletunique_name
设置)。
如果你想删除的Droplet在本教程中创建的两个例子,只是改变国家在创建任务absent
并重新运行你的剧本。
. . .
- name: ensure droplets exist
digital_ocean: >
state=absent
command=droplet
. . .
您也可以在重新运行剧本之前删除调试行。 如果没有,你的Droplets仍然会被删除,但是你会看到debug命令的错误(因为没有IP地址要返回)。
ansible-playbook digitalocean.yml
现在你的两个例子Droplets将被删除。
结论
Ansible是一个非常强大和非常灵活的配置工具。 您已经看到使用仅使用标准Ansible概念和内置模块的DigitalOcean API来配置(和取消配置)Droplets是多么容易。
状态参数,该参数设置为present
,告诉Ansible处于何种状态飞沫应该在设置它。 present
确保Droplet存在,如果它不存在将创建它; 将它设置为absent
告诉Ansible,以确保与指定名称的Droplet不存在的 ,它会删除匹配指定名称的任何Droplet(只要unique_name
设置)。
随着您管理的Droplets数量的增加,自动化过程的能力将节省您在创建,设置和销毁Droplet作为自动化过程一部分的时间。 您可以修改和扩展本教程中的示例,以改进您的设置的自定义配置脚本。