Bug Reference

 https://issues.apache.org/jira/browse/CLOUDSTACK-739

Branch

Work is in progress on the affinity_groups branch

Introduction

Purpose

As part of cloud orchestration there is always a need for cloud admins and users to be able to judiciously place the VMs to ensure better availability of their service. Cloudstack API ‘deployVirtualMachine’ lets you specify the compute/disk tags to choose a specific compute host/storage during VM placement.

But currently, there is no way for a user to let CloudStack know how to place a certain VM in relationship to other already existing VMs in the account.

Following are some real life use cases that indicate the need of a mechanism to enable users specify inter-VM placement strategy.

Use Cases:

  • Deploying an n-Tier App:  When a user wants to deploy a n-Tier App, they might not want VMs in the same Tier to be either on the same host or even on the same POD.  This is one of the ways they can get even more high availability within a zone.
  • User who is deploying multiple VMs as part of an application deployment might have some application restrictions to have VMs running as close to each other as possible.
  • Web VMs in a Basic Zone: For users deploying multiple Web VMs in a Basic zone, they might want to ensure that all web VMs are on as far apart as possible for higher availability.

To address this problem, we will introduce the Affinity Groups feature.

The highlights of the feature include:

  • Admins will be able to expose available ‘affinity/anti-affinity types’ available in the cloud
  • Users can create affinity groups, each group having a certain affinity/anti-affinity type
  • Users associate affinity groups to VMs during deployment.
  • Cloudstack’s Deployment Planner takes into account the affinity groups of the VM and figures out a deployment destination
  • VM’s association with the affinity/anti-affinity groups will be referred while service offering upgrade, migration.
  • Ability to implement new affinity/anti-affinity types via plugin framework

Feature Specifications

The scope of this feature consists of following requirements:

  • Feature needs to be supported on Basic as well as Advanced zones
  • Users should be allowed to configure affinity/anti-affinity while creating or updating VMs
  • For each VM, users should be able to provide multiple affinity/anti-affinity groups.
  • User should be able to create affinity groups based on the available affinity/anti-affinity types
  • When configuring Affinity / anti-affinity for a VM, users should be allowed to provide a list of affinity / anti-affinity groups or select affinity /anti-affinity groups from a list (via UI)

Feature Assumptions

  • If the VM placement cannot happen as per the affinity/anti-affinity groups specified, deployment will fail and user should modify the affinity groups specified and re-initiate the deployment.
  • User can update/delete the affinity group associations of a VM only when the VM is in stopped state.

UI/UX Requirements

  • Affinity group tab that lists the groups created by this user
  • Ability to create a new Affinity group based on globally available affinity types
  • As part of VM creation/update wizards, users should be provided with the following:
    • Choice to associate affinity and/or anti-affinity groups
    • If chosen, users should be provided with a list of affinity groups available or define a new affinity group

Use cases

Admin

  • Admin decides what are the affinity/anti-affinity types available to the users.
  • This depends on which AffinityGroupProcessor plugins are included in the deployment. Each AffinityGroupProcessor plugin implements a certain affinity/anti-affinity and exposes the type it implements.
  • If admin does not want certain type of affinity/anti-affininity then the plugin implementing that type should simply be excluded in the deployment.

User

  • User can list the affinity /anti-affinity types available using listAffinityTypes API (This in turn invokes the chain of AffinityGroupProcessor plugins and adds the type each implements to the list response.)
  • User creates affinity /anti-affinity group using a type available
  • During VM deployment, user can specify affinity/anti-affinity group Ids or names to be associated with the VM. Looking at the affinity group, the corresponding plugin that can handle this type will then process to set the deployment scope.
  • User can list the affinity /anti-affinity groups of a VM
  • User can delete/update the affinity /anti-affinity groups a VM is associated to.
  • User can delete the affinity /anti-affinity group only if there are no VM's associated with it.

Architecture and Design description

The high level functional breakdown of the feature is as follows:

  • New API to list affinity types available.
  • New user APIs to create and list Affinity groups based on affinity types available.
  • Ability to associate affinity groups to VMs during deployment.
  • AffinityGroupProcessor adapter that defines the interface needed to implement an affinity type. This can be implemented by a plugin to add affinity/anti-affinity types to CloudStack.
  • A default HostAffinityProcessor plugin that implements this adapter and processes the host affinity rule.
  • A default HostAntiAffinityProcessor plugin that implements this adapter and processes the host anti-affinity rule.
  • DeploymentPlanningManager - a manager which contains planning for volume, vm, and network.

AffinityGroupProcessor Adapter

This is a new adapter interface that any plugin implementation of some affinity/anti-affinity group should follow.

public interface AffinityGroupProcessor extends Adapter {

    /**
     * process() is called to apply the affinity/anti-affinity rules to the deployment plan and avoid set for the given VM placement.
     * @param vm    virtual machine.
     * @param plan  deployment plan that tells you where it's being deployed to.
     * @param avoid avoid these data centers, pods, clusters, or hosts.
     */
    void process(VirtualMachineProfile<? extends VirtualMachine> vm, DeploymentPlan plan, ExcludeList avoid) throws AffinityConflictException;

    /**
     * getType() should return the affinity/anti-affinity group being implemented
     * @return String Affinity/Anti-affinity type
     */
    String getType();
}

HostAffinityProcessor

We will provide default implementation of the host affinity rule. This processor will implement the AffinityGroupProcessor adapter.

For the given VM, it will list the other VMs associated to its affinity group and set the same hostId in the DeploymentPlan for placement by the planner.

This has been removed from the FS as per discussions on the mailing list. This usecase has less value and more prone to failures in deployment.

HostAntiAffinityProcessor

We will provide default implementation of the host anti-affinity rule. This processor will implement the AffinityGroupProcessor adapter.

For the given VM, it will list the other VMs associated to its affinity group and set the hostIds of these VM’s in the ExcludeList, so that the planner will not place this VM on these hosts.

DeploymentPlanningManager

During VM deployment, deployment planners are invoked currently and they apply the algorithms Admins have set to provide better performance/value. But now  we need to first consider the user preferences of the VM placement defined using affinity groups and set the correct scope for searching the deployment  destination. Then this scope can be passed along to the deployment planners to process.

Thus there is a need of some layer above the deployment planners to orchestrate these deployment stages:

  1. Process Affinity/Anti-affinity - Call the chain of AffinityGroupProcessor adapters to set deploymentplan scope and exclude list
  2. Call DeploymentPlanner - to use heuristics to find the best spot to place the vm/volume. Planner will drill down to the right set of clusters to look for placement based on various heuristics.
  3. Call Allocators - Given a cluster, allocators matches the requirements to capabilities of the physical resource (host, storage pool).
public interface DeploymentPlanningManager extends Manager {

    /**
     * Manages vm deployment stages:
     *    First Process Affinity/Anti-affinity - Call the chain of AffinityGroupProcessor adapters to set deploymentplan scope and exclude list
     *    Secondly, Call DeploymentPlanner - to use heuristics to find the best spot to place the vm/volume. Planner will drill down to the write set of clusters to look for placement based on various heuristics.
     *    Lastly, Call Allocators - Given a cluster, allocators matches the requirements to capabilities of the physical resource (host, storage pool).
     *        
     */
    DeployDestination planDeployment(VirtualMachineProfile<? extends VirtualMachine> vm, DeploymentPlan plan, ExcludeList avoid) throws InsufficientServerCapacityException, AffinityConflictException;
}

API changes

Following are the API additions and changes.

CreateAffinityGroup API

This is a new user API to create affinity groups for the account. Parameters include:
a)    AccountName
b)    DomainId
c)    Name - required
d)    Type (affinity/anti-affinity) - required
e)    Description

ListAffinityGroups API

This is a new user API to list affinity groups.Parameters include:
a)    Affinity group Id
b)    Affinity group Name
c)    VM Id
d)    AccountName and DomainId

It does return the details of the affinity group and also the VM Ids that are part of this group.

{ "listaffinitygroupsresponse" : { "count":1 ,"affinitygroup" : [
{"id":"538d0918-2605-42ff-b4ef-2f1e95ac77b1","name":"db","account":"admin","domainid":"24fd1d41-a2fa-11e2-af0a-90004e86b601","domain":"ROOT","virtualmachineIds":["ac5e0006-0d1a-4334-82cf-9a06732c56c0","126318c6-0fcc-4eb7-89ae-0f4790c4145a"]}
] } }

} }
DeleteAffinityGroup API

This is a new user API to delete affinity groups. Parameters include:
a)    Affinity group Id
b)    Affinity group Name
c)    AccountName and DomainId

UpdateVMAffinityGroup API

This is a new user API to update the affinity groups assocaited with the VM. Parameters include:
a)  List of Affinity group Ids OR
b)  List of Affinity group Name
c)  VM Id

DeployVirtualMachine API

User can set a list of affinity group Ids OR names during a VM deployment. Additional parameters:
a)    affinitygroupids
b)    affinitygroupnames

ListAffinityGroupTypes API

Lists the affinity/ anti-affinity types available in the deployment.

ListVirtualMachines API

The response of this command will include the affinity_groups associated to the VM.

{ "listvirtualmachinesresponse" : { "count":1 ,"virtualmachine" : [  {"id":"2e3e0afd-4b32-428c-835d-72a0cce8cbc1","name":"2e3e0afd-4b32-428c-835d-72a0cce8cbc1","account":"admin","domainid":"6a04ecc4-9bed-11e2-bff6-7010fdc4e018","domain":"ROOT","created":"2013-04-03T14:44:02-0700","state":"Destroyed","haenable":false,"zoneid":"d8ac0a8a-fb57-43c7-8014-3a1f697e68fb","zonename":"lab","templateid":"677cd3ca-9bed-11e2-bff6-7010fdc4e018","templatename":"CentOS 5.6(64-bit) no GUI (XenServer)","templatedisplaytext":"CentOS 5.6(64-bit) no GUI (XenServer)","passwordenabled":false,"serviceofferingid":"adf0cd87-c863-4b79-afda-41f0ee549afa","serviceofferingname":"Medium Instance","cpunumber":1,"cpuspeed":1000,"memory":1024,"guestosid":"67803a82-9bed-11e2-bff6-7010fdc4e018","rootdeviceid":0,"rootdevicetype":"ROOT","securitygroup":[],"nic":[
{"id":"0852d991-0cc5-4397-abe2-9f6bc7fdb8e3","networkid":"3360145c-46a0-44fb-8fca-1cc6e1969c47","networkname":"n1","netmask":"255.255.255.0","gateway":"10.1.1.1","ipaddress":"10.1.1.249","traffictype":"Guest","type":"Isolated","isdefault":true,"macaddress":"02:00:70:b5:00:07"}

],"hypervisor":"XenServer","instancename":"i-2-11-VM","tags":[],*"affinitygroup":[
{"id":"96e30154-ef42-4bc8-a7d4-601e9426fb79","name":"webvms","account":"admin"}

]*,"jobstatus":0} ] } }}

Also affinitygroupid parameter is added to listVirtualMachines API to list VMs by affinity group.

DB Changes

As part of this feature following new tables have been added to the cloud schema:

1) `cloud`.`affinity_group` table to hold the groups created

CREATE TABLE `cloud`.`affinity_group` (
  `id` bigint unsigned NOT NULL auto_increment,
  `name` varchar(255) NOT NULL,
  `type` varchar(255) NOT NULL,
  `uuid` varchar(40),
  `description` varchar(4096) NULL,
  `domain_id` bigint unsigned NOT NULL,
  `account_id` bigint unsigned NOT NULL,
  UNIQUE (`name`, `account_id`),
  PRIMARY KEY  (`id`),
  CONSTRAINT `fk_affinity_group__account_id` FOREIGN KEY(`account_id`) REFERENCES `account`(`id`),
  CONSTRAINT `fk_affinity_group__domain_id` FOREIGN KEY(`domain_id`) REFERENCES `domain`(`id`),
  CONSTRAINT `uc_affinity_group__uuid` UNIQUE (`uuid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

2) `cloud`.`affinity_group_vm_map` table to hold the VM and affinity group associations

CREATE TABLE `cloud`.`affinity_group_vm_map` (
  `id` bigint unsigned NOT NULL auto_increment,
  `affinity_group_id` bigint unsigned NOT NULL,
  `instance_id` bigint unsigned NOT NULL,
  PRIMARY KEY  (`id`),
  CONSTRAINT `fk_agvm__group_id` FOREIGN KEY(`affinity_group_id`) REFERENCES `affinity_group`(`id`)  
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

UI flow

UI/UX Requirements

  • Affinity group tab that lists the affinity  groups created by this user - this should be a separate tab on the left hand side menu.
  • Ability to create a new Affinity group based on globally available affinity types
  • As part of VM creation/update wizards, users should be provided with the following:
    • Choice to associate affinity and/or anti-affinity groups
    • If chosen, users should be provided with a list of affinity groups available or define a new affinity group

FAQ

  • EC2 API fidelity?* Yes, confirmed that the CS API’s around affinity groups are in line with the EC2 placementgroup API’s.
  • However we are not adding support to awsapi yet as part of this feature. *  Is the AWS workflow of placementgroups and VM deployment similar?* Yes confirmed that the workflow is compatible.
  •  EC2 VM deployment RunInstances API takes in the Placement.GroupName parameter.  Similarly CS deployVirtualMachine API will accept List<affinity_group_ids> or List<affinity_group_names>
  • EC2 workflow mentioned here http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/using_cluster_computing.html#create_cluster is similar to our design for affinity groups in the VM deployment wizard:* _ _Auto-scaling support?
    •  This not supported by the feature.
  • Supports Projects?
    • The affinity groups are created by an individual user account and available to that account only. We are not including any support for CloudStack Projects feature.
  • DRS? 
    • This is applicable only for placement operations through CloudStack. This implementation is to only support scenarios where the HV does not do HA or DRS.

Appendix

Appendix A:

Appendix B:

  • No labels