OpenStack Heat再び
Terraformを使っているのだが、結構困ることもちょこちょこ出てきて、実はHeatの方がよかったのでは?という思いも出てきたりしているのでもうちょっと実践的な検証を行うことにした。OpenStackのバージョンはMitaka。
今回は、スケールさせるインスタンス群とそうではないシングルインスタンスを作成し、シングルインスタンスにはFloatingIPを付与する、という構成にする。インスタンス一覧はこのようになっている。
Every 2.0s: openstack server list takaishiryou-no-iMac.local: Mon Apr 17 22:14:28 2017
+--------------------------------------+----------------------+--------+----------------------------------------+------------+
| ID | Name | Status | Networks | Image Name |
+--------------------------------------+----------------------+--------+----------------------------------------+------------+
| a87e1500-2539-4998-85e4-b1f42a2c7f62 | scale-10.8.1.4 | ACTIVE | alpaca-internal=10.8.1.4 | cirros |
| d60adfe6-148b-48fc-a9de-61c553c16837 | scale-10.8.1.6 | ACTIVE | alpaca-internal=10.8.1.6 | cirros |
| c4cec0c2-3faf-4ecf-836d-71b17051ba02 | scale-10.8.1.7 | ACTIVE | alpaca-internal=10.8.1.7 | cirros |
| 999d6f7e-4e50-4c42-be5e-66149a0a92d5 | no-scalable-10.8.1.5 | ACTIVE | alpaca-internal=10.8.1.5, 172.24.4.233 | cirros |
+--------------------------------------+----------------------+--------+----------------------------------------+------------+
各リソースについて
main.yaml
メインはこのようになる。リソースはネットワーク類、スケールインスタンス、シングルインスタンス、シングルインスタンスへのFIP付与だ。パラメータとしては、スケールインスタンスの台数を指定できるようにしている。
heat_template_version: 2016-04-08
description: テストだよ。
parameters:
instance_count:
type: number
label: Instance Count
default: 3
resources:
alpaca_internal:
type: OS::Alpaca::Network
scalable_instances:
type: OS::Alpaca::ServerGroup
properties:
name: scale
count: { get_param: instance_count }
network: { get_attr: [alpaca_internal, network] }
single_instance:
type: OS::Alpaca::Server
properties:
name: no-scalable
network: { get_attr: [alpaca_internal, network] }
test_attach_fip:
type: OS::Alpaca::AttachFloatingIP
properties:
server: { get_attr: [single_instance, server_id] }
ここで、”OS::Alpaca::Network” や “OS::Alpaca::Server” というタイプがあるが、これは独自に定義したリソースだ。Terraformのモジュールに似た機能といってよいだろう。独自定義リソースを使うには、”env.yaml”でリソース名とそれを定義したファイルを関連づける。詳細はドキュメントを参照するとよい。なお、拡張子が”.yml”だとうまく動かなかった。”.yaml”じゃないとダメなようだ。
resource_registry:
"OS::Alpaca::Network": ./os_alpaca_network.yaml
"OS::Alpaca::Server": ./os_alpaca_server.yaml
"OS::Alpaca::AttachFloatingIP": ./os_alpaca_attachfloatingip.yaml
"OS::Alpaca::ServerGroup": ./os_alpaca_servergroup.yaml
OS::Alpaca::Network
必要なネットワークリソースを1つのリソースに定義した。素朴にネットワークとサブネットを作成し、Publicネットワークとはルーターを経由して接続している。
outputsでネットワークを参照できるようにしているが、これはサーバー作成時にネットワークの情報が必要なためだ。
heat_template_version: 2016-04-08
description: ネットワークだよ
resources:
my_net:
type: OS::Neutron::Net
properties:
name: alpaca-internal
my_subnet:
type: OS::Neutron::Subnet
properties:
network_id: { get_resource: my_net }
cidr: "10.8.1.0/24"
dns_nameservers: ["8.8.8.8", "8.8.4.4"]
ip_version: 4
router:
type: OS::Neutron::Router
properties:
external_gateway_info: { network: public }
my_subnet_interface:
type: OS::Neutron::RouterInterface
properties:
router_id: { get_resource: router }
subnet: { get_resource: my_subnet }
outputs:
network:
value: { get_resource: my_net }
OS::Alpaca::Server
次はサーバーだ。サービスで使うベースのインスタンスはって大体設定が共通なので、独自リソースで定義しておくと楽だ。サーバーにユニークな名前をつけようと思って、付与するIPアドレスを用いて「hoge-127-0-0-1」のような名前にしたかったが、うまくいかなかった。get_attrの結果を置換する方法が今のところないようだ。Terraformだと可能なのだが。
heat_template_version: 2016-04-08
description: インスタンスを定義するよ
parameters:
name:
type: string
default: "aaa"
network:
type: string
resources:
port:
type: OS::Neutron::Port
properties:
network: { get_param: network }
server:
type: OS::Nova::Server
properties:
name: { list_join: ['-', [{ get_param: name }, { get_attr: [port, fixed_ips, 0, ip_address] } ] ] }
key_name: r_takaishi
image: cirros
flavor: m1.tiny
networks:
- port: { get_resource: port }
outputs:
server_id:
value: { get_resource: server }
OS::Alpaca::AttachFloatingIP
次はサーバーにFIPを付与するためのリソース。本当は、OS::Alpaca::Serverのパラメータで「attach_fip: true」のようにするとFIPを付与するようにしたかったが、Mitakaだとconditionが使えなかった。newtonかららしい…これもTerraformだとできるので、Newtonにしたい〜!という気持ちになる。
heat_template_version: 2016-04-08
description: サーバーにFIPをアタッチするよ
parameters:
server:
type: string
resources:
floating_ip:
type: OS::Nova::FloatingIP
properties:
pool: public
association:
type: OS::Nova::FloatingIPAssociation
properties:
floating_ip: { get_resource: floating_ip }
server_id: { get_param: server }
OS::Alpaca::ServerGroup
最後はスケールさせるための独自リソース。OS::Heat::ResourceGroupとOS::Alpaca::Serverを組み合わせて、DRYにスケールさせるための記述を成立できた。これは今のところTerraformではできないことだ。
heat_template_version: 2016-04-08
description: 複数台のサーバーを管理する君
parameters:
count:
type: number
default: 1
name:
type: string
default: aaa
network:
type: string
resources:
instances:
type: OS::Heat::ResourceGroup
update_policy: {
rolling_update: { "min_in_service": 1, "max_batch_size": 2, "pause_time": 5}
}
properties:
count: { get_param: count }
resource_def:
type: OS::Alpaca::Server
properties:
name: { get_param: name }
network: { get_param: network }
まとめと感想
より実際に使いそうな記述でHeatを使ってみた。次はCloudConfigを試すかなー。
- 実行した時の差分がよくわからない。どう変化するのかがもうちょっとわかりやすく見られるとよいのだが…何かコマンドがあるのだろうか。サーバーが再作成されるのかどうかというのも分からないので実行が不安になる。
- Horizonから実行履歴が見られるのはよい。
- TerraformからHeatへ移行する場合、かなり運用フローを変えないといけないだろうと感じた。Heatを用いて複数人で開発するのはどうやるんだろう?
うーん、使ってみたらやはりTerraformなのかなー。移行するほどのメリットは感じられないかなあ。