OpenStack: Heatを使ってインスタンスを複数生成する

# 1. 複数のインスタンスを生成するスタック
WebサーバとDBサーバを構築を自動で構築するスタックを作成する。

#### 1.1. テンプレート作成

```test2_stack.yaml
#HOTテンプレートのバージョン
heat_template_version: 2013-05-23

#テンプレートに対するコメント
description: >
 This template installs two instances: 

#パラメータセクション。入力パラメータを定義。
parameters:

  #テンプレートで利用するキーペアの名称
  key_name:
    type: string
    description : Name of a KeyPair to enable SSH access to the instance
    default: yotsu_key

  #テンプレートで利用するインスタンスタイプ
  instance_type:
    type: string
    description: Instance type for web and DB servers
    default: m1.small
    constraints: ##入力可能なパラメータの値を制限
      - allowed_values: [m1.tiny, m1.small, m1.medium, m1.large, m1.xlarge]
        description: instance_type must be a valid instance type

  #テンプレート利用するNetwork ID
  net_id:
    type: string
    description: Network ID
    default: 71c9dc17-cc66-45c6-9892-f5aecafce27c

  #利用するイメージID
  image_id:
    type: string
    description: >
      Name or ID of the image to use for the WordPress server.
    default: centos7

  #DB
  db_name:
    type: string
    description: WordPress database name
    default: wordpress #デフォルトのDB名
    constraints: #制限
      - length: { min: 1, max: 64 } #文字数を制限
        description: db_name must be between 1 and 64 characters
      - allowed_pattern: '[a-zA-Z][a-zA-Z0-9]*' #文字のパターンを制限
        description: >
          db_name must begin with a letter and contain only alphanumeric
          characters
  db_username:
    type: string
    description: The WordPress database admin account username
    default: admin
    hidden: true
    constraints: #制限
      - length: { min: 1, max: 16 }
        description: db_username must be between 1 and 16 characters
      - allowed_pattern: '[a-zA-Z][a-zA-Z0-9]*' #文字のパターンを制限
        description: >
          db_username must begin with a letter and contain only alphanumeric characters
  db_password:
    type: string
    description: The WordPress database admin account password
    default: admin
    hidden: true #パスワードなので隠す
    constraints:
      - length: { min: 1, max: 41 }
        description: db_password must be between 1 and 41 characters
      - allowed_pattern: '[a-zA-Z0-9]*'
        description: db_password must contain only alphanumeric characters

  db_root_password: #DBのrootパスワード
    type: string
    description: Root password for MySQL
    default: admin
    hidden: true
    constraints: #制限
      - length: { min: 1, max: 41 } #長さ
        description: db_root_password must be between 1 and 41 characters
      - allowed_pattern: '[a-zA-Z0-9]*' #許可パターン
        description: db_root_password must contain only alphanumeric characters

#リソースセクション
resources: #DBサーバとWebサーバ、2台のインスタンスを生成
  database_server:
    type: OS::Nova::Server
    properties:
      image: { get_param: image_id }
      flavor: { get_param: instance_type }
      key_name: { get_param: key_name }
      networks:
        - network: { get_param: net_id }
      user_data: #インスタンス起動時に実行されるスクリプトを記述
        str_replace: #動的にtemplateの内容をpramsで指定した値に置換する
          template: | #placeholderを含むテンプレートを定義
            #!/bin/bash -v

            yum -y clean all
            yum -y install mariadb mariadb-server
            touch /var/log/mariadb/mariadb.log
            chown mysql.mysql /var/log/mariadb/mariadb.log
            systemctl start mariadb.service

            # Setup MySQL root password and create a user
            mysqladmin -u root password db_rootpassword
            cat << EOF | mysql -u root --password=db_rootpassword
            CREATE DATABASE db_name;
            GRANT ALL PRIVILEGES ON db_name.* TO "db_user"@"%"
            IDENTIFIED BY "db_password";
            FLUSH PRIVILEGES;
            EXIT
            EOF
          params: #パラメータマッピング
            db_rootpassword: { get_param: db_root_password }
            db_name: { get_param: db_name }
            db_user: { get_param: db_username }
            db_password: { get_param: db_password }

  web_server:
    type: OS::Nova::Server
    properties:
      image: { get_param: image_id }
      flavor: { get_param: instance_type }
      key_name: { get_param: key_name }
      networks:
        - network: { get_param: net_id }
      user_data:
        str_replace:
          template: |
            #!/bin/bash -v

            yum -y clean all
            yum -y install httpd wordpress

            sed -i "/Deny from All/d" /etc/httpd/conf.d/wordpress.conf
            sed -i "s/Require local/Require all granted/" /etc/httpd/conf.d/wordpress.conf
            sed -i s/database_name_here/db_name/ /etc/wordpress/wp-config.php
            sed -i s/username_here/db_user/      /etc/wordpress/wp-config.php
            sed -i s/password_here/db_password/  /etc/wordpress/wp-config.php
            sed -i s/localhost/db_ipaddr/        /etc/wordpress/wp-config.php
            setenforce 0 # Otherwise net traffic with DB is disabled
            systemctl start httpd.service
          params:
            db_rootpassword: { get_param: db_root_password }
            db_name: { get_param: db_name }
            db_user: { get_param: db_username }
            db_password: { get_param: db_password }
            db_ipaddr: { get_attr: [database_server, networks, private, 0] }
```

#### 1.2. スタックの作成と動作確認
スタックを作成

```
# heat stack-create -f test2-stack.yml Test2-Stack
```

作成したスタックを確認

```
# heat stack-list
+--------------------------------------+-------------+-----------------+----------------------+
| id                                   | stack_name  | stack_status    | creation_time        |
+--------------------------------------+-------------+-----------------+----------------------+
| c976cc37-b392-4b1a-a2c7-458b1b50ae26 | TestStack   | CREATE_COMPLETE | 2015-07-07T05:28:58Z |
| 6f33a033-10c4-4e09-849e-020e4c0c8d06 | Test2-Stack | CREATE_COMPLETE | 2015-07-07T08:02:31Z |
+--------------------------------------+-------------+-----------------+----------------------+
```

インスタンスが起動していることを確認

```
# nova list
+--------------------------------------+------------------------------------------+--------+------------+-------------+----------------------+
| ID                                   | Name                                     | Status | Task State | Power State | Networks             |
+--------------------------------------+------------------------------------------+--------+------------+-------------+----------------------+
| 903149cf-f0da-47ac-aa1d-7225d0e94721 | Test2-Stack-database_server-yi2a6qcxpjbp | ACTIVE | -          | Running     | private=192.168.1.37 |
| 067fab1d-9828-40ea-8bc6-2fdfa7241713 | Test2-Stack-web_server-srjh3zgnwvar      | ACTIVE | -          | Running     | private=192.168.1.38 |
+--------------------------------------+------------------------------------------+--------+------------+-------------+----------------------+
```

virshでも確認してみる

```
# virsh list
 Id    Name                           State
----------------------------------------------------
 6     instance-0000001a              running
 7     instance-0000001b              running
```

ライフサイクルイベントを表示

```
# heat event-list 6f33a033-10c4-4e09-849e-020e4c0c8d06
+-----------------+--------------------------------------+------------------------+--------------------+----------------------+
| resource_name   | id                                   | resource_status_reason | resource_status    | event_time           |
+-----------------+--------------------------------------+------------------------+--------------------+----------------------+
| database_server | edf63796-4f68-4f63-b303-9021d92c1e42 | state changed          | CREATE_IN_PROGRESS | 2015-07-07T08:02:32Z |
| database_server | 0dafbabd-6d3b-4ec0-81d6-0f73ec200992 | state changed          | CREATE_COMPLETE    | 2015-07-07T08:02:54Z |
| web_server      | a5516f8a-ecd4-4310-89ab-cab912b07ce8 | state changed          | CREATE_IN_PROGRESS | 2015-07-07T08:02:54Z |
| web_server      | 552393a3-262d-4611-aaec-58340271644f | state changed          | CREATE_COMPLETE    | 2015-07-07T08:03:06Z |
+-----------------+--------------------------------------+------------------------+--------------------+----------------------+
```

#### 1.3. スタックの削除
スタックを削除すると、作成したインスタンスが削除される。

```
# heat stack-delete Test2-Stack
# heat stack-list
+----+------------+--------------+---------------+
| id | stack_name | stack_status | creation_time |
+----+------------+--------------+---------------+
+----+------------+--------------+---------------+
[root@elephant templates(keystone_yotsu)]# nova list
+----+------+--------+------------+-------------+----------+
| ID | Name | Status | Task State | Power State | Networks |
+----+------+--------+------------+-------------+----------+
+----+------+--------+------------+-------------+----------+
```