To create a 3-tiered production-like deployment from scratch using ServerTemplates published by RightScale for a PHP application.
Note: This tutorial uses RightScale's latest revisions of the v13 Infinity ServerTemplates that use Chef cookbooks and recipes instead of RightScripts.
Table of Contents
Although this end-to-end tutorial was originally designed as a hands-on exercise in an Instructor Led Training course, anyone can follow the tutorial and use it as a learning tool as well. The class environment influences naming conventions, hence we often precede names with initials or names in our examples. (For example, an A Record for John Doe named "jd-www", rather than simply "www"). Be sure to provide enough time for yourself to complete the end-to-end exercise. (Estimate: 1-3hrs)
This tutorial will demonstrate how to build a common 3-tier website architecture in the cloud using several of RightScale's ServerTemplates.
Disclaimers
It's recommended that you create a new deployment (Manage > Deployments) for each new project or reference architecture that you're going to build because you do not want to accidentally inherit any unknown configuration settings.
See Create a New Deployment. (Requires 'actor' user role privileges.)
Tip: It's recommended that you create a bookmark to the deployment's Servers tab for quick navigation back to the deployment at any time.
Prerequisites: Requires 'actor' user role privileges in the RightScale account to create SSH Keys and Elastic IPs, and 'security_manager' privileges to create/modify security groups.
Each cloud infrastructure is unique and requires different resources in order to launch a server in their cloud. Depending on the type of cloud infrastructure that you're going to use to launch servers, you will find it useful to create some of the required cloud-specific resources beforehand so that you can select them in the "Add Server Wizard" when you add servers into a deployment. Some cloud resources are also region-specific. For example, you cannot launch an EC2 instance in the 'us-east' region with a 'us-west' security group.
If the cloud does not require the use an SSH Key, you can ignore this step.
SSH Keys are used for authentication purposes to create SSH console sessions for root level access to the instance. Although you are required to associate an SSH Key to a server before you can launch it, the private key material is no longer required if managed SSH (Server Login Control) is enabled for the account (Settings > Account Settings > SSH). By default, Server Login Control is enabled at the account level, where a user's own unique RSA key pair (Settings > User Settings > SSH) is used for authentication purposes for establishing SSH console sessions on all RightLink-enabled instances.
You can either use an existing SSH Key or create a new one.
If the cloud does not support Security Groups, you can ignore this step.
Security groups are firewall settings that apply to instances within a cloud at the infrastructure layer. Security groups are typically used to control ingress communication (i.e. inbound communication to an instance over a particular port and protocol) however, some clouds support the use of security groups to also control egress communication (i.e. outbound requests from the instance). Once you create a security group you can create different firewall rules that control the level of access to instances launched with that particular security group(s). Firewall rules are enforced at the cloud (infrastructure) level using IP-based or Group-based permissions.
If you are building this deployment for demonstration and testing purposes, you can simply create a single security group for all servers in your deployment.
The steps for creating a single security group are different depending on the type of account and cloud that you are using.
Once you are successful setting up your first multi-tier deployment you can set up more secure firewall permissions that would be more realistic for production environments. See Configuring multiple Security Groups for a multi-tiered Deployment.
Some clouds support the use of public IP addresses that you can associate with a server at launch time or remap to another running server, as necessary for lifecycle management scenarios. It's recommended that you use this service, if available for front-end load balancer or web servers that are designed to be public facing. If you're using dedicated HAProxy load balancer servers, you should create/reserve one IP address for each load balancer server. Typically, you will have two HAProxy load balancer servers for high-availability and failover purposes. If you are using a cloud's load balancing service such as Amazon Elastic Load Balancers (ELB) or Rackspace Cloud Load Balancers (CLB) you cannot assign remappable IP addresses. In such cases, skip this step.
In a typical 3-tier architecture setup, DNS A records are used to create fully qualified domain names (FQDNs) that map to a particular server or tier of servers. The diagram below shows a typical example of a 3-tier website architecture.
In this type of architecure, the application servers and any "slave" database servers locate the "master" database server by using Master-DB's FQDN (e.g. db-master.example.com), which points to the Master-DB's private IP address. Similarly, front-end web traffic can be routed to a FQDN (e.g. www.example.com) where each load balancer server has a DNS record for that FQDN so that incoming requests are routed to one of the load balancer servers. Since the IP address of an instance in the cloud is often dynamically assigned at launch time, you are required to use a DNS provider that supports dynamic DNS (i.e. the ability to dynamically update the IP address of an A record) for the Master-DB server (at a minimum). You can also use the same DNS provider for creating FQDNs for the load balancer servers. However, since they do not require the use of dynamic DNS, any DNS provider can be used.
TTLs
When you create the DNS records, it's important to set appropriate TTLs to ensure that servers will not stay connected to an old IP address that is no longer assigned to a functional server. For example, the DNS record that points to the "master" database server should have a low TTL to ensure that the application servers will connect to the correct server within a reasonable amount of time. It's strongly recommended that you use a TTL of 60 seconds for the DNS record that points to the "master" database server. If you are also creating DNS records for the front-end load balancer servers, you can use a more conservative TTL than the database tier. (e.g. 1800 seconds)
Note: If you are using Rackspace's Cloud DNS service, you must use a TTL of 300 seconds because that is the lowest allowable TTL. Be sure to change the 'Database DNS TTL Limit' input from 60 (default) to 300.
You will need to create DNS records for the following servers:
RightScale's ServerTemplates contain scripts that support one of the following DNS providers. Create an account with one of the DNS providers below and set up the A records accordingly.
Prerequisites: Requires 'designer' user role privileges in the RightScale account to create a new credential.
Important!
Only the user who created the credential and any 'admin' users will be able to view and modify an existing credential.
Credentials are a way of passing sensitive information to a script (as an input) in a discrete manner without making the actual value visible in the Dashboard. As a best practice, many of the ServerTemplates published by RightScale are preconfigured to use certain credentials. It's recommended that you create these common credentials in your own account. If they already exist and apply to a different deployment, you might want to create a new set of credentials to avoid any conflicts. In such cases, it's helpful to use a common prefix to group the credentials together. (e.g. APP1_DBADMIN_USER)
If you try to launch a server where one of the inputs references a credential that does not exist in the RightScale account, you will receive an error message and will not be able to launch the server. Therefore, it's best to create any required credentials before you configure and launch a server. Depending on your cloud provider and backup storage selections, you may want to create additional credentials.
At a minimum, create the following credentials. See Create a New Credential for more information.
If you are going through a 3-tier tutorial you should create the following credentials with your own values or you can use the example values, if desired.
* If you use Amazon Route 53 or Rackspace Cloud DNS as your DNS provider, you do not need to set up separate DNS user name and password credentials because your cloud credentials are used for authentication purposes.
ServerTemplates published by RightScale have built-in support for several remote object storage (ROS) solutions. Valid cloud credentials are required to retrieve "private" files from an ROS container, create a new container, or store files in a container (such as a binary database backup files).
Set up your desired ROS service(s) and create the recommended user-defined credentials, which you will use when you define inputs for your deployments.
If you are using a source control management (SCM) system to host your application code, you will need to create the appropriate credentials to retrieve your source code from the specified repository.
You can also download application source code from rsync sources.
If you are using SSL to support HTTPS access, you should create credentials for any of the following values that apply. See How do I create an SSL certificate for my web server?
If you are using the public network to connect to the master database server, it's recommended that you use SSL to encrypt the data being transfered between the master database server and the associated slave and/or application servers. Note: SSL is currently only supported in the Database Manager for MySQL 5.1/5.5 ServerTemplates.
The ServerTemplate contains scripts that can retrieve a database dump file from a container in one of the supported Remote Object Storage (ROS) providers (e.g. Amazon S3, Rackspace Cloud Files). See Database Dump Retrieval.
Create a new bucket/container and upload your database dump file. The file can remain a 'private' object because your cloud credentials can be used (as inputs) for authentication purposes to retrieve the file. Make sure the uploaded file maintains the .gz file extension.
Warning! The filename of the PostgreSQL dump file cannot contain a dash (-) in its prefix name. For example, if your dump file is named, 'my-app-201205030022.gz', you must manually rename it to be 'my_app-201205030022.gz' where you use an underscore (_) to replace the dash, otherwise the script (do::do_dump_import) that imports the database dump file into the instance will fail.
If you are setting up a database server for testing purposes or if you do not have your own dump file, you can use the following sample PostgreSQL dump file to complete the tutorial. The sample is a gzip (.gz) file.
Follow these steps to add a database server to the deployment.
The next step is to define the properties of your database server or servers by entering values for inputs. It is simplest and best to do this at the deployment level. For a detailed explanation of how inputs are defined and used in Chef recipes and RightScripts, see Understanding Inputs.
The inputs that you need to provide values for will depend on which options you're going to use. The ServerTemplate is very flexible and supports a variety of different configurations. You must provide values for the required inputs based on the chosen options.
Go to the deployment's Inputs tab (Manage > Deployments > your deployment > Inputs) and click Edit.
Although you can enter values for missing inputs as text values, it's strongly recommended that you set up credentials for passing sensitive information to scripts such as passwords or any other sensitive data.
Rackspace only
If you use Rackspace for your database servers and backup storage (i.e., Cloud Files) the storage-related Chef recipes will use Rackspace Service Net (SNET) by default. SNET is Rackspace's internal private networking service for optimized communication between Rackspace Cloud Servers and Cloud Files. If SNET is not supported in your Rackspace environment, you must set the "Rackspace SNET Enabled for Backup" input to false; otherwise, all backup and restore operations that rely on Cloud Files will fail.
If the cloud supports the use of mountable volumes (e.g. AWS EBS Volumes, CloudStack volumes, etc.), primary backups will be saved as volume snapshots. It's strongly recommended that you use volumes to store the contents of the PostgreSQL database for efficiency and performance reasons.
However, if the cloud does not support mountable volumes (e.g. Rackspace First Generation), primary backups must be saved to a Remote Object Storage location. In such cases, the contents of the PostgreSQL database will be stored locally on the instance's ephemeral drive. Backups of the database will be stored as binary dump files to the specified object storage container.
Required
Input Name | Description | Example Value |
Number of Volumes in the Stripe (1) | To use striped volumes with your databases, specify a volume quantity. The default is 1, indicating no volume striping. Ignored for clouds that do not support volume-based storage (e.g. Rackspace Legacy/First Generation). | text: 1 |
Total Volume Size (1) | Specify the total size, in GB, of the volume or striped volume set used for primary storage. If dividing this value by the stripe volume quantity does not yield a whole number, then each volume's size is rounded up to the nearest whole integer. For example, if "Number of Volumes in the Stripe" is 3 and you specify a "Total Volume Size" of 5 GB, each volume will be 2 GB. If deploying on a CloudStack-based cloud that does not allow custom volume sizes, the smallest predefined volume size is used instead of the size specified here. This input is ignored for clouds that do not support volume storage (e.g., Rackspace Legacy/First Generation). Important: The value for this input does not describe the actual amount of space that's available for data storage because a percent (default: 90%) is reserved for taking LVM snapshots. Use the 'Percentage of the LVM used for data (1)' input to control how much of the volume stripe is used for data storage. Be sure to account for additional space that will be required to accomodate the growth of your database. | text: 10 NOTE: For Rackspace Open Cloud, the minimum volume size is 100 GB |
Percentage of the LVM used for data (1) | The percentage of the total Volume Group extents (LVM) that is used for data storage. The remaining percent is reserved for taking LVM snapshots. (e.g. 75 percent - 3/4 used for data storage and 1/4 remainder used for overhead and snapshots) WARNING! If the database experiences a large amount of writes/changes, LVM snapshots may fail. In such cases, use a more conservative value for this input. (e.g. 50%) | text: 90% |
Advanced
Input Name | Description | Example Value |
Primary Backup Storage Cloud (default) | Input is ignored if volumes are supported. If the instance is launched into a cloud that does not support volumes, you must specify which ROS solution to use for storing primary backups. Backups are saved as binary dump files to a container that matches the value specified for the Backup Lineage Name input. If a matching container does not exist, one will be created.
| No value/Ignore text: s3 |
Primary Backup Secret (default)
| Input is ignored if volumes are supported. Required cloud credential to store a file in the ROS location specified by the Primary Backup Storage Cloud (default) input.
| No value/Ignore cred: AWS_SECRET_ACCESS_KEY |
Primary Backup User (default) | Input is ignored if volumes are supported. Required cloud credential to store a file in the ROS location specified by the Primary Backup Storage Cloud (default) input.
| No value/Ignore cred: AWS_ACCESS_KEY_ID |
Secondary Backup Storage Cloud (default) | The cloud provider of the specified ROS container where the secondary backup will be stored.
| text: cloudfiles |
Secondary Backup Secret (default) | Required cloud credential to store a file in the ROS location specified by the Secondary Backup Storage Cloud (default) input.
| cred: RACKSPACE_AUTH_KEY |
Secondary Backup User (default) | Required cloud credential to store a file in the ROS location specified by the Secondary Backup Storage Cloud (default) input.
| cred: RACKSPACE_USERNAME |
Secondary Backup Storage Container (1) | Name of the ROS container to use for secondary backups. | text: postgresqlbackups |
Block Device Mount Directory (1) | Input is ignored if volumes are not supported. For cloud providers supporting volume-based storage, the mount point for your backup volume or volumes. (Default is /mnt/storage.) | text: /mnt/storage |
Nickname (1) | Input is ignored if volumes are not supported. For cloud providers supporting volume-based storage, the nickname will be used to name the created volumes and snapshots along with an epoch timestamp. (e.g. data_storage-201203100927) By default, this input is set to 'data_storage' however it's recommended that you create a nickname that describes your application or deployment, which will make it easier to identify the created volumes and snapshots. | text: my_deployment |
Input Name | Description | Example Value |
Database Admin Password Database Admin Username | Username and password of a database user with administrator privileges. The admin username and password are used for tasks that require administrator access to the database. | cred: DBADMIN_PASSWORD cred: DBADMIN_USER |
Database Application Password Database Application Username | Username and password of a database user with user-level privileges. The application username and password allow the application to access the database in a restricted fashion. | cred: DBAPPLICATION_PASSWORD cred: DBAPPLICATION_USER |
Database Backup Lineage | The name associated with your primary and secondary database backups. It's used to associate them with your database environment for maintenance, restore, and replication purposes. Backup snapshots will automatically be tagged with this value. (e.g. rs_backup:lineage=postgresqlbackup) Backups are identified by their lineage name. Note: For servers running on Rackspace Legacy/First Gen, this value also indicates the Cloud Files container to use for storing primary backups. If a Cloud Files container with this name does not already exist, one will automatically be created. | text: postgresqlbackup |
Database Master FQDN | The fully qualified domain name that points to the master database server. Slave database servers and application servers will use the FQDN to locate the "master" database server. Typically, the DNS record will point to the Master-DB server's private IP address. | text: master-db.example.com |
Database Master DNS Record ID | The record ID or hostname used to identify your master database server to your DNS provider. See Deployment Prerequisites (Linux) for more information. Examples:
| text: 1234567 |
Database Replication Password Database Replication User | Username and password of a database user with replication permissions on the PostgreSQL server. The replication username and password are used for replication between the "master" and "slave" database servers. | cred: DBREPLICATION_PASSWORD cred: DBREPLICATION_USER |
Database DNS TTL Limit | The specified TTL limit of the database servers' dynamic DNS records. It's recommended that you use a low TTL for your database servers DNS records to promote quick failovers. The default is set to 60 (seconds). If you are using Rackspace's Cloud DNS service for Rackspace cloud servers, set this value to 300 (which is the lowest allowable TTL for Cloud DNS). | text: 60 text: 300 (Cloud DNS only) |
Force Promote to Master | Determines whether or not the slave checks if there is a current running master database server and changes the current master into a slave after a database server promotion. This input applies to scripts and cookbooks that use the db::do_promote_to_master operational script.
| text: false |
Input Name | Description | Example Value |
DNS Service Provider | Select the DNS provider that you used to create the DNS records for the database servers.
| text: DNSMadeEasy |
DNS Password | The password/key required to update the DNS record of a master/slave database server with the specified DNS service provider.
| cred: DNS_PASSWORD |
DNS User | The username required to update the DNS record of a master/slave database server with the specified DNS service provider.
| cred: DNS_USER |
Cloud DNS region | If 'CloudDNS' is the chosen 'DNS Service Provider', select the appropriate cloud region based on the location of the Rackspace cloud servers. Note: This input is ignored unless you are using CloudDNS. | text: Chicago |
After configuring your inputs, launch your newly configured master database server.
Wait for the server to reach the "operational" state before you run a script to initialize the database server.
The script performs the following actions:
Since you have not loaded an actual database onto the server there is no reason to create a primary backup of the database.
Go to the "current" server's Scripts tab and run the db::do_primary_backup_schedule_disable operational script to disable your scheduled backups (cron jobs).
Later, once you have imported your database you will reverse this action and enable continuous backups.
After initializing the master database server and disabling scheduled backups, you will need to add your database (or databases) and records to it.
Note: If you use a previous backup snapshot instead of a PostgreSQL dump file or initialize a blank PostgreSQL database, refer to the Database Manager for PostgreSQL 9.1 Beta (v13 Infinity) - Runbook for instructions.
Input Name | Description | Example Value |
Dump Container | Name of the ROS container that contains the PostgreSQL database dump file. | text: postgresqldumps |
Database Schema Name | Name of the PostgreSQL database schema to restore from the PostgreSQL dump file identified by the "Dump Prefix" input. This name is set when you import the dump file into PostgreSQL. The name is only defined within the PostgreSQL instance and not within the actual dump file. As a result the name is somewhat arbitrary but should be descriptive. Important! | text: my_db_schema
For the 'app_test-20121603072614.gz' PostgreSQL dump file: text: app_test |
Dump Prefix | The prefix of the PostgreSQL dump file (without the associated .gz extension) to retrieve from the Remote Object Store location specified in "Dump Container." You can specify either the entire file name including the timestamp or just the file prefix without the timestamp, which selects the most recent dump file with that prefix. Example: If your dump file is named "mydb-20121603072614.gz," you could specify either "mydb-20121603072614" or "mydb." | For the provided sample dump file: text: app_test |
Dump Storage Account ID | Required cloud credential to retrieve a private file from the specified ROS location. Set to 'Ignore' if the file is publicly accessible.
| cred: AWS_ACCESS_KEY_ID cred: RACKSPACE_USERNAME
|
Dump Storage Account Secret | Required cloud credential to retrieve a private file from the specified ROS location. Set to 'Ignore' if the file is publicly accessible.
| cred: AWS_SECRET_ACCESS_KEY cred: RACKSPACE_AUTH_KEY |
Dump Storage Account Provider | The remote object storage provider where your PostgreSQL dump file is stored.
| text: s3 |
You are now ready to create the first primary backup of the database. You will need a completed backup in order to initialize a slave database server.
It is now safe to enable continuous backups of the database server.
For more information about configuring and modifying your scheduled backup policy, see the Database Manager for PostgreSQL 9.1 Beta (v13 Infinity) - Runbook.
Although you can run PostgreSQL in single-server mode and having a separate slave server for replication purposes is not required, this is strongly recommended for failover purposes. Create a slave server in your deployment.
Make sure the following conditions are true before you launch the second database server.
You are now ready to launch a "slave" database server for failover and redundancy purposes.
DB (advanced)
Input Name | Description | Example Value |
Init Slave at Boot | Set to 'True' to have the instance initialize with a running master database server as a "slave" on boot. | text: true |
The scripts perform the following actions:
If you created a DNS record for the slave database server, you can set a value for the Database Slave DNS Record ID input and run the db::do_set_dns_slave operational script.
Follow these steps to add a load balancer server to the deployment.
For production environments, it's strongly recommended that you have at least two load balancer servers (preferably in different availability zones or datacenters) for redundancy purposes. The easiest way to create a second load balancer is to simply clone and modify the first load balancer server.
The next step is to define the properties of your load balancer server or servers by entering values for inputs. As a best practice, you should define required inputs for the servers at the deployment level. For a detailed explanation of how inputs are defined and used in Chef recipes and RightScripts, see Inputs and their Hierarchy.
To enter inputs for the Chef recipes that will run on your load balancers, open the deployment's Inputs tab, click Edit, and use the following settings to configure input values. We recommend that you set up credentials for password values and any other sensitive data as shown in the examples.
Input Name | Description | Example Value |
Load Balance Pools | Comma-separated list of URIs or FQDNs for which the load balancer will create server pools to answer website requests. The last entry will be the default backend and will answer for all URIs and FQDNs not listed here. A single entry of any name (for example, default) will mimic basic behavior of one load balancer with one pool of application servers. This will be used for naming server pool backends. Note: Application servers can provide any number of URIs or FQDNs to join corresponding server pool backends (for example, www.mysite.com, api.mysite.com, /serverid, default). | text: www.mysite.com, api.mysite.com
For the standalone and 3-tier tutorials, use: text:default |
Load Balancing Algorithm | Defines which load balancing algorithm is used to establish connections with application servers in the load balancing pool.
| text: roundrobin |
Use Session Stickiness | Determines session stickiness. Set to 'True' to use session stickiness, where the load balancer will reconnect a session to the last server it was connected to (via a cookie). Set to 'False' if you do not want to use sticky sessions; the load balancer will establish a connection with the next available server. | text: true |
HAProxy SSL Certificate | PEM formatted string containing SSL certificates and keys for SSL encryption. To configure HAProxy without SSL encryption, do not set this input. | nil |
Statistics Page Password | Password to access HAProxy statistics page | nil |
Statistics URI | HAProxy statistics URI | text: /haproxy-status |
Statistics Page Username | The username that is required to access the load balancer statistics report page | nil |
If you are using Elastic IPs or already know the public IP addresses that will be used by the load balancer servers, you might have already set up the DNS records for the load balancing tier. However, if you do not know the public IP addresses that will be assigned to the load balancer servers, you must manually set up the DNS records after the servers have been launched. Once the servers become operational (and have been assigned their respective public IP addresses), create or update the DNS records with your DNS provider. Each load balancer server should have its own DNS record with the same hostname (e.g. www.example.com) that points to its public IP address.
The DNS records for the HAProxy load balancing tier should direct traffic from the associated hostname (FQDN) (e.g. www.example.com) to the application servers in its load balancing pool.
Follow these steps to add a load balancer server to the deployment.
The next step is to define the properties of your application balancer server or servers by entering values for inputs. As a best practice, you should define required inputs for the servers at the deployment level. For a detailed explanation of how inputs are defined and used in Chef recipes and RightScripts, see Inputs and their Hierarchy.
To enter inputs for the Chef recipes that will run on your load balancers, open the deployment's Inputs tab, click Edit, and use the following settings to configure input values. We recommend that you set up credentials for password values and any other sensitive data as shown in the examples.
Input Name | Description | Example |
Application Name | The name of the application. This name is used to generate the path of the application code and to determine the backend pool in a load balancer server that the application server will be attached to. Application names can have only alphanumeric characters and underscores. | text: example |
Application Repository URL | The repository location to download application code.. | |
Application Repository Revision | The revision of application code to download from the repository. | text: unified_php |
Virtual Host Name/Path | The virtual host served by the application server. The virtual host name can be a valid domain/path name supported by the access control lists (ACLs) in a load balancer. Ensure that no two application servers in the same deployment having the same application name have different vhost paths. Example: http:://www.example.com, /index | text: http://www.example.com, /index |
Now that you have finished defining server details, you are ready to launch a server in the cloud with the new settings. Click the server's Launch button.
Review the inputs that you set at the Inputs confirmation page and click Launch.
Once all of the servers are operational you can perform the following tests.
If you set up your DNS records and firewall permissions (e.g. security groups) correctly, incoming web requests to your hostname (e.g. www.example.com) will be sent to one of the load balancer servers. HAProxy will then take the request and forward it to one of the application servers in its load balancing pool.
Based on your DNS records, enter the hostname (FQDN) associated with your load balancer servers into a browser window. (e.g. www.example.com) You should see your application's default landing page. If you are using the sample PHP application from RightScale, you should see the following landing page.
To replace the static application servers in the deployment (under the deployment's Servers tab) with a scalable server array for dynamically autoscaling the application tier, follow the Add a Scalable Application Server Array to a Deployment tutorial.
If you completed the tutorial for testing purposes and no longer need the running servers, follow the steps below to safely shutdown the deployment.
© 2006-2014 RightScale, Inc. All rights reserved.
RightScale is a registered trademark of RightScale, Inc. All other products and services may be trademarks or servicemarks of their respective owners.