Implementation and Testing of OpenStack Heat
Implementation and Testing of OpenStack Heat
OpenStack Heat
September 2013
Author:
Davide Michelino
Supervisor(s):
Jose Castro Leon
Luis Fernandez Alvarez
Project Specification
CERN is establishing a large scale private cloud based on OpenStack as part of the expansion of
the computing infrastructure for the LHC.
Many cloud based services use auto-scaling and orchestration to expand and contract their
resources according to user load. The OpenStack Heat project provides an open source
framework to organize the configuration and deployment of cloud applications.
After the implementation of a working environment, was tested a sample use case, developing a
template that deploys webservers within an auto scaling group behind a Load Balancer and
serving webpages hosted on a NFS server. Webservers scale up and scale down according to
current load.
Abstract
The aim of this document is to describe the project that was implemented during the openlab
Summer Programme Implementation and testing of OpenStack Heat.
This document gives a quick brief of what Cloud Computing is and which are the technologies
and models used to build a Cloud Computing infrastructure; then it gives an overview on
OpenSatck project.
The main part of this document gives details on how Heat works and how it has been integrated
in the OpenStack project, and gives a reference on how to install and use it.
The last part describes a use case that has been deployed to test Heat features, giving some details
about the template that implement it.
Table of Contents
1
Introduction ..............................................................................................................6
OpenStack ...............................................................................................................7
Heat .........................................................................................................................8
4.1
4.2
4.3
Heat Template............................................................................................................ 11
4.3.1
4.4
4.4.2
4.4.3
4.4.4
5.2
Functions ....................................................................................................... 12
PackStack ...................................................................................................... 21
5.2.2
5.2.3
KeyStone configuration.................................................................................. 23
5.2.4
5.3
5.4
6.1
6.2
6.2.2
6.2.3
6.2.4
Alarms ............................................................................................................ 29
6.2.5
6.2.6
6.2.7
1 Introduction
OpenStack Heat is an incubated OpenStack project that provides cloud orchestration features,
including high availability and auto scaling ones.
Before start to describe OpenStack Heat, will be given an overview about Cloud Computing
technologies with some details on the service model that OpenStack implements (Infrastructure as
a Service).
2 Cloud Computing
Cloud Computing is an expression used to describe a set of computer science technique
and technologies that allow to access to computational and storage resources through a
network. Usually these resources belong to heterogeneous and distributed sets, and they
are served using virtualization technologies.
The aim of Cloud Computing is to abstract the whole infrastructure, composed by
network resources as well as hardware resources, exposing some API (Application
Programming Interface) to users, that communicate with the services that will manage the
cloud.
Figure 1.
6|P a g e
3 OpenStack
OpenStack is a project to provide an IaaS cloud computing service model. The project is
released under the terms of the Apache License and it is managed by the OpenStack
Foundation. Since its first release in July 2010, by NASA and Rackspace effort, more
then 200 companies joined the project.
OpenStack consists of a series of interrelated projects written in python that offer all the
main services an IaaS software should provides. The main core projects belonging to
OpenStack are:
7|P a g e
Figure 2.
4 Heat
Heat is an OpenStack incubated project that provides Orchestration for OpenStack. It
allows describing cloud infrastructure or composed application (see fig. 3), called
stack, in a text file called template.
8|P a g e
Figure 3.
Heat exposes some API that clients can use to send templates to the Heat engine, which
parse them and it will communicate with all OpenStack services to deploy the resources
and create the stack.
Figure 4.
Moreover Heat provides auto scaling and high availability features within the stacks, so it
can automatically add and destroy virtual machines according to the workload and it can
restart services when something stop working correctly.
Figure 5.
From infrastructure side, Heat is composed by three main services: Heat engine, Heat
API and CloudWatch. Heat engine is the core service, it parses templates and provides
9|P a g e
resources, which are the basic elements of a stack; after it parsed a template, it will
deploy and configure the resources in the cloud.
Heat exposes an openstack native restful API and an Amazon AWS Query compatible
API through the Heat API service.
CloudWatch is the service that collects the metrics which virtual machines send to it, in
order to monitor the status of the running stacks. It can manage alarms to trigger some
action when metrics go above or below user defined values, so it provides auto scaling
and high availability features.
All Heat services communicate with a message broker to send message among them, heat
engine is the only service that communicate directly with external openstack services.
Within the instances Heat needs some helper scripts and daemons in order to provide
CloudFormation features.
cfn-tool package provides all the helper scripts and daemons that heat needs in order to
work, and it includes:
cfn-init: the helper script that initialize the instance at boot time, executing
userdata.
cfn-hup: the daemon that periodically checks services status for High Availability,
sends metrics to CloudWatch and execute hooks when events occur.
cfn-push-stats: the helper script that send metrics to CloudWatch service.
cfn-signal: the helper script that sends signals to Heat API.
10 | P a g e
"Parameters" : {
keys and values #usually input parameters
},
"Mappings" : {
keys and values #usually map input parameters with hard-coded strings
},
"Resources" : {
keys and values #heat support the following Resource Types:
AWS::AutoScaling::LaunchConfiguration, AWS::AutoScaling::AutoScalingGroup,
AWS::AutoScaling::ScalingPolicy, OS::Heat::InstanceGroup,
AWS::CloudWatch::Alarm,
AWS::RDS::DBInstance,
AWS::EC2::EIP': ElasticIp, AWS::EC2::EIPAssociation': ElasticIpAssociation,
AWS::EC2::Instance, OS::Heat::HARestarter,
AWS::EC2::InternetGateway, AWS::EC2::VPCGatewayAttachment,
AWS::ElasticLoadBalancing::LoadBalancer,
AWS::EC2::NetworkInterface, AWS::EC2::RouteTable,
AWS::EC2::SubnetRouteTableAssocation,
AWS::S3::Bucket,
AWS::EC2::SecurityGroup,
AWS::CloudFormation::Stack,
AWS::EC2::Subnet,
OS::Swift::Container,
AWS::IAM::User, AWS::IAM::AccessKey, OS::Heat::AccessPolicy,
11 | P a g e
AWS::EC2::Volume, AWS::EC2::VolumeAttachment,
AWS::EC2::VPC,
AWS::CloudFormation::WaitCondition, AWS::CloudFormation::WaitConditionHandle
},
"Outputs" : {
keys and values #are the output values of the stack (eg. webserver ip
address)
}
}
4.3.1 Functions
Heat provides some functions to allow data manipulation within the templates in order to
write dynamic templates. The functions provided are:
Fn::FindInMap: returns the value corresponding to keys into a map declared in the
Mappings template section.
Fn::Base64: returns the Base64 representation of the string, it is useful to pass
encoded UserData to instances.
Fn::Join: appends a set of values into a single value, separated by the specified
delimiter. You can concatenate values using an empty string delimiter. You can
use it to concatenate strings with function outputs.
4.4.1.1 Instance
Instance resource describes a single instance to be deployed in the stack.
How to describe an Instance Resource:
"Resources" : {
"ResourceName": {
"Type": "AWS::EC2::Instance",
"Metadata" : { # Metadata to be injected into the instance
"AWS::CloudFormation::Init" : { # CloudFormation Configuration,
install packages and enable service
12 | P a g e
to
"config" : {
"packages" : {
"yum" : {
"package1"
"package2"
}
},
"services" : {
"systemd" : {
"service1"
: [],
: []
},
"service2"
"service3"
},
}
}
}
}
}
},
"Properties": { # Instance proprieties
"ImageId" : "image-name-to-launch", # Glance Image to start
"InstanceType"
: "Instance-flavor", # Flavor name to use
"KeyName"
: { "Ref" : "KeyName" }, # the Resource Key to be used
for access CloudFormation services
"UserData"
: { "Fn::Base64" : "#!/bin/bash -v\n echo
\"Userdata!\"" } # UserData to inject
}
}
13 | P a g e
"LoadBalancerName" : {
"Type" : "AWS::ElasticLoadBalancing::LoadBalancer",
"Properties" : {
"AvailabilityZones" : { "Fn::GetAZs" : "" },
"Instances" : [{"Ref": "ServerOne"}, {"Ref": "ServerTwo"}, {"Ref":
"ServerThree"}], # List of the instances to balance
"Listeners" : [ {
"LoadBalancerPort" : "80",
# Specifies the port that Load Balancer
will listen on
"InstancePort" : "80",
# Specifies the port to balance
"Protocol" : "HTTP"
# Specifies the protocol to balance
}],
"HealthCheck" : {
# Specifies some parameters to monitor the
servers' health
"Target" : "HTTP:80/",
"HealthyThreshold" : "3",
"UnhealthyThreshold" : "5",
"Interval" : "30",
"Timeout" : "5"
}
}
choosed
14 | P a g e
in
the
"Properties" : {
"InstanceId" : { "Ref" : "InstanceResouceName" } # The instance logic
name
}
}
"FailureAlarmName": {
"Type": "AWS::CloudWatch::Alarm",
"Properties": {
"AlarmDescription": "Alarm Description",
"MetricName": "ServiceFailure", # Collect signals from services within
the instance in order to check the services health
"Namespace": "system/linux",
"Statistic": "SampleCount", # Count signals
"Period": "300",
# Period time in seconds
"EvaluationPeriods": "1", # How many failing periods will trigger the
action
"Threshold": "2",
# How many signals are needed in a Period to fail
it.
"AlarmActions": [ { "Ref": "WebServerRestartPolicy" } ], # Policy to
trigger on Alarm failure
"ComparisonOperator": "GreaterThanThreshold"
}
}
"group"
: "root"
},
"/etc/cfn/cfn-hup.conf" : {
# Configuration of the daemon
that will do periodically checks
"content" : { "Fn::Join" : ["", [
"[main]\n",
"stack=", { "Ref" : "AWS::StackName" }, "\n",
"credential-file=/etc/cfn/cfn-credentials\n",
"region=", { "Ref" : "AWS::Region" }, "\n",
"interval=", { "Ref" : "HupPollInterval" }, "\n"
# Poll
Interval in seconds
]]},
"mode"
: "000400",
"owner"
: "root",
"group"
: "root"
},
"/etc/cfn/notify-on-service-restarted" : {
service Failure
"content" : { "Fn::Join" : ["", [
"#!/bin/sh\n",
"/opt/aws/bin/cfn-push-stats --watch ",
failure signal to the related alarm defined before
{ "Ref" : "FailureAlarmName" },
" --service-failure\n"
]]},
"mode"
: "000700",
"owner"
: "root",
"group"
: "root"
},
Action
on
# Send a
"/tmp/cfn-hup-crontab.txt" : {
# Crontab file that launch
the cfn-hup script
"content" : { "Fn::Join" : ["", [
"MAIL=\"\"\n",
"\n",
"* * * * * /opt/aws/bin/cfn-hup -f\n"
]]},
"mode"
: "000600",
"owner"
: "root",
"group"
: "root"
},
"/etc/cfn/hooks.conf" : {
failure
"content": { "Fn::Join" : ["", [
"[cfn-service-restarted]\n",
"triggers=service.restarted\n",
# When trigger the hook
"path=Resources.InstanceName.Metadata\n",
# Resouce to
monitor
"action=/etc/cfn/notify-on-service-restarted\n",
to trigger
"runas=root\n"
]]},
"mode"
: "000400",
"owner"
: "root",
"group"
: "root"
16 | P a g e
Script
Then you will need some custom UserData to install the crontab file:
"UserData"
: { "Fn::Base64" : { "Fn::Join" : ["", [
"#!/bin/bash -v\n",
"# install cfn-hup crontab\n",
"crontab /tmp/cfn-hup-crontab.txt\n",
]]}}
}
Wait Condition resources are used to triage resources deployment, sending signals when
instance are initialized successfully. In order to use the wait condition we need the
WaitConditionHandle, the WaitCondition resource, the "Depends on" directive whithin
resources and some specific configuration within the instances.
to
the
17 | P a g e
Then we need some custom UserData in order to send signal when the instance starts its
initialization and when it finish its initialization successfully.
"UserData"
: { "Fn::Base64" : { "Fn::Join" : ["", [
"#!/bin/bash -v\n",
"# Helper function\n",
"function error_exit\n",
"{\n",
"
/opt/aws/bin/cfn-signal -e
1 -r \"$1\" '",
"NFSWaitHandle" }, "'\n", # Signal to send in case of failure
" exit 1\n",
"}\n",
"Ref"
setup
complete\"
'",
Auto Scaling Group is the heat feature that allows multiple deployments of the same
instance whitin a "Scaling Group". User can defines policy to scale up and scale down
instances according to the workload. In order to create an Auto Scaling Group user need
to define AutoScalingGroup, ScalingPolicy, Alarm and LaunchConfiguration resources.
18 | P a g e
"LaunchConfigName" : {
"Type" : "AWS::AutoScaling::LaunchConfiguration",
"Metadata" : {
"AWS::CloudFormation::Init" : {
"config" : {
"files" : {
"/etc/cfn/cfn-credentials" : {
# The aws credentials
defined in the tempalte
"content" : { "Fn::Join" : ["", [
"AWSAccessKeyId=", { "Ref" : "ServerKeys" }, "\n",
"AWSSecretKey=", {"Fn::GetAtt": ["ServerKeys",
"SecretAccessKey"]}, "\n"
]]},
"mode"
: "000400",
"owner"
: "root",
"group"
: "root"
},
"/tmp/stats-crontab.txt" : {
# The crontab that will send
metrics to heat external services
"content" : { "Fn::Join" : ["", [
"MAIL=\"\"\n",
"\n",
"* * * * * /opt/aws/bin/cfn-push-stats --watch ",
# Send the
metric specified by the parameter (in this case --mem-util) to heat external
service
{ "Ref" : "UserAlarm1" }, " --mem-util\n",
"* * * * * /opt/aws/bin/cfn-push-stats --watch ",
{ "Ref" : "UserAlarm2" }, " --mem-util\n"
]]},
"mode"
: "000600",
"owner"
: "root",
"group"
: "root"
}
}],
"HealthCheck" : {
# Specifies some parameters to monitor the
servers' health
"Target" : "HTTP:80/",
"HealthyThreshold" : "3",
"UnhealthyThreshold" : "5",
"Interval" : "30",
"Timeout" : "5"
}
}
#
to
The
the
5 Heat Installation
OpenStack Heat has been installed using RDO repository on Scientific Linux Cern 6.4,
while the OpenStack testing environment has been installed using PackStack.
PackStack is a tool for set up a quick and full installation of OpenStack usung puppet
modules. Using PackStack you can install the infrastructure on several servers or deploy
an all-in-one installation.
21 | P a g e
If you don't have a password-enabled root account, add the local public key to the
authorized_key file
# cd /root/.ssh; cat id_rsa.pub >> authorized_keys
If you want to test you OpenStack installation, download this test image and add it to
glance
#
wget
-c
https://launchpad.net/cirros/trunk/0.3.0/+download/cirros-0.3.0x86_64-disk.img -O cirros.img
#
glance
image-create
--name=cirros-0.3.0-x86_64
--disk-format=qcow2
-container-format=bare < cirros.img
Now you can install all heat packages and dependencies (it will provides mainly the
services heat-api, heat-api-cfn, heat-api-cloudwatch and heat-engine)
# yum install openstack-heat-* MySQL-python
Heat from rdo requires a local mysql server, if there isn't any mysql server installed,
this script is going to install, create and poupulate the database
$MYSQL-ROOT-PASSWORD: will be the mysql root password, if you have already
a mysql server installed, enter the right password
22 | P a g e
Now you have to add the user, services and endpoints for heat on the Identity Service
Add the heat user
$HEAT_USER_PASSWORD_OF_CHOICE: a password for heat user on the
keystone
$SERVICES_TENANT_NAME: your services tenant on the keystone (you can use
the command 'keystone tenant-list' to get it)
# keystone user-create --name heat --pass $HEAT_USER_PASSWORD_OF_CHOICE
#
keystone
user-role-add
--user
heat
--role
admin
--tenant
$SERVICES_TENANT_NAME
Add endpoints
$HEAT_CFN_SERVICE_ID and $HEAT_SERVICE_ID are the service ids of the
services previously created. You can get them by running the 'keystone service-list'
command.
$HEAT_CFN_HOSTNAME and $HEAT_HOSTNAME are heat host hostname or IP
address
# keystone endpoint-create --region RegionOne --service-id $HEAT_CFN_SERVICE_ID
--publicurl
"http://$HEAT_CFN_HOSTNAME:8000/v1"
--adminurl
"http://$HEAT_CFN_HOSTNAME:8000/v1"
--internalurl
"http://$HEAT_CFN_HOSTNAME:8000/v1"
# keystone endpoint-create --region RegionOne --service-id $HEAT_SERVICE_ID -publicurl
"http://$HEAT_HOSTNAME:8004/v1/%(tenant_id)s"
--adminurl
"http://$HEAT_HOSTNAME:8004/v1/%(tenant_id)s"
--internalurl
"http://$HEAT_HOSTNAME:8004/v1/%(tenant_id)s"
23 | P a g e
Make sure that the following variables (in all heat-*-paste.ini files) are pointing to
keystone host
service_host = $KEYSTONE_HOSTNAME
auth_host = $KEYSTONE_HOSTNAME
auth_uri = http://$KEYSTONE_HOSTNAME:35357/v2.0
keystone_ec2_uri = http://$KEYSTONE_HOSTNAME:5000/v2.0/ec2tokens
Now create the role used by heat to receive the progress data in according to
heat_stack_user_role option in /etc/heat/heat-engine.conf (default is heat_stack_user)
keystone role-create --name heat_stack_user
Start the test stack (you will need a valid keypair in OpenStack)
24 | P a g e
#
heat-cfn
create
$STACK-NAME
--templatefile=WordPress_Single_Instance.template
-parameters="DBUsername=wp;DBPassword=wpass;KeyName=test;InstanceType=m1.small;L
inuxDistribution=F18"
First of all is useful to install the heat client, it provides better outputs then heat-cfn
client and it can be used from any host on the network.
# yum install python-heatclient python-heatclient-doc
Start a stack
# heat stack-create -f templatename.template -P
"KeyName=mykey;InstanceType=m1.tiny;LinuxDistribution=F17"
stack-name
List stacks
# heat stack-list
Describe a stack
# heat describe stack-name
Delete a stack
# heat stack-delete stack-name
6 Use case
This use case template deploys some webservers within an auto scaling group and defines
policies that scale up and scale down the number of webservers according to their
memory usage. All the webservers serve pages from a common nfs mountpoint, hosted
on a dedicated nfs server and clients can access the webservers through a load balacer
that distribuite the load within the auto scaling group.
25 | P a g e
Figure 6.
Use case
26 | P a g e
MEMAlarmLow
WebServerScaleDownPolicy
WebServerScaleUpPolicy
[!] Resources that create VMs
It's the resource that deploys the webservers in the auto scaling group. It waits that the
NFSWaitCondition resource is ready.
"WebServerGroup" : {
"Type" : "AWS::AutoScaling::AutoScalingGroup",
"DependsOn" : "NFSWaitCondition",
"Properties" : {
"AvailabilityZones" : { "Fn::GetAZs" : ""},
"LaunchConfigurationName" : { "Ref" : "WebServerLaunchConfig" },
"MinSize" : "2",
"MaxSize" : "8",
"LoadBalancerNames" : [ { "Ref" : "WebServerLoadBalancer" } ]
}
It's the resource that describe the configuration of each WebServer that the stack will
deploy within the Auto Scaling Group.
"WebServerLaunchConfig" : {
"Type" : "AWS::AutoScaling::LaunchConfiguration",
"Metadata" : {
"AWS::CloudFormation::Init" : {
"config" : {
"files" : {
"/etc/cfn/cfn-credentials" : {
"content" : { "Fn::Join" : ["", [
"AWSAccessKeyId=", { "Ref" : "WebServerKeys" }, "\n",
"AWSSecretKey=", {"Fn::GetAtt": ["WebServerKeys",
"SecretAccessKey"]}, "\n"
]]},
"mode"
: "000400",
"owner"
: "root",
"group"
: "root"
},
"/tmp/stats-crontab.txt" : {
"content" : { "Fn::Join" : ["", [
"MAIL=\"\"\n",
"\n",
"* * * * * /opt/aws/bin/cfn-push-stats --watch ",
{ "Ref" : "MEMAlarmHigh" }, " --mem-util\n",
"* * * * * /opt/aws/bin/cfn-push-stats --watch ",
{ "Ref" : "MEMAlarmLow" }, " --mem-util\n"
]]},
"mode"
: "000600",
"owner"
: "root",
"group"
: "root"
27 | P a g e
},
"/tmp/index.html" : {
"content" : { "Fn::Join" : ["", [
"<html>\n",
"<body>\n",
"Nfs server offline\n",
"</body>\n",
"</html>\n"
]]},
"mode"
: "000400",
"owner"
: "root",
"group"
: "root"
},
"/tmp/nfs-site.conf" : {
"content" : { "Fn::Join" : ["", [
"<VirtualHost *:80>\n",
"
ServerAlias /\n",
"
ServerAdmin root@localhost\n",
"
DocumentRoot /var/www/html/nfs\n",
"
DirectoryIndex index.html\n",
"</VirtualHost>\n"
]]},
"mode"
: "000400",
"owner"
: "root",
"group"
: "root"
}
},
"packages" : {
"yum" : {
"httpd"
: [],
"nfs-utils"
: []
}
},
"services" : {
"sysvinit" : {
"httpd"
: { "enabled" : "true", "ensureRunning" : "true" },
"crond"
: { "enabled" : "true", "ensureRunning" : "true" },
"iptables"
: { "enabled" : "false", "ensureRunning" :
"false" }
}
}
}
}
},
"Properties": {
"ImageId" : {
"LinuxDistribution" },
"Fn::FindInMap"
"DistroArch2AMI",
"Ref"
28 | P a g e
6.2.4 Alarms
It describes the resources that will trigger the scale up and down policies.
"MEMAlarmHigh": {
"Type": "AWS::CloudWatch::Alarm",
"Properties": {
"AlarmDescription": "Scale-up if MEM > 50% for 1 minute",
"MetricName": "MemoryUtilization",
"Namespace": "system/linux",
"Statistic": "Average",
"Period": "60",
"EvaluationPeriods": "1",
"Threshold": "75",
"AlarmActions": [ { "Ref": "WebServerScaleUpPolicy" } ],
"Dimensions": [
{
"Name": "AutoScalingGroupName",
"Value": { "Ref": "WebServerGroup" }
29 | P a g e
}
],
"ComparisonOperator": "GreaterThanThreshold"
}
},
"MEMAlarmLow": {
"Type": "AWS::CloudWatch::Alarm",
"Properties": {
"AlarmDescription": "Scale-down if MEM < 15% for 1 minute",
"MetricName": "MemoryUtilization",
"Namespace": "system/linux",
"Statistic": "Average",
"Period": "60",
"EvaluationPeriods": "1",
"Threshold": "50",
"AlarmActions": [ { "Ref": "WebServerScaleDownPolicy" } ],
"Dimensions": [
{
"Name": "AutoScalingGroupName",
"Value": { "Ref": "WebServerGroup" }
}
],
"ComparisonOperator": "LessThanThreshold"
}
},
"NFSServer": {
"Type": "AWS::EC2::Instance",
"Metadata" : {
"AWS::CloudFormation::Init" : {
"config" : {
"packages" : {
"yum" : {
"nfs-utils"
: []
}
},
"services" : {
"sysvinit" : {
"nfs"
: { "enabled" : "true", "ensureRunning" : "true" },
"rpcbind"
: { "enabled" : "true", "ensureRunning" : "true" },
"nfslock"
: { "enabled" : "true", "ensureRunning" : "true" },
"iptables"
: { "enabled" : "false", "ensureRunning" : "false"
}
}
},
"files" : {
"/etc/cfn/cfn-credentials" : {
"content" : { "Fn::Join" : ["", [
"AWSAccessKeyId=", { "Ref" : "WebServerKeys" }, "\n",
"AWSSecretKey=", {"Fn::GetAtt": ["WebServerKeys",
"SecretAccessKey"]}, "\n"
]]},
"mode"
: "000400",
30 | P a g e
"owner"
"group"
: "root",
: "root"
},
"/etc/cfn/cfn-hup.conf" : {
"content" : { "Fn::Join" : ["", [
"[main]\n",
"stack=", { "Ref" : "AWS::StackName" }, "\n",
"credential-file=/etc/cfn/cfn-credentials\n",
"region=", { "Ref" : "AWS::Region" }, "\n",
"interval=", { "Ref" : "HupPollInterval" }, "\n"
]]},
"mode"
: "000400",
"owner"
: "root",
"group"
: "root"
},
"/tmp/cfn-hup-crontab.txt" : {
"content" : { "Fn::Join" : ["", [
"MAIL=\"\"\n",
"\n",
"* * * * * /opt/aws/bin/cfn-hup -f\n"
]]},
"mode"
: "000600",
"owner"
: "root",
"group"
: "root"
},
"/etc/exports" : {
"content": { "Fn::Join" : ["", [
"/nfs/www
192.168.32.0/255.255.255.0(ro,sync,wdelay,hide,nocrossmnt,secure,root_squash,no
_all_squash,no_subtree_check,secure_locks,acl,anonuid=65534,anongid=65534)\n"
]]},
"mode"
: "000644",
"owner"
: "root",
"group"
: "root"
},
"/tmp/index.html" : {
"content": { "Fn::Join" : ["", [
"<html>\n",
"<body>\n",
"nfs site!\n",
"</body>\n",
"</html>\n"
]]},
"mode"
: "000444",
"owner"
: "root",
"group"
: "root"
}
}
}
}
},
"Properties": {
"ImageId" : {
"LinuxDistribution" },
31 | P a g e
"Fn::FindInMap"
"DistroArch2AMI",
"Ref"
"Ref"
32 | P a g e
This is stack output, it will return the Load Balancer's url that users can use to access to
the webservers.
"Outputs" : {
"PublicIp": {
"Description": "LoadBalancer IP",
"Value" :
{ "Fn::Join" : [ "", [ "http://",
"WebServerLoadBalancer", "DNSName" ]}, "/"]] }
}
}
}
33 | P a g e
"Fn::GetAtt"