2

I have an instance resource along these lines:

 masters:
type: OS::Heat::ResourceGroup
properties:
  count: { get_param: num_masters }
  resource_def:
    type: heat_stack_server.yaml
    properties:
      name:
        str_replace:
          template: cluster_id-k8s_type-%index%
          params:
            cluster_id: { get_param: cluster_id }
            k8s_type: master
      cluster_env: { get_param: cluster_env }
      cluster_id:  { get_param: cluster_id }
      type:        master
      image:       { get_param: master_image }
      flavor:      { get_param: master_flavor }
      key_name:    { get_resource: keypair }
      net:         { get_resource: net }
      subnet:      { get_resource: subnet }
      secgrp:
        - { get_resource: master-secgrp }
        - { get_resource: node-secgrp }
      floating_network: { get_param: external_net }
      net_name:
        str_replace:
          template: openshift-ansible-cluster_id-net
          params:
            cluster_id: { get_param: cluster_id }
depends_on:
  - interface

It creates num_masters. Now, I want to guarantee these masters will be created in different availability zones (so that when one of them fails, the other will continue to work).

Say, I have 3 AZ and num_masters == 5. How to spread them, so that zone1 contains nodes 1 and 4, zone2 - 2 and 5, and so on?

Ansible has that loop.cycle thing where you could pass over a list of options over and over. Any ideas how to do it in OS?

Undespairable
  • 203
  • 1
  • 11

1 Answers1

1

OK, I found a solution. I see that someone ticked my question up, so I understand that there's someone else searching for a solution, so I'd better share mine.

You rarely use (and I certainly don't) Heat in isolation from other Configuration Management frameworks. I use it alongside Ansible. So in order to spread nodes between availability zones (AZ) you may consider to prepare this spread yourself. First, I have in my Ansible vars file a list of all AZ available (sorry for the pun):

zones:
 - 'zone1'
 - 'zone2'

Alternatively, you can query Openstack for that list. When you have it, you fill it into the environment file of your stack like this:

{% set zone_cycler = cycler( *zones ) %}
master_availability_zones: [{% for n in range(1,master_number+1) %}"{{ zone_cycler.next() }}"{% if not loop.last %}{{','}} {% endif %}{% endfor %}]

So for five hosts and two zones you'll get this:

master_availability_zones: ["zone1","zone2","zone1","zone2","zone1"]

Then you pass this list into your host resource group like this:

  master_availability_zones:
    type: comma_delimited_list
    label: Master Availability zones
    description: Availability zone mapping for masters

  master_nodes:
    type: OS::Heat::ResourceGroup
    properties:
      count: { get_param: master_number }
      resource_def:
        type: master_template.yaml
        properties:
          ...
          availability_zones: { get_param: master_availability_zones }
          index: "%index%"
          ...

Don't forget to pass along index variable as well, you'll need it on the other side, in master_template.yaml:

  master_node:
    type: OS::Nova::Server
    properties:
      ...
      availability_zone: { get_param: [ availability_zones, { get_param: index } ] }
      ...

Voila, you now have scalable procedure accomodating for arbitrary host and zone numbers.

Undespairable
  • 203
  • 1
  • 11
  • If heat supported some basic math functions, like the mod function, it wouldn't be necessary to repeat the AZs. Instead the index could be the current index mod number_of_azs. – Daniel Watrous Jun 20 '16 at 15:07
  • It could be easier still in that case: you just make your zone name a template and fill zone number as the ```index mod az_number``` – Undespairable Jun 20 '16 at 16:08