Scaling IIS8 on OpenStack

Posted: March 21, 2015 in Cloud Computing, Cool Projects, Heat, OpenStack
Tags: , , ,

I was recently asked to show an example of how Windows Server 2012 running Internet Information Service (IIS) 8 can scale out in an OpenStack environment. I accepted the challenge and this post is the result.  To accomplish the task, I did a default install of an evaluation version of Windows Server 2012 and installed/configured IIS8 along with ASP.net support.  I then created a very simple web page that uses server variables and the current date an time to create some dynamic content.  Lastly, I installed the CloudBase Cloud-Init service so that Windows Server could talk to the OpenStack metadata service.  I hope you enjoy the video.
The Heat template that was used for the deployment is below along with the Load Balancer Heat file (lb_server.yaml) that must be located somewhere that it can be retrieved during the build process.  For my installation I hosted the lb_server.yaml file on another web server using the configuration parameter “type” found on line 45 of the Windows IIS Scaling Heat Template file.

heat_template_version: 2013-05-23

description: >
  HOT template to deploy two servers into an existing neutron tenant network and
  assign floating IP addresses to each server so they are routable from the
  public network.

parameters:
  key_name:
    type: string
    description: Name of keypair to assign to servers
  image:
    type: string
    description: Name of image to use for servers
    default: WinServer2k12
    constraints:
      - allowed_values: [ WinServer2k12 ]
        description: Image ID must be WinServer2k12
  flavor:
    type: string
    description: Flavor to use for servers
    default: m1.medium
    constraints:
      - allowed_values: [m1.small, m1.medium]
  public_net_id:
    type: string
    description: ID of public network for which floating IP addresses will be allocated
    default: 49ec0493-c5cd-409f-a124-089eaaa9e231
  private_net_id:
    type: string
    description: ID of private network into which servers get deployed
    default: 23c19763-dcf8-4110-9b86-9ff114109177
  private_subnet_id:
    type: string
    description: ID of private sub network into which servers get deployed
    default: cb95f1da-87aa-4b8a-b547-e552fe9eafc9

resources:
  iis_server_group:
    type: OS::Heat::AutoScalingGroup
    properties:
      min_size: 1
      max_size: 3
      resource:
        type: http://192.168.200.101/lb_server.yaml
        properties:
          flavor: {get_param: flavor}
          image: {get_param: image}
          key_name: {get_param: key_name}
          pool_id: {get_resource: pool}
          metadata: {"metering.stack": {get_param: "OS::stack_id"}}
          user_data: RAW

  iis_server_scaleup_policy:
    type: OS::Heat::ScalingPolicy
    properties:
      adjustment_type: change_in_capacity
      auto_scaling_group_id: {get_resource: iis_server_group}
      cooldown: 60
      scaling_adjustment: 1

  iis_server_scaledown_policy:
    type: OS::Heat::ScalingPolicy
    properties:
      adjustment_type: change_in_capacity
      auto_scaling_group_id: {get_resource: iis_server_group}
      cooldown: 60
      scaling_adjustment: -1

  net_alarm_high:
    type: OS::Ceilometer::Alarm
    properties:
      description: Scale-up if outgoing traffic > 35000 Bytes over 1 minute
      meter_name: network.outgoing.bytes.rate
      statistic: avg
      period: 60
      evaluation_periods: 1
      threshold: 35
      alarm_actions:
        - {get_attr: [iis_server_scaleup_policy, alarm_url]}
      matching_metadata: {'metadata.user_metadata.stack': {get_param: "OS::stack_id"}}
      comparison_operator: gt

  net_alarm_low:
    type: OS::Ceilometer::Alarm
    properties:
      description: Scale-down if outgoing traffic < 10000 Bytes over 2 minutes
      meter_name: network.outgoing.bytes.rate
      statistic: avg
      period: 120
      evaluation_periods: 1
      threshold: 10
      alarm_actions:
        - {get_attr: [iis_server_scaledown_policy, alarm_url]}
      matching_metadata: {'metadata.user_metadata.stack': {get_param: "OS::stack_id"}}
      comparison_operator: lt
  
  lb_vip_port:
    type: OS::Neutron::Port
    properties:
      network_id: { get_param: private_net_id }
      fixed_ips:
        - subnet_id: { get_param: private_subnet_id }

  lb_vip_floating_ip:
    type: OS::Neutron::FloatingIP
    properties:
      floating_network_id: { get_param: public_net_id }  
      port_id: { get_resource: lb_vip_port }

  lb_pool_vip:
    type: OS::Neutron::FloatingIPAssociation
    properties:
      floatingip_id: { get_resource: lb_vip_floating_ip }
      port_id: { 'Fn::Select': ['port_id', {get_attr: [pool, vip]}]}

  monitor:
    type: OS::Neutron::HealthMonitor
    properties:
      type: TCP
      delay: 5
      max_retries: 5
      timeout: 5

  pool:
    type: OS::Neutron::Pool
    properties:
      protocol: HTTP
      monitors: [{get_resource: monitor}]
      subnet_id: {get_param: private_subnet_id}
      lb_method: ROUND_ROBIN
      vip:
        protocol_port: 80
        ## session_persistence:
        ##   type: SOURCE_IP

  lb:
    type: OS::Neutron::LoadBalancer
    properties:
      protocol_port: 80
      pool_id: {get_resource: pool}
outputs:
  WebsiteURL:
    description: URL for IIS demo page
    value:
      str_replace:
        template: http://host/demo.aspx
        params:
          host: { get_attr: [lb_vip_floating_ip, floating_ip_address] }
heat_template_version: 2013-05-23
description: A load-balancer server
parameters:
  image:
    type: string
    description: Image used for servers
  key_name:
    type: string
    description: SSH key to connect to the servers
  flavor:
    type: string
    description: flavor used by the servers
  pool_id:
    type: string
    description: Pool to contact
  user_data:
    type: string
    description: Server user_data
  metadata:
    type: json
resources:
  server:
    type: OS::Nova::Server
    properties:
      flavor: {get_param: flavor}
      image: {get_param: image}
      key_name: {get_param: key_name}
      metadata: {get_param: metadata}
      user_data: {get_param: user_data}
      user_data_format: RAW
  member:
    type: OS::Neutron::PoolMember
    properties:
      pool_id: {get_param: pool_id}
      address: {get_attr: [server, first_address]}
      protocol_port: 80

There is no customization going on in the template at all. All I was using it for was the determine when to add more instances to handle the traffic load. Additional Windows Heat templates (that do a lot more stuff) can be found on GitHub.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s