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なのかなー。移行するほどのメリットは感じられないかなあ。

Leave a Reply

Your email address will not be published. Required fields are marked *