序章

Ansible 2.0が最近リリースされ、DigitalOceanAPIバージョン2がサポートされています。 つまり、Ansibleを使用して、Webアプリケーションをプロビジョニングするだけでなく、ドロップレットを自動的にプロビジョニングおよび管理することもできます。

注: Ubuntu 14.04を使用する場合は、古いバージョンのDigitalOcean API PythonWrapperdopyを使用する必要があります。 新しいバージョンは機能しませんが、古いバージョンには、プライベートネットワークに関するいくつかの問題の解決など、いくつかの機能とバグ修正がありません。

ただし、Ubuntu16.04では最新バージョンのdopyを使用できます。 代わりに、16.04 用に作成されたこのチュートリアルのバージョンを使用できます。また、Ubuntu14.04から16.04にアップグレードすることもできます。

DigitalOceanは、SSHキーを設定してドロップレットを作成するためのシンプルなWebインターフェイスを提供しますが、新しいサーバーをプロビジョニングするたびに実行する必要がある手動プロセスです。 アプリケーションが拡張してより多くのサーバーを含むようになり、オンデマンドで拡張および縮小する機能が必要な場合は、各サーバーのアプリケーション展開スクリプトを手動で作成および構成する必要はありません。

Ansibleのようなプロビジョニングツールを使用する利点は、このプロセスを完全に自動化できることと、単一のコマンドを実行するのと同じくらい簡単に開始できることです。 このチュートリアルでは、AnsibleによるDigitalOceanAPIv2のサポートの使用方法を例として示します。

特に、このチュートリアルでは、DOアカウントに新しいSSHキーを設定し、2つの異なるドロップレットをプロビジョニングしてWebアプリケーションの展開に使用できるようにするプロセスについて説明します。 このチュートリアルに従うと、これらのタスクを変更して、既存のアプリケーション展開スクリプトに統合できるようになります。

前提条件

このチュートリアルは基本的なAnsibleの知識に基づいているため、Ansibleを初めて使用する場合は、最初にAnsibleインストールチュートリアルのこのセクションを読むことができます。

このチュートリアルに従うには、次のものが必要です。

  • sudo非rootユーザーを含む1つのUbuntu14.04ドロップレット。

  • サーバーにインストールされたAnsible。これは、前のAnsibleチュートリアルこの手順に従ってセットアップできます。

  • APIの読み取りおよび書き込みパーソナルアクセストークン。 安全な場所にトークンを書き留めてください。 このチュートリアルの後半で必要になります。

ステップ1—Ansibleの設定

このステップでは、DigitalOceanAPIと通信するようにAnsibleを構成します。

通常、AnsibleはSSHを使用してさまざまなサーバーに接続し、コマンドを実行します。 これは、Ansibleの使用を開始するために必要な構成が、すべてのモジュールで一般的に標準であることを意味します。 ただし、DigitalOcean APIとの通信は単なるSSHシェルコマンドではないため、少し追加の設定を行う必要があります。 dopy DigitalOcean API Python Wrapper )Pythonモジュールは、AnsibleがAPIと通信できるようにするものです。

dopyをインストールするには、最初にPythonパッケージマネージャーpipをインストールします。

  1. sudo apt-get install python-pip

次に、pipを使用してdopyをインストールします。

  1. sudo pip install 'dopy>=0.3.5,<=0.3.5'

dopyのバージョン0.3.5を指定しています。 執筆時点では、dopyの新しいバージョンは壊れており、Ansibleでは動作しません。

次に、作業をスムーズに行うための新しいディレクトリを作成し、基本的なAnsible構成ファイルを設定します。

デフォルトでは、Ansibleは/etc/ansible/hostsにあるhostsファイルを使用します。このファイルには、管理しているすべてのサーバーが含まれています。 このファイルは一部のユースケースでは問題ありませんが、グローバルです。 これはグローバル構成であり、一部のユースケースでは問題ありませんが、このチュートリアルではローカルホストファイルを使用します。 このようにして、AnsibleのDO APIサポートについて学習し、テストしているときに、既存の構成を誤って壊すことはありません。

新しいディレクトリを作成して移動します。このディレクトリは、このチュートリアルの残りの部分で使用します。

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

Ansibleを実行すると、実行されているディレクトリでansible.cfgファイルが検索され、見つかった場合は、それらの構成設定が適用されます。 これは、個々のユースケースごとに、hostfileオプションなどのオプションを簡単にオーバーライドできることを意味します。

ansible.cfgという名前の新しいファイルを作成し、nanoまたはお気に入りのテキストエディタを使用して編集できるように開きます。

  1. nano ansible.cfg

以下をansible.cfgに貼り付け、ファイルを保存して閉じます。

更新されたansible.cfg
[defaults]
hostfile = hosts

[defaults]グループでhostfileオプションを設定すると、グローバルファイルの代わりに特定のhostsファイルを使用するようにAnsibleに指示されます。 このansible.cfgは、同じディレクトリでhostsというホストファイルを探すようにAnsibleに指示します。

次に、hostsファイルを作成します。

  1. nano hosts

このチュートリアルではDigitalOceanAPIのみを扱うため、Ansibleにlocalhostで実行するように指示できます。これにより、作業が簡単になり、リモートホストに接続する必要がなくなります。 これは、Ansibleにlocalhostを使用するように指示し、ansible_connectionlocalとして指定することで実行できます。 以下のコードをhostsに貼り付け、ファイルを保存して閉じます。

更新されたhostsファイル
[digitalocean]
localhost ansible_connection=local

最後に、前提条件で作成されたAPIトークンを使用して、AnsibleがDigitalOceanAPIと通信できるようにします。 APIトークンについてAnsibleに伝える方法は3つあります。

  1. api_tokenパラメーターを使用して、各DigitalOceanタスクに直接提供します。
  2. プレイブックまたはhostsファイルで変数として定義し、その変数をapi_tokenパラメーターに使用します。
  3. DO_API_TOKENまたはDO_API_KEYのいずれかとして、環境変数としてエクスポートします。

オプション1は最も直接的なアプローチであり、変数を作成したくない場合は魅力的に聞こえるかもしれません。 ただし、APIトークンは、使用されている各タスクにコピーする必要があることを意味します。 さらに重要なことに、これは、変更された場合は、そのすべてのインスタンスを見つけて、それらをすべて置き換える必要があることを意味します。

オプション2では、オプション1のように、プレイブック内でAPIトークンを直接設定できます。 オプション1とは異なり、変数を使用して1つの場所でのみ定義します。これは、より便利で更新が簡単です。 最も単純なアプローチであるため、このチュートリアルではオプション2を使用します。

ただし、オプション3がAPIトークンを保護するために使用するのに最適な方法であることは、何の価値もありません。これにより、誤ってAPIトークンをリポジトリ(他のユーザーと共有される可能性があります)にコミットすることが非常に困難になります。 これにより、トークンをシステムレベルで構成し、それぞれにトークンを含めることなく、さまざまなプレイブック間で機能させることができます。

digitalocean.ymlという基本的なプレイブックを作成します。

  1. nano digitalocean.yml

次のコードをファイルに貼り付け、APIトークンで置き換えてください。

更新されたdigitalocean.yml
---
- hosts: digitalocean

  vars:
    do_token: your_API_token

  tasks:

次のステップで引き続き作業するため、このファイルをエディターで開いたままにしておくことができます。

ステップ2—SSHキーを設定する

このステップでは、サーバー上に新しいSSHキーを作成し、Ansibleを使用してそれをDigitalOceanアカウントに追加します。

最初に行う必要があるのは、ユーザーがSSHキーペアを持っていることを確認することです。これをDigitalOceanにプッシュして、新しいドロップレットにデフォルトでインストールできるようにします。 これはコマンドラインから簡単に実行できますが、Ansibleのusersモジュールでも同じように簡単に実行できます。 Ansibleを使用すると、使用する前にキーが存在することを確認できるという利点もあります。これにより、さまざまなホストでプレイブックを実行する際の問題を回避できます。

プレイブックに、以下のuserタスクを追加します。これを使用して、SSHキーが存在することを確認してから、ファイルを保存して閉じます。

更新されたdigitalocean.yml
---
- 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以外のものを使用したい場合は、キーの名前を変更できます。

プレイブックを実行します。

  1. 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   

それが終了したら、次のコマンドを実行して、キーが存在することを手動で確認できます。

  1. ls -la ~/.ssh/id_rsa*

id_rsa*に一致するすべてのファイルが一覧表示されます。 id_rsaid_rsa.pubが表示され、SSHキーが存在することを示しているはずです。

次に、キーをDigitalOceanアカウントにプッシュします。プレイブックを開いて、もう一度編集します。

  1. nano digitalocean.yml

digital_ocean Ansibleモジュールを使用してSSHキーをアップロードします。また、後のステップで必要になるため、タスクの出力をmy_ssh_key変数として登録します。

ファイルの最後にタスクを追加し、ファイルを保存して閉じます。

更新されたdigitalocean.yml
---
. . .
  - 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モジュールのさまざまなオプションを使用しています。

  • state —これは、存在、アクティブ、不在、または削除できます。 この場合、SSHキーをアカウントに存在させたいので、presentが必要です。
  • コマンド—これはドロップレットまたはsshのいずれかです。 アカウント内のSSHキーの状態を管理できるsshが必要です。
  • name —これはSSHキーを保存するための名前です。これは一意である必要があり、APIおよびWebインターフェイスを介してキーを識別するために使用されます。
  • ssh_pub_key —これはSSH公開鍵であり、ユーザーモジュールを使用してその存在を保証した鍵になります。
  • api_token —これはDigitalOcean APIトークンであり、変数としてアクセスできます(do_tokenvarsセクションで定義)。

次に、プレイブックを実行します。

  1. 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アカウントに存在することを手動で確認できます。左側のサイドバーのUserカテゴリ)。 SSHキーの下に新しいキーが表示されます。

ステップ3—新しい液滴を作成する

このステップでは、新しいドロップレットを作成します。

手順2でdigital_oceanモジュールについて簡単に触れました。 このステップでは、このモジュールに異なるオプションのセットを使用します。

  • コマンド—このモジュールを介してドロップレットを管理するために、前の手順で “ ssh ; this time, we'll use it with droplet`でこのオプションを使用しました。
  • state —前の手順でもこれを使用しました。 ここでは、presentになりたいドロップレットの状態を表します。
  • image_id —これは、ubuntu-14-04-x64のように、新しいドロップレットに使用する画像です。
  • name —これはドロップレットを作成するときに使用するホスト名です。
  • region_id —これは、NYC3のように、ドロップレットを作成する領域です。
  • size_id —これは、512mbのように、作成するドロップレットのサイズです。
  • ssh_key_ids —これは、サーバーの作成時にサーバーに設定されるSSHキーID(または複数のID)です。

このチュートリアルで取り上げているオプション(すべてAnsibleのドキュメントページにあります)以外にも多くのオプションがありますが、これらのオプションをガイドとして使用して、新しいタスクを作成できます。

プレイブックを開いて編集します。

  1. nano digitalocean.yml

下の赤で強調表示されている新しいタスクでプレイブックを更新してから、ファイルを保存して閉じます。 アプリケーションに合わせて、サイズ、地域、画像などのオプションを変更できます。 以下のオプションは、前の手順で作成したSSHキーを使用して、droplet-oneという名前の512MBのUbuntu14.04サーバーを作成します。

更新されたdigitalocean.yml
. . .
      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-14-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を取得し、それを新しいドロップレットに渡すことに注意してください。 これは、SSHキーが新しく作成された場合、またはSSHキーがすでに存在する場合に機能します。

次に、プレイブックを実行します。 ドロップレットが作成されるため、これは以前よりも実行に少し時間がかかります。

  1. 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は、返信メッセージで新しいドロップレットのIPアドレスを提供してくれました。 実行されていることを確認するには、SSHを使用して直接ログインできます。

  1. ssh [email protected]111.111.111.111

これにより、新しいサーバーに接続されます(ステップ2でAnsibleサーバーで作成したSSHキーを使用)。 次に、CTRL+Dを押して、Ansibleサーバーに戻ることができます。

ステップ4—液滴が存在することを確認する

このステップでは、べき等の概念と、Ansibleを使用したドロップレットのプロビジョニングに関連する方法について説明します。

Ansibleは、べき等の概念を使用して動作することを目的としています。 つまり、同じタスクを複数回実行でき、変更は必要な場合にのみ行う必要があります。これは通常、初めて実行する場合です。 このアイデアは、サーバーのプロビジョニング、パッケージのインストール、およびその他のサーバー管理に適しています。

プレイブックを再度実行すると(まだ実行しないでください!)、現在の構成を前提として、プレイブックは先に進み、droplet-oneとも呼ばれる2番目のドロップレットをプロビジョニングします。 もう一度実行すると、3番目のドロップレットが作成されます。 これは、DigitalOceanが同じ名前の複数のドロップレットを許可しているためです。 これを回避するために、unique_nameパラメーターを使用できます。

unique_nameパラメーターは、サーバーに一意のホスト名が必要であることをAnsibleとDigitalOceanに通知します。 つまり、プレイブックを再度実行すると、べき等性が尊重され、既にプロビジョニングされているドロップレットが考慮されるため、同じ名前の2番目のサーバーは作成されません。

プレイブックを開いて編集します。

  1. nano digitalocean.yml

unique_nameパラメーターを追加します。

更新されたdigitalocean.yml
. . .
  - name: ensure droplet one exists
    digital_ocean: >
      state=present
      command=droplet
      name=droplet-one
      unique_name=yes
      size_id=512mb
. . .

プレイブックを保存して実行します。

  1. ansible-playbook digitalocean.yml

出力によってタスクが変更されることはありませんが、IPアドレスを含むデバッグ出力が引き続き表示されます。 DigitalOceanアカウントを確認すると、ドロップレットが1つだけであることがわかります。1つのドロップレットがプロビジョニングされています。

ステップ5—2番目の液滴を作成する

このステップでは、既存の構成を複製して、個別のドロップレットをプロビジョニングします。

別のドロップレットをプロビジョニングするには、最初のドロップレットからAnsibleタスクを複製するだけです。 ただし、プレイブックをもう少し堅牢にするために、ドロップレットのリストを使用してプロビジョニングするように変換します。これにより、必要に応じてフリートを簡単にスケールアウトできます。

まず、ドロップレットのリストを定義する必要があります。

プレイブックを開いて編集します。

  1. nano digitalocean.yml

varsセクションでプロビジョニングするドロップレット名のリストを追加します。

更新されたdigitalocean.yml
---
- hosts: digitalocean

  vars:
    do_token: <digitalocean_token>
    droplets:
    - droplet-one
    - droplet-two

  tasks:
. . .

次に、タスクを更新してドロップレットのリストをループし、ドロップレットが存在するかどうかを確認してから、結果を変数に保存する必要があります。 その後、debugタスクを変更して、各アイテムの変数に格納されている情報を出力する必要もあります。

これを行うには、プレイブックのドロップレットが存在することを確認するタスクを次のように更新します。

更新されたdigitalocean.yml
. . .
  - name: ensure droplets exist
    digital_ocean: >
      state=present
      command=droplet
      name={{ item }}
      unique_name=yes
      size_id=512mb
      region_id=sgp1
      image_id=ubuntu-14-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

プレイブックを保存して実行します。

  1. 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モジュールがデバッグに役立つ追加情報を出力するためです。 これは、このモジュールで登録変数を使用することの小さな欠点です。

それとは別に、最初のドロップレットがすでに実行されている間に、2番目のドロップレットがプロビジョニングされていることがわかります。 これで、Ansibleのみを使用して2つのDigitalOceanドロップレットをプロビジョニングしました。

ドロップレットの削除も同様に簡単です。 タスクのstateパラメーターは、Dropletがどの状態にあるべきかをAnsibleに指示します。 presentに設定すると、ドロップレットが確実に存在し、まだ存在しない場合は作成されます。 absentに設定すると、指定した名前のドロップレットが存在しないことが保証され、指定した名前に一致するドロップレットが削除されます(unique_nameが設定されている場合)。

このチュートリアルで作成した2つのドロップレットの例を削除する場合は、作成タスクの状態をabsentに変更して、プレイブックを再実行してください。

更新されたdigitalocean.yml
. . .
  - name: ensure droplets exist
    digital_ocean: >
      state=absent
      command=droplet
. . .

プレイブックを再実行する前に、デバッグ行を削除することもできます。 そうしないと、ドロップレットは削除されますが、debugコマンドからエラーが表示されます(返すIPアドレスがないため)。

  1. ansible-playbook digitalocean.yml

これで、2つのサンプルドロップレットが削除されます。

結論

Ansibleは、非常に強力で非常に柔軟なプロビジョニングツールです。 標準のAnsibleの概念と組み込みモジュールのみを使用してDigitalOceanAPIを使用して、ドロップレットをプロビジョニング(およびプロビジョニング解除)するのがいかに簡単であるかを見てきました。

presentに設定されたstateパラメーターは、Dropletがどのような状態にあるべきかをAnsibleに指示します。 presentに設定すると、ドロップレットが確実に存在し、まだ存在しない場合は作成されます。 absentに設定すると、Ansibleに指定された名前のドロップレットが存在しないことを確認し、指定された名前に一致するドロップレットを削除します(unique_nameが設定されている場合) )。

管理するドロップレットの数が増えると、プロセスを自動化する機能により、自動化されたプロセスの一部としてドロップレットを作成、設定、および破棄する時間を節約できます。 このチュートリアルの例を適応および拡張して、セットアップに合わせたプロビジョニングスクリプトを改善できます。