AnsibleでRDSを作成してみる

#はじめに
Ansibleを使ってRDSを起動する方法について調べたので、備忘録的に記事にまとめたいと思います。
前提として、RDSセキュリティグループ、RDSサブネットグループ用のサブネット(×2)はあらかじめ作成済みとします。また、Ansibleに関してもインストール済みとします。(versionはansible 2.3.1.0)

#1. 環境セットアップ
はじめにAWS関連のモジュール実行に必要なパッケージ、boto3をインストールします。

```
sudo pip install boto3
```

#2. プレイブックの作成
下記のディレクトリ構成で、プレイブックを作成していきます。

```
ansible
├── roles
│   └── rds
│       ├── tasks
│       │   ├── main.yml
│       └── vars
│           └── main.yml
├── hosts
├── rds.yml
```

##　①. タスクの定義
ansible/roles/rds/tasks配下に、AWSに対する実行タスクを記載したYamlファイル(main.yml)を作成します。各タスクで実行する内容は下記の通りです。

1. 既存のセキュリティグループ IDの取得
2. 既存のサブネット IDの取得
3. RDSサブネットグループの作成
4. RDSの起動


```yaml:ansible/roles/rds/tasks/main.yml
--- 
# 既存のセキュリティグループ IDの取得タスク
## ec2_group_factsモジュールを使用
- name: "Get Security Group ID"
  ec2_group_facts:
    region: "{{ rds.aws_region }}"
    filters:
      group-name: "{{ rds.security_groups }}"
  register: group_fact

# 既存のサブネット IDの取得
## ec2_vpc_subnet_factsモジュールを使用
- name: "Get VPC Subnet ID 1"
  ec2_vpc_subnet_facts:
    region: "{{ rds.aws_region }}"
    filters:
      "tag:Name": "{{ item.1 }}"
  with_subelements:
    - "{{ rds.subnet_grp }}"
    - subnets
  register: subnet_fact

# RDSサブネットグループの作成
## rds_subnet_groupモジュールを使用
- name: "Make RDS Subnet Group"
  rds_subnet_group:
    state: present
    name: "{{ item.name }}"
    description: My DB Subnet Group
    region: "{{ rds.aws_region }}"
    subnets:
      - "{{ subnet_fact.results[0].subnets[0].id }}"
      - "{{ subnet_fact.results[1].subnets[0].id }}"
  with_items: "{{ rds.subnet_grp }}"

# RDSの起動
## rdsモジュールを使用
- name: "Create RDS Instance"
  rds:
    command: create
    instance_name: "{{ rds.db_name }}"
    username: "{{ rds.db_user }}"
    password: "{{ rds.db_password }}"
    db_name: "{{ rds.db_name }}"
    zone: "{{ rds.aws_zone }}"
    subnet: "{{ subnet_fact.results[0].item[0].name }}"
    region: "{{ rds.aws_region }}"
    vpc_security_groups: "{{ group_fact.security_groups[0].group_id }}"
    db_engine: MySQL
    instance_type: "{{ rds.instance }}"
    size: "{{ rds.size }}"
  register: rds_info
  tags: rds
```

##　②. 変数の定義
ansible/roles/rds/vars配下に、タスク実行に必要な各種パラメータを変数指定したyamlファイル(main.yml)を作成します。

```yaml:ansible/roles/rds/vars/main.yml
---
rds:
   db_name: "testdb"
   db_user: "testuser"
   db_password: "password"
   aws_zone: "ap-northeast-1c"
   aws_region: "ap-northeast-1"
   subnet_grp:
     - name: "db-subnet-group"
       subnets:
         - private-a
         - private-c
   security_groups: "db_server"
   instance: "db.t1.micro"
   size: "20"
```

##　③. ホストファイルの作成
AWSに対してタスクを実行するモジュールは全てローカル上で実行するため、localhostを指定したhostsファイルを用意します。

```yaml:ansible/hosts
[localhost]
127.0.0.1
```

##　④. Playbookの作成
最後にホスト情報、ロールを指定したPlaybookをansible/配下に作成します。

```yaml:ansible/rds.yml
- hosts: localhost
  roles:
    - rds
```

#3. Playbookの実行
下記のコマンドでPlaybook(rds.yml)を指定し、実行します。

```
$ ansible-playbook rds.yml 
 [WARNING]: Host file not found: /etc/ansible/hosts

 [WARNING]: provided hosts list is empty, only localhost is available


PLAY [localhost] ************************************************************************************

TASK [Gathering Facts] ******************************************************************************
ok: [localhost]

TASK [aws : Get Security Group ID] ******************************************************************
ok: [localhost]

TASK [aws : Get VPC Subnet ID 1] ********************************************************************
ok: [localhost] => (item=({u'name': u'db-subnet-group'}, u'private-a'))
ok: [localhost] => (item=({u'name': u'db-subnet-group'}, u'private-c'))

TASK [aws : Make RDS Subnet Group] ******************************************************************
ok: [localhost] => (item={u'subnets': [u'private-a', u'private-c'], u'name': u'db-subnet-group'})

TASK [aws : Create RDS Instance] ********************************************************************
changed: [localhost]

PLAY RECAP ******************************************************************************************
localhost                  : ok=5    changed=1    unreachable=0    failed=0 
```

#4. まとめ
必須となるパラメータを集められれば、なかなか簡易な手順で構築できることがわかりました。今回はAnsibleでRDSの作成を行いましたが、他にもAWSサービスを操作する様々なモジュールが。各種試しながら、AWSサービスの構築自動化につなげていきたいです。

当社ではソフトウェア関連取組みの一環として、クラウド型パフォーマンスモニタサービス「New Relic」を提供しています。詳しくは[こちら](https://newrelic.nissho-ele.co.jp/)。