Edited at

AnsibleでGCEインスタンスを管理する

More than 3 years have passed since last update.

AnsibleにはGoogle Compute Engineの

リソース管理用モジュール(GCEモジュール)が

組み込まれています。

GCEモジュールを使うことで、


  • Instanceの生成

  • network access制御

  • persistant diskの利用

  • load balancerの管理

を自動化できます。

さらに、

inventoryプラグインもあり、

生成したGCEinstanceの情報をAnsible dynamic inventoryに自動的に吸い上げ、tagやプロパティでグループ化できます。

しかし、

使う際には、必要な認証や設定がいくつかある上に、

ドキュメントの記述が複雑でわかりづらい部分もあるため

結構ハマりました。

その辺りを回避できるように解説していきます。


準備

AnsibleのGCEモジュールは、pythonのapache-libcloudモジュールに依存しているので、

pip installします。

$ pip install apache-libcloud


ディレクトリ構成

GCEモジュールのドキュメントには、

Playbookファイルなどのディレクトリ構成の記載がありません。

ベスト・プラクティスを見習うべきですが、

簡単に始めるには、以下のような構成で良いんじゃないかと思います。

~/gce_ansible/

play.sh # playbook実行シェルスクリプト
master.yml # master playbook
credentials/ # 証明書管理Dir
cacert.pem # libcloud用 CA bundleファイル
pkey.pem # GCE用 証明書ファイル
secrets.py # 証明書指定ファイル
inventory/ # inventory管理用Dir
gce.ini # GCE用設定ファイル
gce.py # GCE用モジュール
hosts # inventoryファイル
vars/
gce_auth.yml # GCE認証情報変数
instance.yml # GCEinstance設定変数

以下、ディレクトリごとに解説します。


credentials | 証明書の取得


libcloud用 CA bundleファイル

Mac OS Xで利用している場合、libcloud用 CA bundleファイルが必要です。

cURL - Extract CA Certs

で「HTTP from curl.haxx.se: cacert.pem」をダウンロードして、

前述ディレクトリの credentials に配置しましょう。

ちなみに、これが無いとplaybook実行時に以下のようなエラーが出ました。

RuntimeError: No CA Certificates were found in CA_CERTS_PATH.


GCE用 証明書ファイル

次に、GCEにアクセスするための証明書ファイルが必要です。

Google Developer Console

で、(Project名) > APIS&AUTH > 認証情報

を選択、OAuthの「新しいクライアントIDを作成」をクリックします。

「サービスアカウント」を選択してクライアントIDを作成しましょう。

完了画面にパスワード’notasecret’ が表示され、

自動的にp12形式証明書ファイルを取得できます。

完了画面を閉じた後「サービスアカウント」欄に追加されたメールアドレスは後で必要になります。

証明書をapache-libcloudで使うため、

以下のコマンドで、p12ファイルをpem形式(openSSL標準)に変換します。

$ openssl pkcs12 -in (p12ファイルパス).p12 -passin pass:notasecret -nodes -nocerts | openssl rsa -out ~/gce_ansible/credentials/pkey.pem


証明書指定ファイル(secrets.py)

GCE用証明書ファイルをansibleに認識させるため、

以下のようにpythonファイル(secrets.py)を作成します。

GCE_PARAMS = ('i...@project.googleusercontent.com', '~/gce_ansible/credentials/pkey.pem')

GCE_KEYWORD_PARAMS = {'project': 'project-name'}

記載するのは、前述の「サービスアカウント」欄のメールアドレスと、

pemファイルパス、対象のGCEプロジェクト名です。


inventory | 実行対象ホスト


ローカルホスト指定(hosts)

GCEのinstance生成は、ローカルPCから実行するので、

まずはlocalhostを設定します。

[localhost]

127.0.0.1


GCE Dynamic Inventory

Dynamic Inventoryという仕組みを使うと、

GCEで生成したinstanceのIPアドレスを自動で取得して、

inventoryとして判断してくれるようになります。

Ansibleが提供している GCE inventory plugin を使います。

Ansibleのgithubリポジトリから

- contrib/inventory/gce.ini

- contrib/inventory/gce.py

を取得して、それぞれ


  • inventory/gce.ini

  • inventory/gce.py

に置きましょう。

gce.iniに、secrets.pyの絶対パスを指定します。例えば、

libcloud_secrets = /Users/shuhei/gce_ansible/credentials/secrets.py


動作確認

Dynamic Inventoryが正常に動作するかどうかを確認します。

$ cd ~/gce_ansible

$ export SSL_CERT_FILE=$HOME/gce_ansible/credentials/cacert.pem # Mac OSX の場合のみ
$ ./inventory/gce.py --list

GCE上にすでにinstanceが動作している場合は、そのhostの情報がjsonで出力されるはずです。

また、以下のコマンドでさらに詳細な情報が出力されます。

$ cd ~/gce_ansible

$ export GCE_INI_PATH=$HOME/gce_ansible/inventory/gce.ini
$ ansible all -i inventory/gce.py -m setup
hostname | success >> {
"ansible_facts": {
"ansible_all_ipv4_addresses": [
"x.x.x.x"
],
....
}
}


master.yml | playbook本体

いよいよplaybookの作成です。

今回は、GCEのinstanceを生成するだけにしておきます。


master.yml

- name: Create new GCE instances

hosts: localhost
gather_facts: no
vars_files:
- "vars/instance.yml"
- "vars/gce_auth.yml"
tasks:
- name: Launch instances
local_action:
module: gce
instance_names: "{{ names }}"
machine_type: "{{ type }}"
image: "{{ image }}"
zone: "{{ zone }}"
service_account_email: "{{ service_account_email }}"
pem_file: "{{ pem_file }}"
project_id: "{{ project_id }}"
tags: webserver


vars | 変数の管理

playbook内の二重波括弧 {{ … }} で囲っている部分は変数で、

var_files: として指定している以下の2ファイルに値を記載します。


vars/gce_auth.yml

(credentials/secrets.py と内容がかぶっているので何とかならないか...?)

service_account_email: i...@project.googleusercontent.com

pem_file: ~/gce_ansible/credentials/pkey.pem
project_id: project-name


vars/instance.yml

names: www1

type: f1-micro
image: debian-7
zone: us-central1-b


play.sh | playbook実行用シェルスクリプト

playbookを実行する前に、実行するためのシェルスクリプトを作成しておきます。

#!/bin/bash

PLAYBOOK="$1"

if [ -z $PLAYBOOK ]; then
echo "You need to pass a playback as argument to this script."
exit 1
fi

export GCE_INI_PATH=$(pwd)/inventory/gce.ini
export SSL_CERT_FILE=$(pwd)/credentials/cacert.pem
export ANSIBLE_HOST_KEY_CHECKING=False

if [ ! -f "$SSL_CERT_FILE" ]; then
curl -O http://curl.haxx.se/ca/cacert.pem
fi

ansible-playbook -v -i inventory/ "$PLAYBOOK"


実行!

$ cd ~/gce_ansible

$ ./play.sh master.yml

PLAY [Create new GCE instances] ******************
...()...
PLAY RECAP ********************************************************************
127.0.0.1 : ok=1 changed=1 unreachable=0 failed=0

実行後、ふたたび Google Developer Console にアクセスして

該当プロジェクトの

[Compute Engine] > [VMインスタンス]

を見ると、www1 という名前のinstanceが生成されているはずです。

ということで、今回はこの辺りでおしまいです。

次回は、Google Compute Engine(GCE)に生成したinstanceに

アプリケーションをセッティングしていく予定です。

:exclamation: この記事は私のブログ「Let's go Curious」で書いたのですが、

Qiitaさんの方が、多くの人に読んでもらえそうなので、続きはこちらで書こうと思います。