Help us understand the problem. What is going on with this article?

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さんの方が、多くの人に読んでもらえそうなので、続きはこちらで書こうと思います。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away