Ansible2.0 OpenStackモジュール入門

先日、Ansible2.0がリリースされました。アップデートの詳細は[こちらのリリース記事訳](http://qiita.com/t_nakayama0714/items/0d602a4fae60aa78b6ef)を参照していただくとして、ここではその中でも大幅に強化されたOpenStack API操作モジュールについて、その概要や簡単な使い方を紹介します。

## OpenStack上でシステムを構成する一通りのモジュールが揃った
これまでのバージョン1.X系でも、OpenStack上でのインスタンス作成・削除やネットワーク作成・削除といった簡単な機能を提供するモジュールはあったようですが、操作できるAPIは限られていました。しかし、今回のアップデートでは、OpenStackのIaaSとしての機能ほとんどをカバーしているようです。

これにより、 **Ansibleだけでインフラのプロビジョニングからアプリケーションのデプロイまで** 可能になったことになります。これまでは、インフラのプロビジョニングはHeatやVagrantで行い、アプリケーションのデプロイはAnsibleで行うなど、複数の技術を組み合わせる必要がありましたが、全てをAnsibleだけでできるというのは非常に魅力的なのではないでしょうか。

OpenStack関連モジュールの一覧は[公式ドキュメント](http://docs.ansible.com/ansible/list_of_cloud_modules.html#openstack)で確認できます。

## OpenStackモジュールの使い方
それでは早速OpenStackモジュールを使ってみましょう。今回はOpenStackのテナント上に何のリソースも無い状態から、以下の環境を構成します。

* ネットワーク: demo-net
* サブネット: demo-subnet(10.0.0.0/24)
* ルータ: demo-router
* セキュリティグループ: demo-sg
* セキュリティグループルール: tcp/22許可
* キーペア: demo-key
* インスタンス: demo-instance

**ネットワークトポロジー**
![Kobito.WCpi1h.png](https://qiita-image-store.s3.amazonaws.com/0/81715/88eb1f06-897d-0ef1-69ee-699dd2bdfaad.png "Kobito.WCpi1h.png")

### 動作環境
* CentOS6.6
* python 2.7.10（virtualenv環境を使用しました）
* OpenStack Juno

### Ansibleのインストール
pipでもインストールできますが、まだOpenStackモジュールにバグがあったりするので（すでにいくつかハマった）Githubの開発ブランチを使用するようにします。公式ドキュメントでも多くのユーザが開発ブランチを利用していると書いてあります。

リポジトリをクローンして、セットアップスクリプトを読み込みます。

```
$ git clone https://github.com/ansible/ansible.git --recursive
$ cd ansible
$ source hacking/env-setup

$ ansible --version
ansible 2.1.0 (devel e3a6accc1d) last updated 2016/01/20 23:06:19 (GMT +900)
  lib/ansible/modules/core: (detached HEAD ffea58ee86) last updated 2016/01/20 23:06:30 (GMT +900)
  lib/ansible/modules/extras: (detached HEAD e9450df878) last updated 2016/01/20 23:06:33 (GMT +900)
  config file =
  configured module search path = Default w/o overrides
```

Ansibleが依存するPythonライブラリと、OpenStackモジュールが依存するshadeというライブラリをインストールしておきます。

```
$ pip install paramiko PyYAML Jinja2 httplib2 six
$ pip install shade
```

### OpenStack認証ファイル
OpenStack APIのクライアントライブラリであるshadeは、OpenStackの認証情報を`clouds.yml`という名前のファイルから読み込みます。これをカレントディレクトリに作成します。

```clouds.yml
clouds:
  demo:
    auth:
      auth_url: http://keystone:5000/v2.0
      username: demo
      password: secret
      project_name: demo
```

`auth`の部分は適宜ご自身の環境に合わせて修正してください。2行目の`demo`は、操作対象となるOpenStackテナントを識別する任意の名前です。このファイルには複数のOpenStackテナントを定義できて、例えば`staging`と`production`を定義して、Playbook内で使い分けるということができます。

### Playbook
Playbookを以下の通り作成します。

**ディレクトリ構成**

```
.
├── clouds.yml
├── roles
│   └── openstack
│       └── tasks
│           └── main.yml
└── site.yml
```

```yaml:site.yml
---
- name: create openstack resources
  hosts: 127.0.0.1
  connection: local
  roles:
    - openstack
```

```yaml:main.yml
---
- name: create network
  os_network:
    cloud: demo
    state: present
    name: demo-net

- name: create subnet
  os_subnet:
    cloud: demo
    name: demo-subnet
    network_name: demo-net
    cidr: 10.0.0.0/24
    dns_nameservers: 8.8.8.8
    state: present

- name: create router
  os_router:
    cloud: demo
    name: demo-router
    state: present
    network: publicNW
    interfaces:
      - demo-subnet

- name: create security group
  os_security_group:
    cloud: demo
    state: present
    name: demo-sg

- name: add security group rule
  os_security_group_rule:
    cloud: demo
    state: present
    security_group: demo-sg
    protocol: tcp
    port_range_min: 22
    port_range_max: 22
    remote_ip_prefix: 0.0.0.0/0

- name: create keypair
  os_keypair:
    cloud: demo
    state: present
    name: demo-key
  register: keypair_info

- name: create private key
  copy:
    content: "{{ keypair_info['key']['private_key'] }}"
    dest: ./demo-key-private.pem
    mode: 0600

- name: create instance
  os_server:
    cloud: demo
    state: present
    name: demo-instance
    image: centos7.0
    flavor: 1
    key_name: demo-key
    security_groups: demo-sg
    network: demo-net
    floating_ip_pools: publicNW
```

以下のコマンドでPlaybookを実行します。

```
$ ansible-playbook site.yml
```

Playbookについて簡単に解説します。

まず、起点となる`site.yml`では、`hosts: 127.0.0.1`を指定し、`connection: local`としています。今回はリモートサーバにSSHログインして何か設定を行うというのではなく、Playbookを実行するホストからOpenStack APIを操作するという処理なので、このような書き方になっています。

`main.yml`では、`os_*`というモジュールを使用しており、これがOpenStackモジュールになります。`os_*`モジュールには`cloud`というパラメータがあり、この値の`demo`と`clouds.yml`で記述した`demo`が対応します。`demo`というOpenStackテナントに対してリソースを作成するということです。

各タスクの意味は公式ドキュメントを見ていただければすぐわかると思いますので、解説は割愛します。一点だけ、`create private key`タスクでは、その上の`create keypair`タスクのレスポンスからSSH秘密鍵を取り出して、ローカルに鍵ファイルを作成するという処理を行っています。

## まとめ
Ansible2.0でアップデートされたOpenStackモジュールについて、その概要と簡単な使い方をご紹介しました。Ansibleの適用範囲がインフラにまで広がったことで、Ansible一つでテスト・プロダクション環境構築、オートスケーリング、リリース等のシステムライフサイクル全般を賄うことができそうです。