- Home
- >
- Software Development
- >
- How Apache Brooklyn Helped IBM SoftLayer Auto-Scale a Heavy Workload – InApps 2022
How Apache Brooklyn Helped IBM SoftLayer Auto-Scale a Heavy Workload – InApps is an article under the topic Software Development Many of you are most interested in today !! Today, let’s InApps.net learn How Apache Brooklyn Helped IBM SoftLayer Auto-Scale a Heavy Workload – InApps in today’s post !
Read more about How Apache Brooklyn Helped IBM SoftLayer Auto-Scale a Heavy Workload – InApps at Wikipedia
You can find content about How Apache Brooklyn Helped IBM SoftLayer Auto-Scale a Heavy Workload – InApps from the Wikipedia website
A company that provides critical consumer data to over a billion mobile users each day tasked IBM SoftLayer with providing functionality to create auto-scaling groups of servers located on a private network. A key requirement was elasticity; where, based on the workload demands and user-experience response time, systems automatically scale up and scale down based on predetermined policies.
Based on the customer’s requirements, Apache Brooklyn was selected as the auto-scaling tool to implement the solution.
Auto-scaling is based on CPU utilization. If average CPU utilization of the servers in a group is higher than the highest threshold, or trigger event, more resources need to be provisioned or scaled up. If average CPU utilization of the servers in a group is lower than the lowest threshold, or trigger event, resources need to be scaled down. The customer had the following requirements:
- Ability to specify the following parameters:
- Initial number of servers in the group.
- Minimum and maximum number of servers in the group.
- High and low CPU thresholds.
- Number of additional servers to be scaled up and down on a trigger event.
- Integrate SoftLayer Domain Name System (DNS):
- After a server in the group is provisioned, or scaled up, and available, an appropriate SoftLayer DNS record is to be created for it.
- When server is scaled down, the SoftLayer DNS record for it is to be removed.
- Integrate a load balancer:
- After a server in the group is provisioned, or scaled up, and available, the server record is to be added to the appropriate NetScaler load balancer and bound to the appropriate load-balancing group.
- When server is scaled down, it has to be unbound from the load balancing group and the server record is to be removed from the NetScaler.
- Integrate Chef:
- After a server in the group is provisioned, or scaled up, and available, the Chef client is to run and register the node at the Chef server.
- When server is scaled down, the server’s node and client record are to be removed from the Chef server.
- Server provisioning requirements:
- All servers in the group are to be provisioned as SoftLayer virtual machines (VMs) with private-only uplinks, 1,000MB port speed, and a specified private VLAN.
- VMs are to be provisioned from the multi-disk standard template, created by the customer in SoftLayer.
- Operating system
Apache Brooklyn Overview
Apache Brooklyn is a framework for modeling, monitoring, and managing applications through autonomic blueprints. Click here for more information.
Apache Brooklyn Concepts
The Apache Brooklyn documentation provides definitions of the Apache Brooklyn concepts such as
- Entities
- Application
- Parent and Membership Configuration
- Sensors and Effectors
- Lifecycle and Management Context
- Dependent Configuration
- Location, Policies
- Execution
- Implementation
Integrating SoftLayer DNS, NetScaler, and Chef
Apache Brooklyn provides a base class for customizing location, brooklyn.location.jclouds.BasicJcloudsLocationCustomizer
, which contains methods that allow for creating additional parameters when machines are provisioned. Actions can be executed after a machine is provisioned, and before and after it has been released when canceled.
We created our own location customizer class that extended the brooklyn.location.jclouds.BasicJcloudsLocationCustomizer
provided by Brooklyn. For our example, we will refer to it as brooklyn.location.jclouds.ProjectJcloudsLocationCustomizer
.
The following three methods were overridden:
public void customize(JcloudsLocation location, ComputeService computeService, TemplateOptions templateOptions)
– The method gets invoked before calling the cloud API to provision a server. We enabled the ability to supply provisioning properties such asprivateNetworkOnly, primaryBackendNetworkComponentVlanId, portSpeed
, and others.public void customize(JcloudsLocation location, ComputeService computeService, JcloudsSshMachineLocation machine)
– The method gets invoked after a machine is provisioned and started, thus all server parameters, like server IP address, are available. The code to add a server to DNS and the load balancer has to be placed in this method. SoftLayer DNS and NetScaler REST API are used to create DNS records and bind the server to NetScaler. We utilized a package provided by Brooklyn,brooklyn.util.http
, to submit REST calls to SoftLayer DNS and NetScaler APIs.public void preRelease(JcloudsSshMachineLocation machine)
– The method gets invoked on machine cancelation before the server is stopped. We added REST calls to SoftLayer DNS and NetScaler here to remove DNS and NetScaler records and unbind the server from NetScaler’s group.
We did not have to do anything specific to connect the new server to Chef. The image, which was used to provision the server, had a Chef client installed on it and start-up script (the script runs the Chef client and connects it to the Chef server). If you prefer, you can utilize Brooklyn integration with Chef to create blueprints.
We also added a REST call to the Chef server to remove appropriate client and node records.
Application Blueprint
Within the application blueprint, we customized the location, metric collecting parameters, and auto-scaling properties of the servers. Here are the commands used to customize each component:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 | name: Group1 location:
jclouds:softlayer:tor01: customizerType: brooklyn<span class=“hljs-class”>.location</span><span class=“hljs-class”>.jclouds</span><span class=“hljs-class”>.ProjectJcloudLocationCustomizer</span> privateNetworkOnly: true primaryBackendNetworkComponentVlanId: <span class=“hljs-number”>12345</span> portSpeed: <span class=“hljs-number”>1000</span> imageId: <span class=“hljs-number”>123456</span> dnsZoneId: <span class=“hljs-number”>12345</span> netscalerGroup: app1 netscalerGroupPort: <span class=“hljs-number”>8080</span> netscalerUrl: http:<span class=“hljs-comment”>//user:[email protected]/nitro/v1/</span>
services: – type: brooklyn<span class=“hljs-class”>.entity</span><span class=“hljs-class”>.group</span><span class=“hljs-class”>.DynamicCluster</span> id: cluster name: dynamic cluster initialSize: <span class=“hljs-number”>1</span> memberSpec: <span class=“hljs-variable”>$brooklyn</span>:entitySpec: name: VMinSL type: brooklyn<span class=“hljs-class”>.entity</span><span class=“hljs-class”>.basic</span><span class=“hljs-class”>.EmptySoftwareProcess</span> brooklyn<span class=“hljs-class”>.initializers</span>: – type: brooklyn<span class=“hljs-class”>.entity</span><span class=“hljs-class”>.software</span><span class=“hljs-class”>.ssh</span><span class=“hljs-class”>.SshCommandSensor</span> brooklyn<span class=“hljs-class”>.config</span>: name: server<span class=“hljs-class”>.cpucount</span> command: <span class=“hljs-string”>“LANG=en_US.UTF-8 sar -u 1 1|grep Average | awk ‘{print 100 – $8}'”</span> targetType: java<span class=“hljs-class”>.lang</span><span class=“hljs-class”>.Double</span> period: <span class=“hljs-number”>10s</span> brooklyn<span class=“hljs-class”>.config</span>: post<span class=“hljs-class”>.launch</span><span class=“hljs-class”>.command</span>: <span class=“hljs-string”>“sudo apt-get install -y sysstat”</span>
brooklyn<span class=“hljs-class”>.enrichers</span>: – type: brooklyn<span class=“hljs-class”>.enricher</span><span class=“hljs-class”>.basic</span><span class=“hljs-class”>.Aggregator</span> brooklyn<span class=“hljs-class”>.config</span>: enricher<span class=“hljs-class”>.sourceSensor</span>: <span class=“hljs-variable”>$brooklyn</span>:<span class=“hljs-function”><span class=“hljs-title”>sensor</span><span class=“hljs-params”>(<span class=“hljs-string”>“server.cpucount”</span>)</span></span> enricher<span class=“hljs-class”>.targetSensor</span>: <span class=“hljs-variable”>$brooklyn</span>:<span class=“hljs-function”><span class=“hljs-title”>sensor</span><span class=“hljs-params”>(<span class=“hljs-string”>“server.cpucount.averaged”</span>)</span></span> enricher<span class=“hljs-class”>.aggregating</span><span class=“hljs-class”>.fromMembers</span>: true transformation: average brooklyn<span class=“hljs-class”>.policies</span>: – policyType: brooklyn<span class=“hljs-class”>.policy</span><span class=“hljs-class”>.autoscaling</span><span class=“hljs-class”>.AutoScalerPolicy</span> brooklyn<span class=“hljs-class”>.config</span>: metric: <span class=“hljs-variable”>$brooklyn</span>:<span class=“hljs-function”><span class=“hljs-title”>sensor</span><span class=“hljs-params”>(<span class=“hljs-string”>“server.cpucount.averaged”</span>)</span></span> metricLowerBound: <span class=“hljs-number”>10</span> metricUpperBound: <span class=“hljs-number”>60</span> minPoolSize: <span class=“hljs-number”>1</span> maxPoolSize: <span class=“hljs-number”>5</span>
|
Location
In the location section of the blueprint we specified provisioning properties such as
- Where the server is to be previsioned (data center and VLAN).
- Whether the server will be provisioned with privateNetworkOnly.
- An image ID of the SoftLayer standard template or flex image.
- Port speed.
We also specified the SoftLayer DNS zone ID, which is used by ProjectJcloudLocationCustomizer
to add and delete records in the DNS zone, and NetScaler information for binding and unbinding the server from NetScaler.
<span class=“hljs-attribute”>location</span>:
<span class=“hljs-attribute”>jclouds</span>:<span class=“hljs-attribute”>softlayer</span>:<span class=“hljs-attribute”>tor01</span>: <span class=“hljs-attribute”>customizerType</span>: brooklyn.location.jclouds.ProjectJcloudLocationCustomizer <span class=“hljs-attribute”>privateNetworkOnly</span>: true <span class=“hljs-attribute”>primaryBackendNetworkComponentVlanId</span>: <span class=“hljs-number”>12345</span> <span class=“hljs-attribute”>portSpeed</span>: <span class=“hljs-number”>1000</span> <span class=“hljs-attribute”>dnsZoneId</span>: <span class=“hljs-number”>12345</span> <span class=“hljs-attribute”>netscalerGroup</span>: app1 <span class=“hljs-attribute”>netscalerGroupPort</span>: <span class=“hljs-number”>8080</span> <span class=“hljs-attribute”>netscalerUrl</span>: <span class=“hljs-attribute”>http</span>:<span class=“hljs-comment”>//user:[email protected]/nitro/v1/</span>
|
Services
In the services section of the blueprint, we specified
- That we were deploying a group of servers
- What Brooklyn was to install on each server
- How CPU metrics were to be collected and used
- The parameters of the auto-scaling policy
Here is the application spec:
services: – type: brooklyn<span class=“hljs-class”>.entity</span><span class=“hljs-class”>.group</span><span class=“hljs-class”>.DynamicCluster</span> <span class=“hljs-id”>#group</span> of servers id: cluster name: dynamic cluster initialSize: <span class=“hljs-number”>1</span> <span class=“hljs-id”>#number</span> of servers initially created <span class=”hljs-keyword”>in</span> the group
|
The brooklyn.entity.basic.EmptySoftwareProcess
call was used because Apache Brooklyn only needed to provision servers from an image and no additional installation or configuration was required. This section also specified a sensor – server.cpucount – which periodically collects CPU utilization from the server:
memberSpec: <span class=“hljs-variable”>$brooklyn</span>:entitySpec: name: VMinSL type: brooklyn<span class=“hljs-class”>.entity</span><span class=“hljs-class”>.basic</span><span class=“hljs-class”>.EmptySoftwareProcess</span> brooklyn<span class=“hljs-class”>.initializers</span>: – type: brooklyn<span class=“hljs-class”>.entity</span><span class=“hljs-class”>.software</span><span class=“hljs-class”>.ssh</span><span class=“hljs-class”>.SshCommandSensor</span> brooklyn<span class=“hljs-class”>.config</span>: name: server<span class=“hljs-class”>.cpucount</span> command: <span class=“hljs-string”>“LANG=en_US.UTF-8 sar -u 1 1|grep Average | awk ‘{print 100 – $8}'”</span> targetType: java<span class=“hljs-class”>.lang</span><span class=“hljs-class”>.Double</span> period: <span class=“hljs-number”>10s</span> brooklyn<span class=“hljs-class”>.config</span>: post<span class=“hljs-class”>.launch</span><span class=“hljs-class”>.command</span>: <span class=“hljs-string”>“sudo apt-get install -y sysstat”</span>
|
Metrics
In the metrics section of the blueprint, metrics from individual servers are collected and the average is assigned to the cluster level sensor:
brooklyn<span class=“hljs-class”>.enrichers</span>: – type: brooklyn<span class=“hljs-class”>.enricher</span><span class=“hljs-class”>.basic</span><span class=“hljs-class”>.Aggregator</span> brooklyn<span class=“hljs-class”>.config</span>: enricher<span class=“hljs-class”>.sourceSensor</span>: <span class=“hljs-variable”>$me0</span><span class=“hljs-variable”>$brooklyn</span>:<span class=“hljs-function”><span class=“hljs-title”>sensor</span><span class=“hljs-params”>(<span class=“hljs-string”>“server.cpucount.averaged”</span>)</span></span> enricher<span class=“hljs-class”>.aggregating</span><span class=“hljs-class”>.fromMembers</span>: true transformation: average
|
Auto scaling policies
In this section, auto-scaling policy properties are defined:
brooklyn<span class=“hljs-class”>.policies</span>: – policyType: brooklyn<span class=“hljs-class”>.policy</span><span class=“hljs-class”>.autoscaling</span><span class=“hljs-class”>.AutoScalerPolicy</span> brooklyn<span class=“hljs-class”>.config</span>: metric: <span class=“hljs-variable”>$brooklyn</span>:<span class=“hljs-function”><span class=“hljs-title”>sensor</span><span class=“hljs-params”>(<span class=“hljs-string”>“server.cpucount.averaged”</span>)</span></span> metricLowerBound: <span class=“hljs-number”>10</span> metricUpperBound: <span class=“hljs-number”>60</span> minPoolSize: <span class=“hljs-number”>1</span> maxPoolSize: <span class=“hljs-number”>5</span> minPeriodBetweenExecs: <span class=“hljs-number”>10</span>m resizeUpIterationIncrement: <span class=“hljs-number”>2</span> resizeUpIterationMax: <span class=“hljs-number”>2</span> resizeDownIterationIncrement: <span class=“hljs-number”>2</span> resizeDownIterationMax: <span class=“hljs-number”>2</span>
|
Once the solution was deployed, users were able to seamlessly auto-scale up and down their applications in a timely manner, registering and de-registering the system records with load balancing, DNS, and Chef servers.
This essay originally appeared in the IBM SoftLayer KnowledgeLayer blog.
IBM is a sponsor of InApps.
Feature Image: “YO/OY” sculpture, by Deborah Kass, Brooklyn Bridge Park.
Source: InApps.net
Let’s create the next big thing together!
Coming together is a beginning. Keeping together is progress. Working together is success.