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?
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.