Asgard, the Grails App that Deploys Netflix to the Cloud

Preview:

DESCRIPTION

Speaker: Joe Sondow Asgard is a free and open source Grails application built and used by Netflix to deploy code changes and to manage resources in the Amazon cloud at large scale. In this talk we'll delve into how Asgard works, covering topics such as: Open source motivation, presence, and support. Tour of the user interface. Customizing Asgard for your own company. How Netflix philosophies drive Asgard's design. The Netflix Cloud Model. Easy large deployments and fast rollback. Caching the cloud with Groovy. Visual language for the cloud. Publishing a REST API. Mocking AWS for offline testing. Comparison with the AWS Management Console.

Citation preview

Joe Sondow, Netflix

The Grails App that Deploys Netflix to the Cloud

@joesondow

Slides onlinehttp://slideshare.net/joesondow

@joesondow

Who am I?

@joesondow

Who am I?

@joesondow

Who am I?Joe Sondow

@joesondow

Who am I?Joe Sondow

Netflix since 2010

@joesondow

Who am I?Joe Sondow

Netflix since 2010

Asgard lead

@joesondow

Who am I?Joe Sondow

Netflix since 2010

Asgard lead

Grails

@joesondow

Who am I?Joe Sondow

Netflix since 2010

Asgard lead

Grails

jQuery

@joesondow

Why am I here?

Why am I here?

Sell you something

Why am I here?

Sell you something

Discuss business plans

Why am I here?

Sell you something

Discuss business plans

Answer technical questions

Why am I here?

Sell you something

Discuss business plans

Answer technical questions

Be a smaller fish in AWS

Why am I here?

Sell you something

Discuss business plans

Answer technical questions

Be a smaller fish in AWS

Give back to community

Why am I here?

Sell you something

Discuss business plans

Answer technical questions

Be a smaller fish in AWS

Give back to community

Build cloud standards

Why am I here?

Sell you something

Discuss business plans

Answer technical questions

Be a smaller fish in AWS

Give back to community

Build cloud standards

Steal your engineers

Why am I here?

Asgard

Asgard

AsgardScreen shots

AsgardApplication list

AsgardAuto Scaling Group list

AsgardCluster deployment, ready for fast rollback

Asgard

AsgardApplication deployment

AsgardApplication deployment

Cloud management

AsgardApplication deployment

Cloud management

Started 2010

AsgardApplication deployment

Cloud management

Started 2010

Open source June 2012

AsgardApplication deployment

Cloud management

Started 2010

Open source June 2012

http://netflix.github.io

AsgardApplication deployment

Cloud management

Started 2010

Open source June 2012

http://netflix.github.io

100’s of Jira tickets

AsgardApplication deployment

Cloud management

Started 2010

Open source June 2012

http://netflix.github.io

100’s of Jira tickets

Actively developed

Source code and downloadhttps://github.com/Netflix/asgard

User forumhttps://groups.google.com/group/AsgardUsers

The Asgard Showhttps://youtube.com/TheAsgardShow

Open Source, Closed Config

Open Source, Closed ConfigPull company-specific details out of Asgard

Open Source, Closed Config

Open Source, Closed Config

Open Source, Closed ConfigAsgard for Netflix is configured to use company-specific extension points such as standard utility links for instances

Open Source, Closed ConfigOut-of-the-box Asgard installation has no instance utility links

Open Source, Closed Config

link  {

       //  Avoid  GStrings  here  because  these  Strings  are  stored  dynamic  templates  for  arbitrary  server  names.        String  logUrlStart  =  'http://${server}:7777'        String  configUrlStart  =  'http://${server}:9999/AdminConfig'        instanceLinkGroupingsToLinkTemplateLists  =  [                        'Logs':  [                                        new  TextLinkTemplate(logUrlStart  +  '/Admin/list?view=tomcat/catalina.out',  'catalina.out'),                                        new  TextLinkTemplate(logUrlStart  +  '/Admin/list',  'Log  File  Archive'),                                        new  TextLinkTemplate(logUrlStart  +  '/Admin/threaddumps',  'Thread  Dumps'),                                        new  TextLinkTemplate(logUrlStart  +  '/AdminProxy',  'Admin  Proxy  Info'),                                        new  TextLinkTemplate(logUrlStart  +  '/AdminStatus',  'Admin  Proxy  Status'),                                        new  TextLinkTemplate(logUrlStart  +  '/GC/index',  'GC  Visualization')                        ],                        'Netflix  Configuration':  [                                        new  TextLinkTemplate(configUrlStart  +  '/prop.html',  'NetflixConfiguration  Properties  Console'),                                        new  TextLinkTemplate(configUrlStart  +  '/libs.html',  'Libraries  Console'),                                        new  TextLinkTemplate(configUrlStart  +  '/machineProps',  'Machine  Readable  Properties'),                                        new  TextLinkTemplate(configUrlStart  +  '/webapp/META-­‐INF/MANIFEST.MF',  'Manifest'),                        ]        ]}

Netflix specific $ASGARD_HOME/Config.groovy

Open Source, Closed Config

asgardHome = System.getenv('ASGARD_HOME') ?: System.getProperty('ASGARD_HOME') ?: "${System.getProperty('user.home')}/.asgard"

// Locations to search for config files that get merged into the main config.// Config files can either be Java properties files or ConfigSlurper scripts.grails.config.locations = [ "file:${asgardHome}/Config.groovy", 'classpath:sourceVersion.properties']

grails-app/conf/Config.groovy references external configuration file~/.asgard/Config.groovyhttps://github.com/Netflix/asgard/blob/master/grails-app/conf/Config.groovy

Open Source, Closed Config

grails  {        awsAccounts=["171234567890"]        awsAccountNames=["171234567890":  "prod"]}secret  {        accessId="AKOBIWANLANDOLUKEHAN"        secretKey="Od0INd/C3P0/R2D2atatTIEFIGHTERdeathstar"}cloud  {        accountName="prod"        publicResourceAccounts=["amazon"]}

External Config.groovy also holds the AWS account credentials, or references for finding them.

Netflix is the world’s leading Internet television network with nearly 38 million members in 40 countries enjoying more than one billion hours of TV shows and movies per month, including original series.

(from http://ir.netflix.com)

Freedom and Responsibility

Freedom and ResponsibilityCorporate culture and the Cloud

Freedom and Responsibility

Freedom and ResponsibilityCloud SOA

Freedom and ResponsibilityCloud SOA

100’s of services

Freedom and ResponsibilityCloud SOA

100’s of services

Small teams

Freedom and ResponsibilityCloud SOA

100’s of services

Small teams

Independent releases

Freedom and ResponsibilityCloud SOA

100’s of services

Small teams

Independent releases

Controlled chaos

Cloud deployment model

Cloud deployment modelApplications and Clusters

Cloud deployment model

Cloud deployment model

Auto ScalingGroup

Cloud deployment model

Auto ScalingGroup

LaunchConfiguration

Cloud deployment model

Auto ScalingGroup

LaunchConfiguration

Elastic LoadBalancer

Cloud deployment model

Auto ScalingGroup

LaunchConfiguration

Amazon MachineImage

Elastic LoadBalancer

Cloud deployment model

Auto ScalingGroup

LaunchConfiguration

SecurityGroup

Amazon MachineImage

Elastic LoadBalancer

Cloud deployment model

Auto ScalingGroup

LaunchConfiguration

SecurityGroup

Amazon MachineImage

Instances

Elastic LoadBalancer

Cloud deployment model

Auto ScalingGroup

LaunchConfiguration

SecurityGroup

Amazon MachineImage

Instances

Elastic LoadBalancer

Cloud deployment model

Auto ScalingGroup

LaunchConfiguration

SecurityGroup

Amazon MachineImage

Instances

Elastic LoadBalancer

Cloud deployment model

Auto ScalingGroup

LaunchConfiguration

SecurityGroup

Amazon MachineImage

Instances

Elastic LoadBalancer

Cloud deployment model

Cloud deployment model

Search

Cloud deployment model

API Search

Cloud deployment model

API

Ratings

Search

Cloud deployment modelStreaming Starts

API

Ratings

Search

Cloud deployment modelStreaming Starts

Autocomplete API

Ratings

Search

Cloud deployment modelStreaming Starts

Autocomplete API

Sign Up

Ratings

Search

Cloud deployment modelStreaming Starts

Autocomplete API

Sign Up

Ratings

Search

ApplicationApplication

ApplicationApplication

Application

Application

Inventing the Application

Inventing the ApplicationProblem:

Application is not an Amazon concept

Inventing the ApplicationProblem:

Application is not an Amazon concept

Solution:

Create an Application database in the cloud

Enforce naming conventions on Amazon objects

Fast Rollback

Fast RollbackOptimism causes outages

Fast RollbackOptimism causes outages

Production traffic is unique

Fast RollbackOptimism causes outages

Production traffic is unique

Keep old version running

Fast RollbackOptimism causes outages

Production traffic is unique

Keep old version running

Switch traffic to new version

Fast RollbackOptimism causes outages

Production traffic is unique

Keep old version running

Switch traffic to new version

Monitor results

Fast RollbackOptimism causes outages

Production traffic is unique

Keep old version running

Switch traffic to new version

Monitor results

Revert traffic quickly

Fast Rollback

Fast Rollback

api-usprod-v007

api-frontend

Fast Rollback

api-usprod-v007

api-frontend

api-usprod-v008

Fast Rollback

api-usprod-v007

api-frontend

api-usprod-v008

Fast Rollback

api-usprod-v007

api-frontend

api-usprod-v008

Fast Rollback

api-usprod-v007

api-frontend

api-usprod-v008

Fast Rollback

api-usprod-v007

api-frontend

Inventing the Cluster

Inventing the ClusterProblem:

Two ASGs with one function but different names

Inventing the ClusterProblem:

Two ASGs with one function but different names

Solution:

Append version number in reserved format

Parse ASG name to determine long-term “cluster”

Inventing the Cluster

api

api-usprod

api-usprod-v007

api-usprod-v008

Application

Cluster

Auto Scaling Group

Auto Scaling Group

Instead of keeping a database in sync, use naming conventions to store the source in truth in Amazon’s API

Database Aversion

Database AversionStoring metadata on cloud objects

Database Aversion

Database Aversion

Naming conventions

Database Aversion

Naming conventions

Tagging conventions

Database Aversion

Naming conventions

Tagging conventions

No GORM domain objects

Database Aversion

Naming conventions

Tagging conventions

No GORM domain objects

AWS Java SDK

Database Aversion

Naming conventions

Tagging conventions

No GORM domain objects

AWS Java SDK

Less to go out of sync

Database Aversion

Naming conventions

Tagging conventions

No GORM domain objects

AWS Java SDK

Less to go out of sync

Shared source of truth

Caching the Cloud

Caching the CloudResponsive, massive, multi-region metadata

Caching the Cloud

Caching the Cloud

Large counts

Caching the Cloud

Large counts

Many types

Caching the Cloud

Large counts

Many types

Complex relationships

Caching the Cloud

Large counts

Many types

Complex relationships

Multiple regions

Caching the Cloud

Large counts

Many types

Complex relationships

Multiple regions

Consistent single objects

Caching the Cloud

Large counts

Many types

Complex relationships

Multiple regions

Consistent single objects

Eventually consistent lists

class  Caches  {        final  CachedMap<AppRegistration>  allApplications        final  CachedMap<ApplicationMetrics>  allApplicationMetrics        final  CachedMap<HardwareProfile>  allHardwareProfiles        final  MultiRegionCachedMap<MetricAlarm>  allAlarms        final  MultiRegionCachedMap<ApplicationInstance>  allApplicationInstances        final  MultiRegionCachedMap<AutoScalingGroup>  allAutoScalingGroups        final  MultiRegionCachedMap<AvailabilityZone>  allAvailabilityZones        final  MultiRegionCachedMap<Cluster>  allClusters        final  MultiRegionCachedMap<DBInstance>  allDBInstances        final  MultiRegionCachedMap<DBSecurityGroup>  allDBSecurityGroups        final  MultiRegionCachedMap<DBSnapshot>  allDBSnapshots        final  MultiRegionCachedMap<String>  allDomains        final  MultiRegionCachedMap<FastProperty>  allFastProperties        final  MultiRegionCachedMap<Image>  allImages        final  MultiRegionCachedMap<Instance>  allInstances        final  MultiRegionCachedMap<InstanceTypeData>  allInstanceTypes        final  MultiRegionCachedMap<KeyPairInfo>  allKeyPairs        final  MultiRegionCachedMap<LaunchConfiguration>  allLaunchConfigurations        //  etc.        //  etc.        //  etc.}

Caching the Cloud

class  Caches  {        final  CachedMap<AppRegistration>  allApplications        final  CachedMap<ApplicationMetrics>  allApplicationMetrics        final  CachedMap<HardwareProfile>  allHardwareProfiles        final  MultiRegionCachedMap<MetricAlarm>  allAlarms        final  MultiRegionCachedMap<ApplicationInstance>  allApplicationInstances        final  MultiRegionCachedMap<AutoScalingGroup>  allAutoScalingGroups        final  MultiRegionCachedMap<AvailabilityZone>  allAvailabilityZones        final  MultiRegionCachedMap<Cluster>  allClusters        final  MultiRegionCachedMap<DBInstance>  allDBInstances        final  MultiRegionCachedMap<DBSecurityGroup>  allDBSecurityGroups        final  MultiRegionCachedMap<DBSnapshot>  allDBSnapshots        final  MultiRegionCachedMap<String>  allDomains        final  MultiRegionCachedMap<FastProperty>  allFastProperties        final  MultiRegionCachedMap<Image>  allImages        final  MultiRegionCachedMap<Instance>  allInstances        final  MultiRegionCachedMap<InstanceTypeData>  allInstanceTypes        final  MultiRegionCachedMap<KeyPairInfo>  allKeyPairs        final  MultiRegionCachedMap<LaunchConfiguration>  allLaunchConfigurations        //  etc.        //  etc.        //  etc.}

Caching the Cloudclass  Caches  {        final  CachedMap<AppRegistration>  allApplications        final  CachedMap<ApplicationMetrics>  allApplicationMetrics        final  CachedMap<HardwareProfile>  allHardwareProfiles        final  MultiRegionCachedMap<MetricAlarm>  allAlarms        final  MultiRegionCachedMap<ApplicationInstance>  allApplicationInstances        final  MultiRegionCachedMap<AutoScalingGroup>  allAutoScalingGroups        final  MultiRegionCachedMap<AvailabilityZone>  allAvailabilityZones        final  MultiRegionCachedMap<Cluster>  allClusters        final  MultiRegionCachedMap<DBInstance>  allDBInstances        final  MultiRegionCachedMap<DBSecurityGroup>  allDBSecurityGroups        final  MultiRegionCachedMap<DBSnapshot>  allDBSnapshots        final  MultiRegionCachedMap<String>  allDomains        final  MultiRegionCachedMap<FastProperty>  allFastProperties        final  MultiRegionCachedMap<Image>  allImages        final  MultiRegionCachedMap<Instance>  allInstances        final  MultiRegionCachedMap<InstanceTypeData>  allInstanceTypes        final  MultiRegionCachedMap<KeyPairInfo>  allKeyPairs        final  MultiRegionCachedMap<LaunchConfiguration>  allLaunchConfigurations        //  etc.        //  etc.        //  etc.}

class  AwsRdsService  implements  CacheInitializer,  InitializingBean  {

       MultiRegionAwsClient<AmazonRDS>  awsClient        Caches  caches

       void  initializeCaches()  {                caches.allDBInstances.ensureSetUp({  Region  region  -­‐>  retrieveDBInstances(region)  })        }

       private  List<DBInstance>  retrieveDBInstances(Region  region)  {                awsClient.by(region).describeDBInstances(new  DescribeDBInstancesRequest()).getDBInstances()        }

       Collection<DBInstance>  getDBInstances(UserContext  userContext)  {                caches.allDBInstances.by(userContext.region).list()        }}

Caching the Cloudclass  AwsRdsService  implements  CacheInitializer,  InitializingBean  {

       MultiRegionAwsClient<AmazonRDS>  awsClient        Caches  caches

       void  initializeCaches()  {                caches.allDBInstances.ensureSetUp({  Region  region  -­‐>  retrieveDBInstances(region)  })        }

       private  List<DBInstance>  retrieveDBInstances(Region  region)  {                awsClient.by(region).describeDBInstances(new  DescribeDBInstancesRequest()).getDBInstances()        }

       Collection<DBInstance>  getDBInstances(UserContext  userContext)  {                caches.allDBInstances.by(userContext.region).list()        }}

class  AwsRdsService  implements  CacheInitializer,  InitializingBean  {

       MultiRegionAwsClient<AmazonRDS>  awsClient        Caches  caches

       void  initializeCaches()  {                caches.allDBInstances.ensureSetUp({  Region  region  -­‐>  retrieveDBInstances(region)  })        }

       private  List<DBInstance>  retrieveDBInstances(Region  region)  {                awsClient.by(region).describeDBInstances(new  DescribeDBInstancesRequest()).getDBInstances()        }

       Collection<DBInstance>  getDBInstances(UserContext  userContext)  {                caches.allDBInstances.by(userContext.region).list()        }}

Caching the Cloudclass  AwsRdsService  implements  CacheInitializer,  InitializingBean  {

       MultiRegionAwsClient<AmazonRDS>  awsClient        Caches  caches

       void  initializeCaches()  {                caches.allDBInstances.ensureSetUp({  Region  region  -­‐>  retrieveDBInstances(region)  })        }

       private  List<DBInstance>  retrieveDBInstances(Region  region)  {                awsClient.by(region).describeDBInstances(new  DescribeDBInstancesRequest()).getDBInstances()        }

       Collection<DBInstance>  getDBInstances(UserContext  userContext)  {                caches.allDBInstances.by(userContext.region).list()        }}

class  AwsRdsService  implements  CacheInitializer,  InitializingBean  {

       MultiRegionAwsClient<AmazonRDS>  awsClient        Caches  caches

       void  initializeCaches()  {                caches.allDBInstances.ensureSetUp({  Region  region  -­‐>  retrieveDBInstances(region)  })        }

       private  List<DBInstance>  retrieveDBInstances(Region  region)  {                awsClient.by(region).describeDBInstances(new  DescribeDBInstancesRequest()).getDBInstances()        }

       Collection<DBInstance>  getDBInstances(UserContext  userContext)  {                caches.allDBInstances.by(userContext.region).list()        }}

class  AwsRdsService  implements  CacheInitializer,  InitializingBean  {

       MultiRegionAwsClient<AmazonRDS>  awsClient        Caches  caches

       void  initializeCaches()  {                caches.allDBInstances.ensureSetUp({  Region  region  -­‐>  retrieveDBInstances(region)  })        }

       private  List<DBInstance>  retrieveDBInstances(Region  region)  {                awsClient.by(region).describeDBInstances(new  DescribeDBInstancesRequest()).getDBInstances()        }

       Collection<DBInstance>  getDBInstances(UserContext  userContext)  {                caches.allDBInstances.by(userContext.region).list()        }}

Caching the Cloudclass  AwsRdsService  implements  CacheInitializer,  InitializingBean  {

       MultiRegionAwsClient<AmazonRDS>  awsClient        Caches  caches

       void  initializeCaches()  {                caches.allDBInstances.ensureSetUp({  Region  region  -­‐>  retrieveDBInstances(region)  })        }

       private  List<DBInstance>  retrieveDBInstances(Region  region)  {                awsClient.by(region).describeDBInstances(new  DescribeDBInstancesRequest()).getDBInstances()        }

       Collection<DBInstance>  getDBInstances(UserContext  userContext)  {                caches.allDBInstances.by(userContext.region).list()        }}

class  AwsRdsService  implements  CacheInitializer,  InitializingBean  {

       MultiRegionAwsClient<AmazonRDS>  awsClient        Caches  caches

       void  initializeCaches()  {                caches.allDBInstances.ensureSetUp({  Region  region  -­‐>  retrieveDBInstances(region)  })        }

       private  List<DBInstance>  retrieveDBInstances(Region  region)  {                awsClient.by(region).describeDBInstances(new  DescribeDBInstancesRequest()).getDBInstances()        }

       Collection<DBInstance>  getDBInstances(UserContext  userContext)  {                caches.allDBInstances.by(userContext.region).list()        }}

class  AwsRdsService  implements  CacheInitializer,  InitializingBean  {

       MultiRegionAwsClient<AmazonRDS>  awsClient        Caches  caches

       void  initializeCaches()  {                caches.allDBInstances.ensureSetUp({  Region  region  -­‐>  retrieveDBInstances(region)  })        }

       private  List<DBInstance>  retrieveDBInstances(Region  region)  {                awsClient.by(region).describeDBInstances(new  DescribeDBInstancesRequest()).getDBInstances()        }

       Collection<DBInstance>  getDBInstances(UserContext  userContext)  {                caches.allDBInstances.by(userContext.region).list()        }}

class  AwsRdsService  implements  CacheInitializer,  InitializingBean  {

       MultiRegionAwsClient<AmazonRDS>  awsClient        Caches  caches

       void  initializeCaches()  {                caches.allDBInstances.ensureSetUp({  Region  region  -­‐>  retrieveDBInstances(region)  })        }

       private  List<DBInstance>  retrieveDBInstances(Region  region)  {                awsClient.by(region).describeDBInstances(new  DescribeDBInstancesRequest()).getDBInstances()        }

       Collection<DBInstance>  getDBInstances(UserContext  userContext)  {                caches.allDBInstances.by(userContext.region).list()        }}

Caching the Cloudclass  AwsRdsService  implements  CacheInitializer,  InitializingBean  {

       MultiRegionAwsClient<AmazonRDS>  awsClient        Caches  caches

       void  initializeCaches()  {                caches.allDBInstances.ensureSetUp({  Region  region  -­‐>  retrieveDBInstances(region)  })        }

       private  List<DBInstance>  retrieveDBInstances(Region  region)  {                awsClient.by(region).describeDBInstances(new  DescribeDBInstancesRequest()).getDBInstances()        }

       Collection<DBInstance>  getDBInstances(UserContext  userContext)  {                caches.allDBInstances.by(userContext.region).list()        }}

class  AwsRdsService  implements  CacheInitializer,  InitializingBean  {

       MultiRegionAwsClient<AmazonRDS>  awsClient        Caches  caches

       void  initializeCaches()  {                caches.allDBInstances.ensureSetUp({  Region  region  -­‐>  retrieveDBInstances(region)  })        }

       private  List<DBInstance>  retrieveDBInstances(Region  region)  {                awsClient.by(region).describeDBInstances(new  DescribeDBInstancesRequest()).getDBInstances()        }

       Collection<DBInstance>  getDBInstances(UserContext  userContext)  {                caches.allDBInstances.by(userContext.region).list()        }}

class  AwsRdsService  implements  CacheInitializer,  InitializingBean  {

       MultiRegionAwsClient<AmazonRDS>  awsClient        Caches  caches

       void  initializeCaches()  {                caches.allDBInstances.ensureSetUp({  Region  region  -­‐>  retrieveDBInstances(region)  })        }

       private  List<DBInstance>  retrieveDBInstances(Region  region)  {                awsClient.by(region).describeDBInstances(new  DescribeDBInstancesRequest()).getDBInstances()        }

       Collection<DBInstance>  getDBInstances(UserContext  userContext)  {                caches.allDBInstances.by(userContext.region).list()        }}

class  AwsRdsService  implements  CacheInitializer,  InitializingBean  {

       MultiRegionAwsClient<AmazonRDS>  awsClient        Caches  caches

       void  initializeCaches()  {                caches.allDBInstances.ensureSetUp({  Region  region  -­‐>  retrieveDBInstances(region)  })        }

       private  List<DBInstance>  retrieveDBInstances(Region  region)  {                awsClient.by(region).describeDBInstances(new  DescribeDBInstancesRequest()).getDBInstances()        }

       Collection<DBInstance>  getDBInstances(UserContext  userContext)  {                caches.allDBInstances.by(userContext.region).list()        }}

Caching the Cloud

Visual Language for the Cloud

Visual Language for the CloudTango open source icons

Visual Language for the Cloud

Visual Language for the Cloud

AWS is intimidating

Visual Language for the Cloud

AWS is intimidating

Many object types

Visual Language for the Cloud

AWS is intimidating

Many object types

Help newbie users

Visual Language for the Cloud

AWS is intimidating

Many object types

Help newbie users

Reduce cognitive load

Visual Language for the Cloud

AWS is intimidating

Many object types

Help newbie users

Reduce cognitive load

Make it easy

Visual Language for the Cloud

AWS is intimidating

Many object types

Help newbie users

Reduce cognitive load

Make it easy

Avoid surprises

Visual Language for the Cloud

Visual Language for the Cloud

At a glance, these nav bar items look alike.

Visual Language for the Cloud

At a glance, these nav bar items look alike.

Visual Language for the Cloud

Visual Language for the Cloud

Some screens have multiple action buttons that look too similar.

Visual Language for the Cloud

Some screens have multiple action buttons that look too similar.

Visual Language for the Cloud

Visual Language for the Cloud

Because of naming conventions, these links look alike.

Visual Language for the Cloud

Because of naming conventions, these links look alike.

Visual Language for the Cloud

Visual Language for the CloudThe indicators for the current AWS region are too easy to miss.

Visual Language for the CloudThe indicators for the current AWS region are too easy to miss.

Visual Language for the Cloud

These availability zones are important to recognize at a glance but their names look similar, and they appear on many screens.

Visual Language for the Cloud

These availability zones are important to recognize at a glance but their names look similar, and they appear on many screens.

Visual Language for the Cloud

Tango Icons

Tango Iconshttp://tango.freedesktop.org/

Tango Iconshttp://tango.freedesktop.org/http://tango.freedesktop.org/Tango_Icon_Theme_Guidelines

http://commons.wikimedia.org/wiki/Tango_icons

Used by Firefox, Jenkins, GIMP, OpenOffice, VMWare

REST API in Grails

REST API in GrailsEnable external mashups with cloud data

REST API in Grails

REST API in Grails

REST API in Grails

REST API in Grails

REST API in Grails

REST API in Grails

REST API in Grails

REST API in Grails

REST API in Grails

REST API in Grailsdef show = { String name = params.id UserContext userContext = UserContext.of(request) AppRegistration app = applicationService.getRegisteredApplication(userContext, name) def groups = awsAutoScalingService.getAutoScalingGroupsForApp(userContext, name) List<String> clusterNames = groups.collect { Relationships.clusterFromGroupName(it.autoScalingGroupName) }.unique() Map details = [ app: app, strictName: Relationships.checkStrictName(app.name), clusters: clusterNames, groups: groups, balancers: awsLoadBalancerService.getLoadBalancersForApp(userContext, name), securities: awsEc2Service.getSecurityGroupsForApp(userContext, name), appSecurityGroup: awsEc2Service.getSecurityGroup(userContext, name), launches: awsAutoScalingService.getLaunchConfigurationsForApp(userContext, name), ] withFormat { html { return details } xml { new XML(details).render(response) } json { new JSON(details).render(response) } }}

ApplicationController.groovy

Offline Development

Offline DevelopmentMakes on a plane

Offline DevelopmentMock data

Mock behavior

System property switch offline=true

Mock Datahttp://asgardprod/us-east-1/autoScaling/list.json

Mock DataParse JSON

Mock BehaviorOverride Amazon Java client methods

System Propertygrails run-app -Doffline=true

Why not the AWS console?

Why not the AWS console?

Why not the AWS console?

Why not the AWS console?Hide keys

Why not the AWS console?Hide keys

Customize model

Why not the AWS console?Hide keys

Customize model

Enforce conventions

Why not the AWS console?Hide keys

Customize model

Enforce conventions

Automate workflow

Why not the AWS console?Hide keys

Customize model

Enforce conventions

Automate workflow

Log changes

Why not the AWS console?Hide keys

Customize model

Enforce conventions

Automate workflow

Log changes

Integrate systems

Why not the AWS console?Hide keys

Customize model

Enforce conventions

Automate workflow

Log changes

Integrate systems

Customize REST API

@NetflixOSS

@NetflixOSShttp://techblog.netflix.com

@NetflixOSShttp://techblog.netflix.comhttp://netflix.github.io

Thank you

http://github.com/Netflix/asgard

Thank youQuestions?

@AsgardOSS @joesondow jobs.netflix.com

http://github.com/Netflix/asgard