[openstack-dev] [Heat] rough draft of Heat autoscaling API

Zane Bitter zbitter at redhat.com
Mon Nov 25 19:31:05 UTC 2013


Top-posting *and* replying to myself today :D

I realised that I could have implemented this in less time than I've 
spent arguing about it already, so I did:

https://review.openstack.org/#/c/58357/
https://review.openstack.org/#/c/58358/

cheers,
Zane.


On 19/11/13 23:27, Zane Bitter wrote:
> On 19/11/13 19:14, Christopher Armstrong wrote:
>> On Mon, Nov 18, 2013 at 5:57 AM, Zane Bitter <zbitter at redhat.com
>> <mailto:zbitter at redhat.com>> wrote:
>>
>>     On 16/11/13 11:15, Angus Salkeld wrote:
>>
>>         On 15/11/13 08:46 -0600, Christopher Armstrong wrote:
>>
>>             On Fri, Nov 15, 2013 at 3:57 AM, Zane Bitter
>>             <zbitter at redhat.com <mailto:zbitter at redhat.com>> wrote:
>>
>>                 On 15/11/13 02:48, Christopher Armstrong wrote:
>>
>>                     On Thu, Nov 14, 2013 at 5:40 PM, Angus Salkeld
>>                     <asalkeld at redhat.com <mailto:asalkeld at redhat.com>
>>                     <mailto:asalkeld at redhat.com
>>                     <mailto:asalkeld at redhat.com>>> wrote:
>>
>>                          On 14/11/13 10:19 -0600, Christopher Armstrong
>>                     wrote:
>>
>>                     http://docs.heatautoscale.__ap__iary.io/
>>                     <http://apiary.io/>
>>
>>                              <http://docs.heatautoscale.__apiary.io/
>>                     <http://docs.heatautoscale.apiary.io/>>
>>
>>                              I've thrown together a rough sketch of the
>>                     proposed API for
>>                              autoscaling.
>>                              It's written in API-Blueprint format (which
>>                     is a simple subset
>>                              of Markdown)
>>                              and provides schemas for inputs and outputs
>>                     using JSON-Schema.
>>                              The source
>>                              document is currently at
>>                     https://github.com/radix/heat/____raw/as-api-spike/
>>                     <https://github.com/radix/heat/__raw/as-api-spike/>
>>                     autoscaling.__apibp
>>
>>
>>
>> <https://github.com/radix/__heat/raw/as-api-spike/__autoscaling.apibp
>>
>> <https://github.com/radix/heat/raw/as-api-spike/autoscaling.apibp>
>>                      >
>>
>>
>>                              Things we still need to figure out:
>>
>>                              - how to scope projects/domains. put them
>>                     in the URL? get them
>>                              from the
>>                              token?
>>                              - how webhooks are done (though this
>>                     shouldn't affect the API
>>                              too much;
>>                              they're basically just opaque)
>>
>>                              Please read and comment :)
>>
>>
>>                          Hi Chistopher
>>
>>                          In the group create object you have 'resources'.
>>                          Can you explain what you expect in there? I
>>                     thought we talked at
>>                          summit about have a unit of scaling as a nested
>>                     stack.
>>
>>                          The thinking here was:
>>                          - this makes the new config stuff easier to
>>                     scale (config get
>>                     applied
>>                          Â  per scaling stack)
>>
>>                          - you can potentially place notification
>>                     resources in the scaling
>>                          Â  stack (think marconi message resource -
>>                     on-create it sends a
>>                          Â  message)
>>
>>                          - no need for a launchconfig
>>                          - you can place a LoadbalancerMember resource
>>                     in the scaling stack
>>                          Â  that triggers the loadbalancer to add/remove
>>                     it from the lb.
>>
>>
>>                          I guess what I am saying is I'd expect an api
>>                     to a nested stack.
>>
>>
>>                     Well, what I'm thinking now is that instead of
>>                     "resources" (a
>>                     mapping of
>>                     resources), just have "resource", which can be the
>>                     template definition
>>                     for a single resource. This would then allow the
>>                     user to specify a
>>                     Stack
>>                     resource if they want to provide multiple resources.
>>                     How does that
>>                     sound?
>>
>>
>>                 My thought was this (digging into the implementation
>>                 here a bit):
>>
>>                 - Basically, the autoscaling code works as it does now:
>>                 creates a
>>                 template
>>                 containing OS::Nova::Server resources (changed from
>>                 AWS::EC2::Instance),
>>                 with the properties obtained from the LaunchConfig, and
>>                 creates a
>>                 stack in
>>                 Heat.
>>                 - LaunchConfig can now contain any properties you like
>>                 (I'm not 100%
>>                 sure
>>                 about this one*).
>>                 - The user optionally supplies a template. If the
>>                 template is
>>                 supplied, it
>>                 is passed to Heat and set in the environment as the
>>                 provider for the
>>                 OS::Nova::Server resource.
>>
>>
>>             I don't like the idea of binding to OS::Nova::Server
>>             specifically for
>>             autoscaling. I'd rather have the ability to scale *any*
>>             resource,
>>             including
>>             nested stacks or custom resources. It seems like jumping
>>             through hoops to
>>
>>
>>         big +1 here, autoscaling should not even know what it is
>>         scaling, just
>>         some resource. solum might want to scale all sorts of non-server
>>         resources (and other users).
>>
>>
>>     I'm surprised by the negative reaction to what I suggested, which is
>>     a completely standard use of provider templates. Allowing a
>>     user-defined stack of resources to stand in for an unrelated
>>     resource type is the entire point of providers. Everyone says that
>>     it's a great feature, but if you try to use it for something they
>>     call it a "hack". Strange.
>>
>>
>> To clarify this position (which I already did in IRC), replacing one
>> concrete resource with another that means something in a completely
>> different domain is a hack -- say, replacing "server" with "group of
>> related resources". However, replacing OS::Nova::Server with something
>> which still does something very much like creating a server is
>> reasonable -- e.g., using a different API like one for creating
>> containers or using a different cloud provider's API.
>
> Sure, but at the end of the day it's just a name that is used internally
> and which a user would struggle to even find referenced anywhere (I
> think if they look at the resources created by the autoscaling template
> it *might* show up). The name is completely immaterial to the idea, as
> demonstrated below where I did a straight string substitution (1 line in
> the environment) for a better name and nothing changed.
>
>>     So, allow me to make a slight modification to my proposal:
>>
>>     - The autoscaling service manages a template containing
>>     OS::Heat::ScaledResource resources. This is an imaginary resource
>>     type that is not backed by a plugin in Heat.
>>     - If no template is supplied by the user, the environment declares
>>     another resource plugin as the provider for OS::Heat::ScaledResource
>>     (by default it would be OS::Nova::Server, but this should probably
>>     be configurable by the deployer... so if you had a region full of
>>     Docker containers and no Nova servers, you could set it to
>>     OS::Docker::Container or something).
>>     - If a provider template is supplied by the user, it would be
>>     specified as the provider in the environment file.
>>
>>     This, I hope, demonstrates that autoscaling needs no knowledge
>>     whatsoever about what it is scaling to use this approach.
>>
>>
>> It'd be interesting to see some examples, I think. I'll provide some
>> examples of my proposals, with the following caveats:
>
> Excellent idea, thanks :)
>
>> - I'm assuming a separation of launch configuration from scaling group,
>> as you proposed -- I don't really have a problem with this.
>> - I'm also writing these examples with the plural "resources" parameter,
>> which there has been some bikeshedding around - I believe the structure
>> can be the same whether we go with singular, plural, or even
>> whole-template-as-a-string.
>>
>> # trivial example: scaling a single server
>>
>> POST /launch_configs
>>
>> {
>>      "name": "my-launch-config",
>>      "resources": {
>>          "my-server": {
>>              "type": "OS::Nova::Server",
>>              "properties": {
>>                  "image": "my-image",
>>                  "flavor": "my-flavor", # etc...
>>              }
>>          }
>>      }
>> }
>
> This case would be simpler with my proposal, assuming we allow a default:
>
>   POST /launch_configs
>
>   {
>        "name": "my-launch-config",
>        "parameters": {
>            "image": "my-image",
>            "flavor": "my-flavor", # etc...
>        }
>   }
>
> If we don't allow a default it might be something more like:
>
>
>   POST /launch_configs
>
>   {
>        "name": "my-launch-config",
>        "parameters": {
>            "image": "my-image",
>            "flavor": "my-flavor", # etc...
>        },
>        "provider_template_uri":
> "http://heat.example.com/<tenant_id>/resources_types/OS::Nova::Server/template"
>
>   }
>
>
>> POST /groups
>>
>> {
>>      "name": "group-name",
>>      "launch_config": "my-launch-config",
>>      "min_size": 0,
>>      "max_size": 0,
>> }
>
> This would be the same.
>
>>
>> (and then, the user would continue on to create a policy that scales the
>> group, etc)
>>
>> # complex example: scaling a server with an attached volume
>>
>> POST /launch_configs
>>
>> {
>>      "name": "my-launch-config",
>>      "resources": {
>>          "my-volume": {
>>              "type": "OS::Cinder::Volume",
>>              "properties": {
>>                  # volume properties...
>>              }
>>          },
>>          "my-server": {
>>              "type": "OS::Nova::Server",
>>              "properties": {
>>                  "image": "my-image",
>>                  "flavor": "my-flavor", # etc...
>>              }
>>          },
>>          "my-volume-attachment": {
>>              "type": "OS::Cinder::VolumeAttachment",
>>              "properties": {
>>                  "volume_id": {"get_resource": "my-volume"},
>>                  "instance_uuid": {"get_resource": "my-server"},
>>                  "mountpoint": "/mnt/volume"
>>              }
>>          }
>>      }
>> }
>
> This appears slightly more complex on the surface; I'll explain why in a
> second.
>
>   POST /launch_configs
>
>   {
>        "name": "my-launch-config",
>        "parameters": {
>            "image": "my-image",
>            "flavor": "my-flavor", # etc...
>        }
>        "provider_template": {
>            "hot_format_version": "some random date",
>            "parameters" {
>                "image_name": {
>                    "type": "string"
>                },
>                "flavor": {
>                    "type": "string"
>                } # &c. ...
>            },
>            "resources" {
>                "my-volume": {
>                    "type": "OS::Cinder::Volume",
>                    "properties": {
>                        # volume properties...
>                    }
>                },
>                "my-server": {
>                    "type": "OS::Nova::Server",
>                    "properties": {
>                        "image": {"get_param": "image_name"},
>                        "flavor": {"get_param": "flavor"}, # etc...
>                   }
>                },
>                "my-volume-attachment": {
>                    "type": "OS::Cinder::VolumeAttachment",
>                    "properties": {
>                        "volume_id": {"get_resource": "my-volume"},
>                        "instance_uuid": {"get_resource": "my-server"},
>                        "mountpoint": "/mnt/volume"
>                    }
>                }
>            },
>            "outputs" {
>                 "public_ip_address": {
>                     "Value": {"get_attr": ["my-server",
> "public_ip_address"]} # &c. ...
>            }
>        }
>   }
>
> (BTW the template could just as easily be included in the group rather
> than the launch config. If we put it here we can validate the parameters
> though.)
>
> There are a number of advantages to including the whole template, rather
> than a resource snippet:
>   - Templates are versioned!
>   - Templates accept parameters
>   - Templates can provide outputs - we'll need these when we go to do
> notifications (e.g. to load balancers).
>
> The obvious downside is there's a lot of fiddly stuff to include in the
> template (hooking up the parameters and outputs), but this is almost
> entirely mitigated by the fact that the user can get a template, ready
> built with the server hooked up, from the API by hitting
> /resource_types/OS::Nova::Server/template and just edit in the Volume
> and VolumeAttachment. (For a different example, they could of course
> begin with a different resource type - the launch config accepts any
> keys for parameters.) To the extent that this encourages people to write
> templates where the outputs are actually supplied, it will help reduce
> the number of people complaining their load balancers aren't forwarding
> any traffic because they didn't surface the IP addresses.
>
>>
>> (and so on, creating the group and policies in the same way).
>
> ditto.
>
>> Can you please provide an example of your proposal for the same use
>> cases? Please indicate how you'd specify the custom properties for each
>> resource and how you specify the provider template in the API.
>
> As you can see, it's not really different, just an implementation
> strategy where all the edge cases have already been worked out, and all
> the parts already exist.
>
> cheers,
> Zane.
>
> _______________________________________________
> OpenStack-dev mailing list
> OpenStack-dev at lists.openstack.org
> http://lists.openstack.org/cgi-bin/mailman/listinfo/openstack-dev




More information about the OpenStack-dev mailing list