Chapter 9
Configuration as Code

THE AWS CERTIFIED DEVELOPER – ASSOCIATE EXAM TOPICS COVERED IN THIS CHAPTER MAY INCLUDE, BUT ARE NOT LIMITED TO, THE FOLLOWING:

  • Domain 1: Deployment
  • check mark 1.1 Deploy Serverless Applications.
  • check mark 1.2 Use AWS OpsWorks Stacks to Deploy Applications.
  • check mark 1.3 Use Amazon Elastic Container Service (Amazon ECS) to Deploy Containers.
  • Domain 3: Development with AWS Services
  • check mark 3.1 Write code for serverless applications.
  • check mark 3.2 Write code that interacts with AWS services by using APIs, SDKs, and AWS CLI.

Introduction to Configuration as Code

To expand on the theme of automation, you can add configuration to AWS enterprise as code.

AWS CloudFormation leverages standard AWS APIs to provision and update infrastructure in your account. Though AWS CloudFormation is highly effective at this task, there are some configuration tasks that are either inaccessible from the AWS API or more easily done with standard configuration management tools, such as Chef and Puppet. AWS OpsWorks Stacks provides a serverless Chef infrastructure to configure servers with Chef code, known as recipes. Much like AWS CloudFormation templates, Chef recipe code is declarative in nature. This means you do not have to rely on the accuracy of procedural steps, as you would with a userdata script you apply to Amazon Elastic Compute Cloud (Amazon EC2) instances or launch configurations. If you separate infrastructure from configuration, you also gain the ability to update each on separate cadences.

Symbol of Tip If a security vulnerability is found that requires a configuration update, use a recipe update. When you do the same in AWS CloudFormation, this requires a combination of userdata updates and cfn-hup configuration. A specific configuration management tool, however, requires only a new configuration code to submit to the instance, which will digest and apply the changes automatically.

In containerized environments, configuration of the container itself must also be done. Amazon Elastic Container Service (Amazon ECS) allows you to define the requirements of, schedule, and configure Docker containers to deploy to a cluster of Amazon EC2 instances. The cluster itself can be easy to provision with AWS CloudFormation, along with configuration of container requirements such as CPU and memory needs. By combining this with configuration management tools, both the cluster and any active containers can be configured dynamically.

Using AWS OpsWorks Stacks to Deploy Applications

AWS OpsWorks Stacks lets you manage applications and servers on AWS and on-premises. With AWS OpsWorks Stacks, you can model your application as a stack that contains different layers, such as load balancing, database, and application server. You can deploy and configure Amazon EC2 instances in each layer or connect other resources such as Amazon Relational Database Service (Amazon RDS) databases. AWS OpsWorks Stacks lets you set automatic scaling for your servers on preset schedules or in response to a constant change of traffic levels, and it uses lifecycle hooks to orchestrate changes as your environment scales. You run Chef recipes with Chef Solo, which allows you to automate tasks such as install packages and program languages or frameworks, configure software, and more.

What Is AWS OpsWorks Stacks?

AWS OpsWorks Stacks is the only service that performs configuration management tasks. Configuration management is the process designed to ensure that infrastructure in a given system adheres to a specific set of standards, settings, or attributes (its configuration). Popular configuration management tools include Chef and Puppet. AWS OpsWorks Stacks allows you to manage the configuration of both on-premises and cloud infrastructures. To accomplish this, you organize units of infrastructure into stacks and layers. AWS OpsWorks Stacks can also perform application deployments by the configuration of apps. You can implement configuration changes at specific times in the lifecycle of your infrastructure through the use of lifecycle events, such as when an instance is first brought online or offline. Unlike traditional Chef Server installations, AWS OpsWorks Stacks uses Chef Zero, Chef Solo, or local mode Chef Client. You do not need to involve an actual Chef Server in the configuration management process.

There are two additional AWS OpsWorks services, AWS OpsWorks for Chef Automate and AWS OpsWorks for Puppet Enterprise. Unlike AWS OpsWorks Stacks, both services provision an Amazon EC2 instance in your AWS account with either Chef Automate or Puppet Enterprise software. Table 9.1 lists key differences between each service.

Table 9.1 AWS OpsWorks Services

AWS OpsWorks Stacks AWS OpsWorks for Chef Automate AWS OpsWorks for Puppet Enterprise
Manage infrastructure X
Chef X X
Puppet X
Code repository X X
Built-in automatic scaling X
Amazon EC2 Auto Scaling X X X
Compliance X

Code repository Unlike AWS OpsWorks Stacks, the other two AWS OpsWorks services create an Amazon EC2 instance in your account. This instance will store any Chef or Puppet code for access by any cloud or on-premises instances (nodes) in your environment. AWS OpsWorks Stacks, however, requires you to store Chef code in an external location such as an Amazon Simple Storage Service (Amazon S3) bucket.

Amazon EC2 Auto scaling AWS OpsWorks includes the ability to have instances automatically come online in response to changes in demand. All three AWS OpsWorks services also support “traditional” automatic scaling.

Chef compliance You can use Chef Compliance to track, alert, report on, and remediate compliance violations in your infrastructure. For example, if your organization has strict requirements on SSH access to Linux systems, you can use InSpec (https://www.inspec.io) policies in Chef Compliance to scan nodes in your environment periodically for violations of the current SSH policy.

AWS OpsWorks Stacks supports these Chef versions:

  • Chef 11.10 (Linux)
  • Chef 12.0 (Linux)
  • Chef 12.2 (Windows)

AWS OpsWorks Stack Concepts

This section details AWS OpsWorks Stack concepts including cookbooks, recipes, packaging, stacks, layers, instances, apps, users, permissions, lifecycle events, resources, data bags, Chef, and monitoring your configuration.

Cookbooks and Recipes

Symbol of Note AWS OpsWorks Stacks leverages Chef to implement configuration. Chef itself is not in scope for the AWS Certified Developer – Associate exam. For more information, refer to the Chef training material (https://learn.chef.io).

Chef is a Ruby-based configuration management language that AWS OpsWorks Stacks uses to enforce configuration on Amazon EC2 on-premises instance nodes. Chef uses a declarative syntax to describe how to configure a node without detailing the actual steps to achieve the desired configuration. Chef organizes these declarative statements into recipes, which act as a collection of resources to configure on nodes.

template '/tmp/somefile' do
  mode '0755'
  source 'somefile.erb'
  not_if { File.exist?('/etc/passwd') }
end

In the previous example, the file /tmp/somefile is created from the somefile.erb template. This template file is in a cookbook, which acts as a container for recipes and any files, templates, attributes, or other components to enforce configuration on a node. Attribute files provide data to recipes, and AWS OpsWorks Stacks can modify them with custom JSON at the stack, layer, and deployment levels. You can copy files from cookbooks to nodes to create static files and use templates to provide dynamic data to files before you create them on the node.

Cookbooks normally belong to a cookbook repository, or chef-repo, which is a versioned directory that contains cookbooks and their recipes. A single cookbook repository can contain one or more cookbooks. When you set the cookbook repository for a stack, all cookbooks in the repository copy to each instance in the stack. The directory structure of a chef-repo must match Figure 9.1.

The figure shows an example of Cookbook repository structure.

Figure 9.1 Cookbook repository structure

Recipes use nodes to execute in their “run list.” Recipes that you assign to a node’s run list execute in the order in which they appear. You can assign recipes to roles, which you assign to a node’s run list.

Assigning Recipes to Roles

If a role named database-server contains two recipes, postgresql::default and monitoring::default, the following two run lists are the same:

RUN_LIST="recipe['postgresql::default'],recipe['monitoring::default']"
RUN_LIST="role['database-server']"

In a typical Chef installation, one or more Chef Servers manage multiple nodes across an enterprise. The Chef Server is responsible for distributing cookbooks, managing node information, and providing data to nodes as the Chef runs (an execution of chef-client on a node that enforces any assigned recipes).

Symbol of Note In AWS OpsWorks Stacks, there is no Chef Server to manage nodes. Chef is run with chef-client in local mode on the instance. Local mode creates an in-memory Chef Server to duplicate needed functionality.

Managing Cookbooks

To install custom cookbooks in your stack, you first have to enable the Use Custom Chef Cookbooks field in the stack properties. Once you enable this field, you can then provide the details of the cookbook repository, such as the Git Repository URL, as shown in Figure 9.2.

The figure shows a screenshot illustrating how to enable custom cookbooks.

Figure 9.2 Enabling custom cookbooks

When instances first create and start in a stack, they will download custom cookbooks from the repository you select. However, running instances will not download new cookbooks automatically. You must manually set the Run Command’s Command option to Update Custom Cookbooks, as shown in Figure 9.3.

The figure shows a screenshot illustrating how to set manually the Run Command’s Command option to Update Custom Cookbooks.

Figure 9.3 Running a command

Symbol of Note You cannot manually start stopped Amazon EBS backed load-based and time-based instances, and thus you must replace the instance to update custom cookbooks.

Package Cookbook Dependencies

Chef provides a utility called Berkshelf (https://docs.chef.io/berkshelf.html) to manage dependencies of cookbooks throughout the development and deployment process. In Chef 11.10 stacks, you can install Berkshelf automatically on any instances in your stack. For a production environment, AWS recommends that you do not use Berkshelf to import dependencies during Chef runs. This process introduces a dependency on the external Chef Supermarket API (https://supermarket.chef.io). If the supermarket is unavailable when instances create in your stack, the initial Chef run may fail.

Instead, package the custom cookbooks you develop and their dependencies into a single .zip archive with the berks package Berkshelf command. When you execute this command in a cookbook directory, it will automatically scan any Berksfile and metadata.rb to list any dependencies, download them from their external location, and package them into a compressed .tar archive. You can upload this archive to Amazon S3 and configure it as the custom cookbook repository location for your stack.

berks package cookbooks.tar.gz
Cookbook(s) packaged to /Users/username/tmp/berks/cookbooks.tar.gz

When you package dependencies for multiple cookbooks in the parent directory of the cookbooks, create a Berksfile such as this:

source "https://supermarket.chef.io"
cookbook "server-app", path: "./server-app"
cookbook "server-utils", path: "./server-utils"

After you package the dependencies, run the berks package command from this directory to download and dependencies for your cookbooks.

berks package cookbooks.tar.gz

Stack

A typical workload in AWS will include systems for various purposes, such as load balancers, application servers, proxy servers, databases, and more. The set of Amazon EC2 on-premises instances, Amazon RDS, Elastic Load Balancing, and other systems make up a stack. You can organize stacks across an enterprise.

Suppose you have a single application with dev, test, and production environments. Each of these environments has a stack that enables you to separate resources to ensure stability of changes. You group resources into stacks by logical or functional purposes. The example stack in Figure 9.4 includes three layers, a cookbook repository, an application repository, and one app to deploy to the application server instances. This stack manages a full application available to users over the Internet.

The figure shows an example of stack structure.

Figure 9.4 Example stack structure

When you create a new stack, you will have the option to set the stack’s properties.

Stack Name

Stack Name identifies stacks in the AWS OpsWorks Stacks console. Since this name is not unique, AWS OpsWorks assigns a Globally Unique Identifier (GUID) to the stack after you create it.

API Endpoint Region

AWS OpsWorks associates a stack with either a global endpoint or one of multiple regional endpoints. When you create a resource in the stack, such as an instance, it is available only from the endpoint you specify when you create the stack. For example, if a stack is created with the global “classic” endpoint, any instances will be accessible only by AWS OpsWorks Stacks that use the global API endpoint in the US East (N. Virginia) region. Resources are not available across regional endpoints.

Amazon Virtual Private Cloud

Stacks can create and manage instances in Amazon EC2 Classic or an Amazon Virtual Private Cloud (Amazon VPC). When you select an Amazon VPC, you will be able to specify in what subnets to deploy instances when they are created.

Default Operating System

AWS OpsWorks Stacks supports many built-in Linux operating systems and Windows Server (only in Chef 12.2 stacks). If there is a custom Amazon Machine Images (AMI) you want to use, you must configure other tasks on the AMI to make it compatible with AWS OpsWorks Stacks. You must base the custom AMI off an AMI that AWS OpsWorks supports.

  • The AMI must support cloud-init.
  • The AMI must support the instance types you plan to launch.
  • The AMI must utilize a 64-bit operating system.

Layer

A layer acts as a subset of instances or resources in a stack. Layers act as groups of instances or resources based on a common function. This is especially important, as the Chef recipe code applies to a layer and all instances in a layer. A layer is the point where any configuration of nodes will be set, such as what Chef recipes to execute at each lifecycle hook. A layer can contain any one or more nodes, and a node must be a member of one or more layers. When a node is a member of multiple layers, it will run any recipes you configure for each lifecycle event for both layers in the layer and recipe order you specify.

From the point of view of a Chef Server installation, a layer is synonymous with a Chef Role. In the node object, the layer and role data are equivalent. This is primarily to ensure compatibility with open-source cookbooks that are not written specifically for AWS OpsWorks Stacks.

Elastic Load Balancing

After a layer is created, any elastic load balancers in the same region associate with the layer. Any instances that come online in the layer will automatically register with the load balancer. The instances will also deregister from the load balancer when they go offline.

Elastic IP Addresses

You can configure layers to assign public or elastic IP addresses to instances when they come online. For Amazon Elastic Block Store (Amazon EBS) backed instances, the IP address will remain assigned after the instance stops and starts again. For instance-store backed instances, the IP address may not be the same as the original AWS OpsWorks instance.

Amazon EBS Volumes

Linux stacks include the option to assign one or more Amazon EBS volumes to a layer. In the process, you configure the mount point, size, Redundant Array of Independent Disks (RAID) configuration, volume type, Input/Output Operations Per Second (IOPS), and encryption settings. When new instances start in the layer, AWS OpsWorks Stacks will attempt to create an Amazon EBS volume with the configuration and attach it to the instance. Through the instance’s setup lifecycle event, AWS OpsWorks Stacks runs a Chef cookbook to mount the volume to the instance. When the volumes add or remove volumes to or from a layer, only new instances will receive the configuration updates. Existing instances’ volumes do not change.

Symbol of Note Only Chef 11.10 stacks support RAID configurations.

Amazon RDS Layer

Amazon RDS layers pass connection information to an existing Amazon RDS instance. When you associate an Amazon RDS instance to a stack, it is assigned to an app. This passes the connection information to the instances via the app’s deploy attributes, and you can access the data within your Chef recipes with node[:deploy][:app_name][:database] hash.

You can associate a single Amazon RDS instance with multiple apps in the same stack. However, you cannot associate multiple Amazon RDS instances with the same app. If your application needs to connect to multiple databases, use custom JSON to include the connection information for the other database(s).

Amazon ECS Cluster Layer

Amazon ECS cluster layers provide configuration management capabilities to Linux instances in your Amazon ECS cluster. You can associate a single cluster with a single stack at a time. To create this layer, you must register the cluster with the stack. After this, it will appear in the Layer type drop-down list of available clusters from which to create a layer, as shown in Figure 9.5.

The figure shows a screenshot illustrating how to create Amazon ECS cluster layers.

Figure 9.5 Creating a layer

Symbol of Note Use the console or AWS CLI/SDK commands to create the cluster.

After the layer is created, any existing cluster instances will not import into the stack. Instead, the instances need to register with the stack as on-premises instances, or you need to create a new instance in the layer with the AWS OpsWorks Stacks console or CLI and replace them with new instances. When you create new instances, AWS OpsWorks Stacks will automatically install Docker and the Amazon ECS agent before it registers the instance with the cluster.

Symbol of Note An instance cannot belong to both an Amazon ECS cluster layer and a Chef 11.10 built-in layer. However, the instance can belong to an Amazon ECS cluster layer and other custom layer(s).

Chef 11.10 Built-in Layers

AWS OpsWorks Stacks provides several types of built-in layers for Chef 11.10 stacks.

  • HAProxy layer
  • MySQL layer
  • AWS Flow (Ruby) layer
  • Java app server layer
  • Node.js app server layer
  • PHP app server layer
  • Rails layer
  • Static web server layer
  • Amazon ECS cluster layer

Each of the built-in layers provides a number of preconfigured recipes that speed up the process to deploy applications and manage underlying infrastructure. For example, the Node.js app server layer requires you to specify only one or more apps in the stack and associate it with the layer. When you use the built-in recipes, the app (or apps) automatically deploys to any instances in the layer.

Much like wrapper cookbooks in Chef, you can override built-in layers if you specify a custom attribute or template files. To do so, you can create a cookbook with the same name as the cookbook you want to override and include only the files you want to replace.

Custom Cookbooks or Templates

The built-in apache2 recipe includes an apache2.conf.erb template file that you can override if you create a directory structure as a custom cookbook in your repository.

apache2
|- templates
|-- default
|--- apache2.conf.erb

When your instance updates its cookbooks, it will merge both the built-in layer’s cookbooks with your custom ones and override the template file with your changes.

Instances

An instance represents either an Amazon EC2 or on-premises instance, and the configuration AWS OpsWorks Stacks enforces upon it. You can associate instances with one or more layers, which will define the configuration to apply to the instance. AWS OpsWorks Stacks can create instances. For existing instances or on-premises servers, they can register with a stack, and you can manage them in the same manner as if you created them as AWS OpsWorks Stacks.

Symbol of Note Some Linux distributions can register instances.

Instance Type

AWS OpsWorks Stacks supports three instance types.

24/7 instances This instance type runs until you manually stop it.

Time-based instances Instances of this type run on a daily and weekly schedule that you configure and are useful for handling predictable changes in a load on your stack.

Load-based instances Load-based instances start and stop automatically based on metrics such as NetworkOut or CPUUtilization.

You can use time-based and load-based instances to implement automatic scaling in response to predictable or sudden changes in demand. However, unlike Amazon EC2 Auto Scaling groups, you must create time-based and load-based instances ahead of time with the AWS OpsWorks console or AWS CLI. The underlying Amazon EC2 instance will not be created until the time you specify, or the load threshold occurs, but the AWS OpsWorks instance object must exist ahead of time.

If your stack contains more than several instances, a mix of the previous instance types will provide adequate scalability in response to predictable and sudden changes in demand.

For example, if the lowest demand throughout the day in your environment requires three running instances, then it would make sense to include at least three 24/7 instances in the stack. If demand has a predictable pattern throughout the rest of the day, you can use a number of time-based instances to scale out to meet known increases in demand. To accommodate any potential changes outside the norm, you can configure additional load-based instances as well. Figure 9.6 demonstrates the use of each instance type to react dynamically to changes in request volume.

The figure shows a bar graph demonstrating the use of each instance type to react dynamically to changes in request volume. The x-axis represents time of delay ranges from 6 AM to 12AM. The y-axis represents number of instances ranges from 2 to 16.

Figure 9.6 Instance usage over time

Root Device Type

When you create an Amazon EC2 instance, you have the option to choose either the instance-store or Amazon EBS backed instance types. There are several advantages and disadvantages to each type, as shown in Table 9.2.

Table 9.2 Instance-Store–Backed vs. Amazon EBS Backed

Type Advantages Disadvantages
Instance-store–backed Lower cost

Slower boot after initial

No data persistence

Amazon EBS backed

Faster boot after initial

Retain disk contents

Higher cost

You can apply more configuration settings at the layer, such as Amazon EBS volumes and elastic IP addresses.

Instance Updates

When an instance first boots, AWS OpsWorks Stacks will automatically install any new security and package updates. However, after the initial boot, this will not occur again. This is to ensure that future updates do not affect the performance of your applications. For Linux stacks, you can initiate updates with the Update Dependencies command. Windows stacks do not provide any built-in means to perform updates.

As an alternative to updating instances directly, you can instead regularly launch new instances to replace old ones. As the new instances are created, they will be patched with the latest available security and operating system updates. If you would like to prevent updates entirely and manage this through a separate process, instances can be set to not install updates on startup when you create them. Additionally, this can be set at the layer level to propagate to any new instances that you add to the layer.

Register Instances

If there are instances running in your own data center or other Amazon EC2 instances in your account (or even other accounts), you can register those instances with your stack. You can perform tasks such as user management, package updates, operating system upgrades, and application deployments on registered instances in the same manner as “native” instances.

To register an instance with a stack, you use the aws opsworks register AWS CLI command. The command itself will install the AWS OpsWorks agent on the instance, which is responsible for communicating with the AWS OpsWorks Stacks service endpoint to receive commands and publish information. When you register with other Amazon EC2 instances, they will need both an AWS Identity and Access Management (IAM) instance profile or IAM user credentials with access to register instances with the AWS CLI via the AWS-managed policy, AWSOpsWorksRegisterWithCLI.

When you register instances, you must provide a valid SSH user and private key or valid username and password. These must correspond to a Linux user on the target system (unless you call the register command from the target system itself). After the instance registers, it will display in the AWS OpsWorks Stacks console for assignment to one or more layers in your stack.

You can also deregister an instance from a stack if you no longer want to manage it as part of that stack. This frees it up for you to register it with a different stack or management process.

AWS OpsWorks Agent

The AWS OpsWorks Agent installs on any instances that the stack registers or creates. The agent is responsible for querying the AWS OpsWorks Stacks endpoint for commands to execute on the instance, provide instance metrics to the service, provide health checks for auto healing, and update itself (if configured to do so). You can configure the stack to use a specific agent version or automatically update to the latest available version.

Auto-Healing Instances

If you enable auto healing for a layer, instances that fail to communicate with the AWS OpsWorks service endpoint for more than 5 minutes restart automatically. You can view this in the Amazon CloudWatch Events console where initiated_by is set to auto-healing. Auto healing is enabled by default on all layers in a stack, but you can disable them at any time.

When instances are auto-healed, the exact behavior depends on the type of instance.

  • For instance-store backed instances, the underlying instance terminates, and a new one is created in its place.
  • Amazon EBS backed instances stop and start with the appropriate Amazon EC2 API command.

Apps

An app refers to the location where you store application code and other files. This can be an Amazon S3 bucket, a Git repository, or an HTTP bundle. If you require credentials to connect to the repository, the app configuration provides them as well. The Deploy lifecycle event includes any apps that you configure for an instance at the layer or layers to which it corresponds.

Symbol of Note AWS OpsWorks Stacks automatically downloads and deploys applications in built-in layers. For custom layers, you must include this functionality in your recipe code.

After you configure one or more apps for a layer, running a deployment on instances in that layer will copy the application code from the configured repository and perform any needed deployment steps. In Chef 11.10 built-in layers, this occurs automatically. For custom layers in any Chef version, the deployment process is not automatic, and you must use custom cookbooks.

To perform app updates, you first modify the app itself to point to a new version. Either the current location (Amazon S3 file, Git branch, or HTTP archive) must have the update of the new application code or the app must point to a new revision. Currently running instances will not automatically update. Instances that create after the app updates will deploy the latest version. Any instances that stop at the time of the update will update when the instance starts again.

Users and Permissions Management

AWS OpsWorks Stacks provides the ability to manage users at the stack level, independent of IAM permissions. This is incredibly useful to provide access to instances in a stack without giving a user actual permission to your account. Since most large organizations have strict access policies for third-party contractors, AWS OpsWorks Stacks allows you to give access to perform some stack management tasks, as well as Secure Socket Shell (SSH) or Remote Desktop Protocol (RDP) access to stack instances, and not allow nonemployees access to perform tasks within your account.

Symbol of Note AWS OpsWorks Stacks users associate with regional endpoints and cannot be given access to stacks not in the same region. In this case, you need to import the user into the other region(s).

Managing Permissions

There are four permission types you can apply to a user to provide stack-level permission.

Deny No action is allowed on the stack.

Show The user can view stack configuration but cannot interact with it in any way.

Deploy The user can view stack configuration and deploy apps.

Manage The user can view stack configuration, deploy apps, and manage stack configuration.

AWS OpsWorks Stacks permissions do not allow certain actions, such as to create or clone stacks. IAM permissions restrict these actions, and you must assign them to an IAM user or IAM role. If the user in question is also an IAM user, you can fine-tune the permissions levels.

Symbol of Tip You can give an IAM user the Manage permission at the stack level but deny the ability to delete layers (opsworks:DeleteLayer) at the IAM level. Like IAM, explicit deny will always take precedence over explicit allow.

Along with stack-level permissions, you can give AWS OpsWorks users SSH or RDP access into instances with or without administrative access. You can also configure users to manage their own SSH keys so that they can set their key once they provide access and do not require shared key files through other means. This is also more secure than Amazon EC2 key pairs, as the keys are unique to individual users.

User permissions are set at the stack level in the AWS OpsWorks console, as shown in Figure 9.7. Here you can assign stack and instance permissions to individual user accounts.

The figure shows a screenshot illustrating how to user permissions at the stack level in the AWS OpsWorks console.

Figure 9.7 AWS OpsWorks Stacks user permissions

Managing Users

For existing IAM users for whom you would like to configure stack-level access, you can import them into AWS OpsWorks Stacks on the Users page of the AWS OpsWorks console. Once you import them, you can assign stack-level permissions. These permissions combine with current IAM policies before AWS OpsWorks evaluates them. For example, if you would like to deny access to a specific stack for an IAM user, you can import the user into AWS OpsWorks Stacks and then assign the Deny permission for that stack.

Symbol of Tip If you import an IAM user into AWS OpsWorks Stacks and then later delete that user, you must manually delete the AWS OpsWorks Stacks user as well to revoke any SSH or RDP access.

Lifecycle Events

At each layer of a stack, you will set which Chef recipes you would like to execute at each stage of a node’s lifecycle, such as when it comes online or goes offline. These stages are lifecycle events. The recipes at each lifecycle event execute in the order you specify in the AWS OpsWorks Agent.

Outside of the lifecycle events, you can execute recipes manually with the Execute Recipes command in the AWS OpsWorks console (see Figure 9.8) or AWS CLI. When invoking the command, you can provide a list of recipes to execute in order.

The figure shows a screenshot illustrating how to execute recipes manually with the Execute Recipes command in the AWS OpsWorks console.

Figure 9.8 Running command recipes to execute

You can add more custom recipes to each lifecycle event in the layer’s configuration. Recipes execute in the order they appear in the Custom Chef recipes lifecycle event, as shown in Figure 9.9.

The figure shows a screenshot illustrating the Custom Chef recipes for lifecycle events.

Figure 9.9 Custom Chef recipes for lifecycle events

Setup

This event occurs once the instance has come online after initial creation or when the instance stops and starts. Setup automatically invokes the Deploy command after it completes successfully.

Configure

Any time an instance in a stack comes online or goes offline, all instances in the same stack will undergo a Configure lifecycle event. This ensures that all instances in a stack are “aware” of each other. For example, if a layer in your stack installs and configures haproxy for load balancing, any instances in the same layer will need to update to include the new node in /etc/hosts (or remove the node that went offline).

Deploy

After an instance has come online and completes the initial Setup and Configure events, a Deploy event deploys any apps that you configure for the layer. This step can copy application code from a repository, start or refresh services, and perform other tasks to bring your application(s) online.

After an instance has run Deploy for the first time, it will never do so again automatically. This prevents untested changes from reaching production instances. After you test a feature change or bug fix, you must manually run the Deploy event with the AWS OpsWorks Stacks console or AWS CLI.

Undeploy

The Undeploy lifecycle event runs when you delete or remove an app from a layer. You use this to perform tasks such as when you want to remove an application’s configuration or other cleanup tasks when you remove an app.

Shutdown

Before the actual shutdown command issues to an instance, the Shutdown lifecycle event gives you the opportunity to perform tasks such as taking snapshots and copying log files to Amazon S3 for later use. If the instance’s layer also includes a load balancer, the instance deregisters after the configured connection draining time.

Resource Management

AWS OpsWorks Stacks allows for management of other resources in your account as part of your stack, and it includes elastic IP addresses, Amazon EBS volumes, and Amazon RDS instances. You register the resources with the stack to make them available to assign them to instances or layers. If you attach resources to instances in the stack and you delete the instance, the resource remains registered with the stack until it is manually deregistered. Deregistering resources does not automatically delete them. You must delete the resource itself with the respective service console or AWS CLI command.

Amazon EBS Volumes

Amazon EBS volumes that are not currently attached to any instances can register with a stack, and you can assign them to instances if the volume uses XFS formatting. You cannot attach volumes to running instances. To attach a volume to a running instance, you must stop it. You can move a volume between instances that are both offline.

Symbol of Note You cannot attach Amazon EBS volumes to Windows stacks.

Elastic IP Addresses

As with Amazon EBS volumes, elastic IP addresses that are not associated with resources in your account may be registered with the stack. You can assign an elastic IP address to an instance regardless of whether it is running or not. After an Elastic IP address is disassociated from an instance, a configure lifecycle event updates instances in the stack with the instance’s new IP address.

Amazon RDS Instances

You can register Amazon EBS instances to only one stack at a time. However, you can register a single Amazon RDS instance with multiple apps in the same stack.

Chef 11 and Chef 12

Both Chef 11 and Chef 12 provide unique functionality differences that are important to note before you use AWS OpsWorks Stacks. Each of the major differences is outlined in this section.

The differences in this section are with respect to AWS OpsWorks Stacks as a service, and they do not include differences between Chef versions 11.10 and 12.0. Since version 11.10 has been deprecated by Chef, community support will not be as strong as for later versions.

Separate Chef Runs

In Chef 11.10 stacks, AWS-provided cookbooks were run in the same Chef run as any custom cookbooks. The AWS cookbooks performed various tasks such as mounting Amazon EBS volumes that had been attached to the instance in the AWS OpsWorks console. However, this could result in situations where custom cookbooks had naming conflicts with those provided by AWS. You had to split this into two separate Chef runs on the instance to eliminate any potential namespace conflicts.

Community Support

Since the deprecation of Chef 11.10, community support has gradually decreased. Any open source cookbooks on the Chef Supermarket, for example, will likely make use of Chef 12.0 functionality, removing backward compatibility for Chef 11.10 stacks.

Built-in Layers

Chef 12.0 stacks no longer include the built-in layers as in Chef 11.10 stacks, such as the Rails layer. To implement these layers in Chef 12.0 stacks, you can still copy the built-in cookbooks from a Chef 11.10 stack and update them to be compatible with Chef 12.0. Chef 12.0 stacks still support built-in layer types from Chef 11.10 stacks.

  • Amazon RDS instance layers
  • Amazon ECS cluster layers
Berkshelf

Berkshelf is no longer available for the automatic installation on Chef 12.0 instances. Instead, install Berkshelf with a custom cookbook.

Data Bags

In lieu of custom JSON, Chef 12.0 stacks support data bags to provide better compatibility with community cookbooks. You can declare data bags in the custom JSON field of the stack, layer, and deployment configurations to provide instances in your stack for any additional data that you would like to provide. The attributes set in the data bags will no longer be available in the node object, as with Chef 11.10 stacks, but instead are available with Chef search.

Example: Searching Data Bag Content

Here’s an example of searching a data bag for a value:

app = search("aws_opsworks_app").first
Chef::Log.info("********** The app's short name is '#{app['shortname']}' **********")
Chef::Log.info("********** The app's URL is '#{app['app_source']['url']}' **********")

Data Bags and Custom JSON

In Chef 11.10 stacks, you provide data to instances with custom JSON, which populates in the node object when Chef runs. You can access this information in your recipe code to specify configuration based on the value of custom JSON. You can specify custom JSON at the stack, layer, and deployment levels. Any data that you define at the deployment level overrides the data set at the layer or stack levels. Any data set at the layer level overrides the data set at the stack level.

Example: Stack-Level Settings in Custom JSON

Here’s a JSON example at the stack level:

{
  "state": "visible",
  "colors": {
    "foreground": "light-blue",
    "background": "dark-gray"
  }
}

Now set the custom JSON for the layer to override the stack-level settings.

{
  "state": "hidden",
  "colors": {
    "foreground": "light-blue",
    "background": "dark-gray"
  }
}

Next, execute the recipe on an instance; the value of node['state'] will be hidden.

Chef::Log.info("********** The app's initial state is '#{node['state']}' **********")
Chef::Log.info("********** The app's initial foreground color is '#{node['colors']['foreground']}' **********")
Chef::Log.info("********** The app's initial background color is '#{node['colors']['background']}' **********")

Custom JSON is limited to 80 KB in size. If you need to provide larger data, consider the use of Amazon S3 and retrieve files with a custom cookbook.

Chef 12.0 and 12.2 stacks use data bags instead of custom JSON. This provides better integration with community cookbooks that rely on data bags as the latest Chef standard to provide structured data to cookbooks. Data bags are also written in JSON at the stack, layer, and deployment levels. Any stack data originally provided in the node object on Chef 11.10 stacks is instead made available through one of several data bags during Chef runs.

App Data Bag (aws_opsworks_app)

Suppose the aws_opsworks_app data bag provides information about any apps associated with the layer. In Chef 11.10 stacks, you can access app information in the node object.

Chef::Log.info ("********** The app's short name is '#{node['opsworks']['applications'].first['slug_name']}' **********")
Chef::Log.info("********** The app's URL is '#{node['deploy']['simplephpapp']['scm']['repository']}' **********")
Moving to data bags in Chef 12.0 and 12.2 stacks, Chef search is used to query data bag contents. The above example would instead look like:
app = search("aws_opsworks_app").first
 
Chef::Log.info("********** The app's short name is '#{app['shortname']}' **********")
Chef::Log.info("********** The app's URL is '#{app['app_source']['url']}' **********")

To add custom data bags to your stack, specify them in either the stack, layer, or deployment custom JSON field. To create data bags to call users with a single item, you can do the following:

{
  "opsworks": {
    "data_bags": {
      "users": {
        {
          "id": "nick",
          "comment": "Nick Alteen",
          "home": "/opt/alteen",
          "ssh_keys": ["123…", "456…"]
        }
      }
    }
  }
}

Monitor Instance Metrics

AWS OpsWorks Stacks provides a custom dashboard to monitor up to 13 custom metrics for each instance in the stack. The agent that runs on each instance will publish the information to the AWS OpsWorks Stacks service. If you enable the layer, system, application, and custom logs, they automatically publish to Amazon CloudWatch Logs for review without access the instance itself. You can monitor details at the stack, layer, and instance levels. The metrics that the AWS OpsWorks Agent publishes include cpu_idle, memory_free, procs, and others. Since these metrics are provided by the AWS OpsWorks Agent running on the instance itself, information not available to the underlying host of the instance is provided.

Symbol of Note Windows instance monitoring provides only the standard Amazon EC2 metrics.

For each stack in your account, a dashboard displays these metrics over time. The metrics divide by layer and display over time periods that vary, as shown in Figure 9.10.

The figure shows a screenshot illustrating how to monitor all layers in a stack.

Figure 9.10 Monitoring all layers in a stack

If you select a layer name in the monitoring dashboard, you can review each individual layer. In the layer’s dashboard, metrics divide by individual instances. For example, if you select PHP App Server, as shown in Figure 9.10, the screen in Figure 9.11 displays.

The figure shows a screenshot illustrating how to monitor a single layer in a stack.

Figure 9.11 Monitoring a single layer

From the layer dashboard, you can review individual instance metrics if you select the instance name. For example, if you select php-app1, as shown in Figure 9.11, the screen in Figure 9.12 displays.

The figure shows a screenshot illustrating how to monitor individual instance metrics by selecting instance name.

Figure 9.12 Monitoring an instance

If you enable Amazon CloudWatch Logs on Linux stacks, you can configure the AWS OpsWorks Agent to send system, application, and custom logs to Amazon CloudWatch Logs. With this, alerts can be set when the logs detect specific string patterns, such as HTTP 500 responses in web servers. To publish logs, the instance profile for any instances in the layer must contain permission to push logs. To do this, you assign the AWSOpsWorksCloudWatchLogs managed policy to the corresponding role. Since this integration requires a later agent version, enabling it for your layer will result in all instances being upgraded to a compatible agent version (if they do not already have one).

When you stream logs to Amazon CloudWatch Logs, the log groups use the following naming convention:

stack_namelayer_namechef_log_name

Custom logs, which you define by the file path in the layer settings, add to log groups with the naming convention.

/stack_name/layer_short_name/file_path_name

Along with CloudWatch Logs, CloudWatch Events support stacks. Any time the following types of events occur, you can invoke custom actions in response.

  • Instance state change
  • Command state change
  • Deployment state change
  • Alerts

AWS OpsWorks Stacks Service Limits

AWS OpsWorks Stacks enforces the service limits shown in Table 9.3. These limits can be increased by submitting a request to AWS Support.

Table 9.3 AWS OpsWorks Stacks Service Limits

Limit Value
Stacks per region per account 40
Layers per stack 40
Instances per stack 40
Apps per stack 40

Using AWS OpsWorks Stacks with AWS CodePipeline

Inside a stack, you specify a value for App to refer to a repository or archive that contains application code to deploy to one or more layers. You can use AWS CodePipeline to update an AWS OpsWorks app, which then deploys to any instances in layers you associate with this app.

To configure AWS CodePipeline to deploy to a stack, select the appropriate stack, layer, and app to update with the input artifact, as shown in Figure 9.13.

The figure shows a screenshot illustrating how to use AWS OpsWorks Stacks with AWS CodePipeline.

Figure 9.13 Using AWS OpsWorks Stacks with AWS CodePipeline

Deployment Best Practices

Since app or cookbook updates do not deploy automatically to running instances, you need a robust deployment strategy to ensure that changes complete successfully (or do not cause outages if they fail). This section details the deployment best practices recommended by AWS.

Rolling Deployments

You can issue commands to subsets of instances in a stack or layer at a time. If you split the deployment into multiple phases, the blast radius of failures will be minimized to only a few instances that you can replace, roll back, or repair.

Blue/Green Deployments (Separate Stacks)

Much like you use separate stacks for different environments of the same application, you can also use separate stacks for different deployments. This ensures that all features and updates to an application can be thoroughly tested before routing requests to the new environment. Additionally, you can leave the previous environment running for some time to perform backups, investigate logs, or perform other tasks.

When you use Elastic Load Balancing layers and Amazon Route 53, you can route traffic to the new environment with built-in weighted routing policies. You can progressively increase traffic to the new stack as health checks and other monitoring indicate the new application version has deployed without error.

Manage Databases Between Deployments

In either deployment strategy, there will likely be a backend database with which instances running either version will need to communicate. Currently, Amazon RDS layers support registering a database with only one stack at a time.

If you do not want to create a new database and migrate data as part of the deployment process, you can configure both application version instances to connect to the same database (if there are no schema changes that would prevent this). Whichever stack does not have the Amazon RDS instance registered will need to obtain credentials via another means, such as custom JSON or a configuration file in a secure Amazon S3 bucket.

If there are schema changes that are not backward compatible, create a new database to provide the most seamless transition. However, it will be important to ensure that data is not lost or corrupted during the transition process. You should heavily test this before you attempt it in a production deployment.

Using Amazon Elastic Container Service to Deploy Containers

Amazon ECS is a highly scalable, high-performance container orchestration service that supports Docker containers and allows you to easily run and scale containerized applications on AWS. Amazon ECS eliminates the need for you to install and operate your own container orchestration software, manage and scale a cluster of virtual machines, or schedule containers on those virtual machines.

With simple API calls, you can launch and stop Docker-enabled applications, query the complete state of your application, and access many familiar features such as IAM roles, security groups, load balancers, Amazon CloudWatch Events, AWS CloudFormation templates, and AWS CloudTrail logs.

What Is Amazon ECS?

Amazon ECS streamlines the process for managing and scheduling containers across fleets of Amazon EC2 instances, without the need to include separate management tools for container orchestration or cluster scaling. AWS Fargate reduces management further as it deploys containers to serverless architecture and removes cluster management requirements entirely. To create a cluster and deploy services, you need only configure the resource requirements of containers and availability requirements. Amazon ECS manages the rest with the use of an agent that runs on cluster instances. AWS Fargate requires no agent management.

To react to changes in demands for your service or application, Amazon ECS supports Amazon EC2 Auto Scaling groups of cluster instances that allow your service to increase running container counts across multiple instances as demand increases. You can define container isolation and dependencies as part of the service definition. You can use the service definition to enforce requirements without user interaction, such as “only one container of type A may run on a cluster instance at a time.”

Amazon ECS Concepts

This section details Amazon ECS concepts.

Amazon ECS Cluster

Amazon ECS clusters are the foundational infrastructure components on which containers run. Clusters consist of one or more Amazon EC2 instances in your Amazon VPC. Each instance in a cluster (cluster instance) has an agent installed. The agent is responsible for receiving container scheduling/shutdown commands from the Amazon ECS service and to report the current health status of containers (restart or replace). Figure 9.14 demonstrates an Amazon EC2 launch type, where instances make up the Amazon ECS cluster.

The figure shows an AWS Fargate cluster that runs in multiple availability zones (AZs).

Figure 9.14 Amazon ECS architecture

In an AWS Fargate launch type, Amazon ECS clusters are no longer made up of Amazon EC2 instances. Since the tasks themselves launch on the AWS infrastructure, AWS assigns each one an elastic network interface with an Amazon VPC. This provides network connectivity for the container without the need to manage the infrastructure on which it runs. Figure 9.15 demonstrates an AWS Fargate cluster that runs in multiple availability zones (AZs).

The figure shows an Amazon EC2 launch type, where instances make up the Amazon ECS cluster.

Figure 9.15 AWS Fargate architecture

An individual cluster can support both Amazon EC2 and AWS Fargate launch types. However, a single cluster instance can belong to only one cluster at a time. Amazon EC2 launch types support both on-demand and spot instances, and they allow you to reduce cost for noncritical workloads.

To enable network connectivity for containers that run on your instance, the corresponding task definition must outline port mappings from the container to the host instance. When you create a container instance, you can select the instance type to use. The compute resources available to this instance type will determine how many containers can be run on the instance. For example, if a t2.micro instance has one vCPU and 1 GB of RAM, it will not be able to run containers that require two vCPUs.

After you add a container instance to a cluster and you place containers on it, there may be situations where you would need to remove the container from the cluster temporarily—for a regular patch, for example. However, if critical tasks run on a container instance, you may want to wait for the containers to terminate gracefully. Container instance draining can be used to drain running containers from an instance and prevent new ones from being started. Depending on the service’s configuration, replacement tasks start before or after the original tasks terminate.

  • If the value of minimumHealthyPercent is less than 100 percent, the service will terminate the task and launch a replacement.
  • If the value is greater than 100 percent, the service will attempt to launch a replacement task before it terminates the original.

To make room for launching additional tasks, you can scale out a cluster with Amazon EC2 Auto Scaling groups. For an EC2 Auto Scaling group to work with an Amazon ECS cluster, you must install the Amazon ECS agent either as part of the AMI or via instance userdata. To change the number container instances that run, you can adjust the size of the corresponding EC2 Auto Scaling group. If you need to terminate instances, any tasks that run on them will also halt.

Symbol of Note Scaling out a cluster does not also increase the running task count. You use service automatic scaling for this process.

AWS Fargate

AWS Fargate simplifies the process of managing containers in your environment and removes the need to manage underlying cluster instances. Instead, you only need to specify the compute requirements of your containers in your task definition. AWS Fargate automatically launches containers without your interaction.

With AWS Fargate, there are several restrictions on the types of tasks that you can launch. For example, when you specify a task definition, containers cannot be run in privileged mode. To verify that a given task definition is acceptable by AWS Fargate, use the Requires capabilities field of the Amazon ECS console or the --requires-capabilities command option of the AWS CLI.

Symbol of Note AWS Fargate requires that containers launch with the network mode set to awsvpc. In other words, you can launch only AWS Fargate containers into Amazon VPCs.

Symbol of Note AWS Fargate requires the awslogs driver to enable log configuration.

Containers and Images

Symbol of Note Amazon ECS launches and manages Docker containers. However, Docker is not in scope for the AWS Certified Developer – Associate Exam.

Any workloads that run on Amazon ECS must reside in Docker containers. In a virtual server environment, multiple virtual machines share physical hardware, each of which acts as its own operating system. In a containerized environment, you package components of the operating system itself into containers. This removes the need to run any nonessential aspects of a full-fledged virtual machine to increase portability. In other words, virtual machines share the same physical hardware, while containers share the same operating system.

Container images are similar in concept to AMIs. Images provision a Docker container. You store images in registries, such as a Docker Hub or an Amazon Elastic Container Repository (ECR).

Symbol of Note You can create your own private image repository; however, AWS Fargate does not support this launch type.

Docker provides mobility and flexibility of your workload to allow containers to be run on any system that supports Docker. Compute resources can be better utilized when you run multiple containers on the same cluster, which makes the best possible use of resources and reduces idle compute capacity. Since you separate service components into containers, you can update individual components more frequently and at reduced risk.

Task Definition

Though you can package entire applications into a single container, it may be more efficient to run multiple smaller containers, each of which contains a subset of functionality of your full application. This is referred to as service-oriented architecture (SOA). In SOA, each unit of functionality for an overall system is contained separately from the rest. Individual services work with one another to perform a larger task. For example, an e-commerce website that uses SOA could have sets of containers for load balancing, credit card processing, order fulfillment, or any other tasks that users require. You design each component of the system as a black box so that other components do not need to be aware of inner workings to interact with them.

A task definition is a JSON document that describes what containers launch for your application or system. A single task definition can describe between one and 10 containers and their requirements. Task definitions can also specify compute, networking, and storage requirements, such as which ports to expose to which containers and which volumes to mount.

You should add containers to the same task definition under the following circumstances:

  • The containers all share a common lifecycle.
  • The containers need to run on the same common host or container instance.
  • The containers need to share local resources or volumes.

An entire application does not need to deploy with a single task definition. Instead, you should separate larger application segments into separate task definitions. This will reduce the impact of breaking changes in your environment. If you allocate the right-sized container instances, you can also better control scaling and resource consumption of the containers.

After a task definition creates and uploads to Amazon ECS, it can launch one or more tasks. When a task is created, the containers in the task definition are scheduled to launch into the target cluster via the task scheduler.

Task Definition with Two Containers

The following example demonstrates a task definition with two containers. The first container runs a WordPress installation and binds the container instance’s port 80 to the same port on the container. The second container installs MySQL to act as the backend data store of the WordPress container. The task definition also specifies a link between the containers, which allows them to communicate without port mappings if the network setting for the task definition is set to bridge.

{
  "containerDefinitions": [
    {
      "name": "wordpress",
      "links": [
        "mysql"
      ],
      "image": "wordpress",
      "essential": true,
      "portMappings": [
        {
          "containerPort": 80,
          "hostPort": 80
        }
      ],
      "memory": 500,
      "cpu": 10
    },
    {
      "environment": [
        {
          "name": "MYSQL_ROOT_PASSWORD",
          "value": "password"
        }
      ],
      "name": "mysql",
      "image": "mysql",
      "cpu": 10,
      "memory": 500,
      "essential": true
    }
  ],
  "family": "hello_world"
}

Services

When creating a service, you can specify the task definition and number of tasks to maintain at any point in time. After the service creates, it will launch the desired number of tasks; thus, it launches each of the containers in the task definition. If any containers in the task become unhealthy, the service is responsible and launches replacement tasks.

Deployment Strategies

When you define a service, you can also configure deployment strategies to ensure a minimum number of healthy tasks are available to serve requests while other tasks in the service update. The maximumPercent parameter defines the maximum percentage of tasks that can be in RUNNING or PENDING state. The minimumHealthyPercent parameter specifies the minimum percentage of tasks that must be in a healthy (RUNNING) state during deployments.

Suppose you configure one task for your service, and you would like to ensure that the application is available during deployments. If you set the maximumPercent to 200 percent and minimumHealthyPercent to 100 percent, it will ensure that the new task launches before the old task terminates. If you configure two tasks for your service and some loss of availability is acceptable, you can set maximumPercent to 100 percent and minimumHealthyPercent to 50 percent. This will cause the service scheduler to terminate one task, launch its replacement, and then do the same with the other task. The difference is that the first approach requires double the normal cluster capacity to accommodate the additional tasks.

Balance Loads

You can configure services to run behind a load balancer to distribute traffic automatically to tasks in the service. Amazon ECS supports classic load balancers, application load balancers, and network load balancers to distribute requests. Of the three load balancer types, application load balancers provide several unique features.

Application Load Balancing (ALB) load balancers route traffic at layer 7 (HTTP/HTTPS). Because of this, they can take advantage of dynamic host port mapping when you use them in front of Amazon ECS clusters. ALBs also support path-based routing so that multiple services can listen on the same port. This means that requests will be to different tasks based on the path specified in the request.

Classic load balancers, because they register and deregister instances, require that any tasks being run behind the load balancer all exist on the same container instance. This may not be desirable in some cases, and it would be better to use an ALB.

Schedule Tasks

If you increase the number of instances in an Amazon ECS cluster, it does not automatically increase the number of running tasks as well. When you configure a service, the service scheduler determines how many tasks run on one or more clusters and automatically starts replacement tasks should any fail. This is especially ideal for long-running tasks such as web servers. If you configure it to do so, the service scheduler will ensure that tasks register with an elastic load balancer.

You can also run a task manually with the RunTask action, or you can run tasks on a cron-like schedule (such as every N minutes on Tuesdays and Thursdays). This works well for tasks such as log rotation, batch jobs, or other data aggregation tasks.

To dynamically adjust the run task count dynamically, you use Amazon CloudWatch Alarms in conjunction with Application Auto Scaling to increase or decrease the task count based on alarm status. You can use two approaches for automatically scaling Amazon ECS services and tasks: Target Tracking Policies and Step Scaling Policies.

Target Tracking Policies

Target tracking policies determine when to scale the number of tasks based on a target metric. If the metric is above the target, such as CPU utilization being above 75 percent, Amazon ECS can automatically launch more tasks to bring the metric below the desired value. You can specify multiple target tracking policies for the same service. In the case of a conflict, the policy that would result in the highest task count wins.

Step Scaling Policies

Unlike target tracking policies, step scaling policies can continue to scale in or out as metrics increase or decrease. For example, you can configure a step scaling policy to scale out when CPU utilization reaches 75 percent, again at 80 percent, and one final time at 90 percent. With this approach, a single policy can result in multiple scaling activities as metrics increase or decrease.

Task Placement Strategies

Regardless of the method you use, task placement strategies determine on which instances tasks launch or which tasks terminate during scaling actions. For example, the spread task placement strategy distributes tasks across multiple AZs as much as possible. Task placement strategies perform on a best-effort basis. If the strategy cannot be honored, such as when there are insufficient compute resources in the AZ you select, Amazon ECS will still try to launch the task(s) on other cluster instances. Other strategies include binpack (uses CPU and memory on each instance at a time) and random.

Task placement strategies associate with specific attributes, which are evaluated during task placement. For example, to spread tasks across availability zones, the placement strategy to use is as follows:

"placementStrategy": [
    {
        "field": "attribute:ecs.availability-zone",
        "type": "spread"
    }
]
Task Placement Constraints

Task placement constraints enforce specific requirements on the container instances on which tasks launch, such as to specify the instance type as t2.micro.

"placementConstraints": [
    {
        "expression": "attribute:ecs.instance-type == t2.micro",
        "type": "memberOf"
    }
]

Amazon ECS Service Discovery

Amazon ECS Service Discovery allows you to assign Amazon Route 53 DNS entries automatically for tasks your service manages. To do so, you create a private service namespace for each Amazon ECS cluster. As tasks launch or terminate, the private service namespace updates to include DNS entries for each task. A service directory maps DNS entries to available service endpoints. Amazon ECS Service Discovery maintains health checks of containers, and it removes them from the service directory should they become unavailable.

Symbol of Note To use public namespaces, you must purchase or register the public hosted zone with Amazon Route 53.

Private Image Repositories

Amazon ECS can connect to private image repositories with basic authentication. This is useful to connect to Docker Hub or other private registries with a username and password. To do so, the ECS_ENGINE_AUTH_TYPE and ECS_ENGINE_AUTH_DATA environment variables must be set with the authorization type and actual credentials to connect. However, you should not set these properties directly. Instead, store your container instance configuration file in an Amazon S3 bucket and copy it to the instance with userdata.

Amazon Elastic Container Repository

Amazon Elastic Container Repository (Amazon ECR) is a Docker registry service that is fully compatible with existing Docker CLI tools. Amazon ECR supports resource-level permissions for private repositories and allows you to preserve a secure registry without the need to maintain an additional application. Since it integrates with IAM users and Amazon ECS cluster instances, it can take advantage of IAM users or instance profiles to access and maintain images securely without the need to provide a username and password.

Amazon ECS Container Agent

The Amazon ECS container agent is responsible for monitoring the status of tasks that run on cluster instances. If a new task needs to launch, the container agent will download the container images and start or stop containers. If any containers fail health checks, the container agent will replace them. Since the AWS Fargate launch type uses AWS-managed compute resources, you do not need to configure the agent.

To register an instance with an Amazon ECS cluster, you must first install the Amazon ECS Agent. This agent installs automatically on Amazon ECS optimized AMIs. If you would like to use a custom AMI, it must adhere to the following requirements:

  • Linux kernel 3.10 or greater
  • Docker version 1.9.0 or greater and any corresponding dependencies

The Amazon ECS container agent updates regularly and can update on your instance(s) without any service interruptions. To perform updates to the agent, replace the container instance entirely or use the Update Container Agent command on Amazon ECS optimized AMIs.

Symbol of Note You cannot perform agent updates on Windows instances using these methods. Instead, terminate the instance and create a new server in its absence.

To configure the Amazon ECS container agent, update /etc/ecs/config on the container instance and then restart the agent. You can configure properties such as the cluster to register with, reserved ports, proxy settings, and how much system memory to reserve for the agent.

Amazon ECS Service Limits

Table 9.4 displays the limits that AWS enforces for Amazon ECS. You can change limits with an asterisk (*) by making a request to AWS Support.

Table 9.4 Amazon ECS Service Limits

Limit Value
Clusters per region per account* 1,000
Container instances per cluster* 1,000
Services per cluster* 500
Tasks that use Amazon EC2 launch type per service* 1,000
Tasks that use AWS Fargate launch type per region per account* 20
Public IP addresses for tasks that use AWS Fargate launch type* 20
Load balancers per service 1
Task definition size 32 KiB
Task definition containers 10
Layer size of image that use AWS Fargate task 4 GB
Shared volume that use AWS Fargate tasks 10 GB
Container storage that use AWS Fargate tasks 10 GB

Using Amazon ECS with AWS CodePipeline

When you select Amazon ECS as a deployment provider, there is no option to create the cluster and service as part of the pipeline creation process. This must be done ahead of time. After the cluster is created, select the appropriate cluster and service names in the AWS CodePipeline console, as shown in Figure 9.16.

The figure shows a screenshot illustrating how to select the appropriate cluster and service names in the AWS CodePipeline console.

Figure 9.16 Amazon ECS as a deployment provider

You must provide an image filename as part of this configuration. This is a JSON-formatted document inside your code repository or archive or as an output build artifact, which specifies the service’s container name and image tag. We recommend that the cluster contain at least two Amazon EC2 instances so that one can act as primary while the other handles deployment of new containers.

Summary

This chapter includes infrastructure, configuration, and deployment services that you use to deploy configuration as code.

AWS CloudFormation leverages standard AWS APIs to provision and update infrastructure in your account. AWS CloudFormation uses standard configuration management tools such as Chef and Puppet.

Configuration management of infrastructure over an extended period of time is best served with the use of a dedicated tool such as AWS OpsWorks Stacks. You define the configuration in one or more Chef recipes to achieve configuration as code on top of your infrastructure. AWS OpsWorks Stacks can be used to provide a serverless Chef infrastructure to configure servers with Chef code (recipes).

Chef recipe code is declarative in nature, and you do not have to rely on the accuracy of procedural steps, as you would with a userdata script you apply to Amazon ECS instances or launch configurations. You can use Amazon ECS instead of instances or serverless functions to use a containerization method to manage applications. If you separate infrastructure from configuration, you also gain the ability to update each on separate cadences.

Amazon ECS supports Docker containers, and it allows you to run and scale containerized applications on AWS. Amazon ECS eliminates the need to install and operate your own container orchestration software, manage and scale a cluster of virtual machines, or schedule containers on those virtual machines.

AWS Fargate reduces management further as it deploys containers to serverless architecture and removes cluster management requirements. To create a cluster and deploy services, you configure the resource requirements of containers and availability requirements. Amazon ECS manages the rest through an agent that runs on cluster instances. AWS Fargate requires no agent management.

Amazon ECS clusters are the foundational infrastructure components on which containers run. Clusters consist of Amazon EC2 instances in your Amazon VPC. Each cluster instance has an agent installed that is responsible for receiving scheduling/shutdown commands from the Amazon ECS service and reporting the current health status of containers (restart or replace).

In lieu of custom JSON, Chef 12.0 stacks support data bags to provide better compatibility with community cookbooks. You can declare data bags in the custom JSON field of the stack, layer, and deployment configurations to provide instances in your stack for any additional data that you would like to provide.

AWS OpsWorks Stacks lets you manage applications and servers on AWS and on-premises. You can model your application as a stack that contains different layers, such as load balancing, database, and application server. You can deploy and configure Amazon EC2 instances in each layer or connect other resources such as Amazon RDS databases. AWS OpsWorks Stacks lets you set automatic scaling for your servers on preset schedules or in response to a constant change of traffic levels, and it uses lifecycle hooks to orchestrate changes as your environment scales. You run Chef recipes with Chef Solo, which allows you to automate tasks such as installing packages and program languages or frameworks, configuring software, and more.

An app is the location where you store application code and other files, such as an Amazon S3 bucket, a Git repository, or an HTTP bundle, and it includes sign-in credentials. The Deploy lifecycle event includes any apps that you configure for an instance at the layer or layers to which it corresponds.

At each layer of a stack, you set which Chef recipes to execute at each stage of a node’s lifecycle, such as when it comes online or goes offline (lifecycle events). The recipes at each lifecycle event are executed by the AWS OpsWorks Agent in the order you specify.

AWS OpsWorks Stacks allows for management of other resources in your account as part of your stack and include elastic IP addresses, Amazon EBS volumes, and Amazon RDS instances.

The AWS OpsWorks Stacks dashboard monitors up to 13 custom metrics for each instance in the stack. The agent that runs on each instance will publish the information to the AWS OpsWorks Stacks service. If you enable the layer, system, application, and custom logs, they automatically publish to Amazon CloudWatch Logs for review without accessing the instance itself.

When you define a consistent deployment pattern for infrastructure, configuration, and application code, you can convert entire enterprises to code. You can remove manual management of most common processes and replace them with seamless management of entire application stacks through a simple commit action.

Exam Essentials

Understand configuration management and Chef. Configuration management is the process designed to ensure the infrastructure in a given system adheres to a specific set of standards, settings, or attributes. Chef is a Ruby-based configuration management language that AWS OpsWorks Stacks uses to enforce configuration on Amazon EC2 on-premises instances, or nodes. Chef uses a declarative syntax to describe the desired state of a node, abstracting the actual steps needed to achieve the desired configuration. This code is organized into recipes, which are organized into collections called cookbooks.

Know how AWS OpsWorks Stacks organizes configuration code into cookbooks. In traditional Chef implementations, cookbooks belong to a chef-repo, which is a versioned directory that contains cookbooks and their underlying recipes and files. A single cookbook repository can contain one or more cookbooks. When you define the custom cookbook location for a stack, all cookbooks copy to instances in the stack.

Know how to update custom cookbooks on a node. When instances first launch in a stack, they will download cookbooks from the custom cookbook repository. You must manually issue an Update Custom Cookbooks command to instances in your stack to update the instance.

Understand the different AWS OpsWorks Stacks components. The topmost object in AWS OpsWorks Stacks is a stack, which contains all elements of a given environment or system. Within a stack, one or more layers contain instances you group by common purpose. A single instance references either an Amazon EC2 or on-premises instance and contains additional configuration data. A stack can contain one or more apps, which refer to repositories where application code copies to for deployment. Users are regional resources that you can configure to access one or more stacks in an account.

Know the different AWS OpsWorks Stacks instance types and their purpose. AWS OpsWorks Stacks has three different instance types: 24/7, time-based, and load-based. The 24/7 instances run continuously unless an authorized user manually stops it, and they are useful for handling the minimum expected load of a system. Time-based instances start and stop on a given 24-hour schedule and are recommended for predicable increases in load at different times of the day. Load-based instances start and stop in response to metrics, such as CPU utilization for a layer, and you use them to respond to sudden increases in traffic.

Understand how AWS OpsWorks Stacks implements auto healing. The AWS OpsWorks Stacks agent that runs on an instance performs a health check every minute and sends the response to AWS. If the AWS OpsWorks Stacks agent does not receive the health check for five continuous minutes, the instance restarts automatically. You can disable this feature. Auto healing events publish to Amazon CloudWatch for reference.

Understand the AWS OpsWorks Stacks permissions model. AWS OpsWorks Stacks provides the ability to manage users at the stack level, independent of IAM permissions. This is useful for providing access to instances in a stack but not to the AWS Management Console or API. You can assign AWS OpsWorks Stacks users to one of four permission levels: Deny, Show, Deploy, and Manage. Additionally, you can give users SSH/RDP access to instances in a stack (with or without sudo/administrator permission). AWS OpsWorks Stacks users are regional resources. If you would like to give a user in one region access to a stack in another region, you need to copy the user to the second region. Some AWS OpsWorks Stacks activities are available only through IAM permissions, such as to delete and create stacks.

Know the different AWS OpsWorks Stacks lifecycle events. Instances in a stack are provisioned, configured, and retired using lifecycle events. The AWS OpsWorks Stacks supports the lifecycle events: Setup, Configure, Deploy, Undeploy, and Shutdown. The Configure event runs on all instances in a stack any time one instance comes online or goes offline.

Know the components of an Amazon ECS cluster. A cluster is the foundational infrastructure component on which containers are run. Clusters are made up of one or more Amazon EC2 instances, or they can be run on AWS-managed infrastructure using AWS Fargate. A task definition is a JSON file that describes which containers to launch on a cluster. Task definitions can be defined by grouping containers that are used for a common purpose, such as for compute, networking, and storage requirements. A service launches on a cluster and specifies the task definition and number of tasks to maintain. If any containers become unhealthy, the service is responsible for launching replacements.

Know the difference between Amazon ECS and AWS Fargate launch types. The AWS Fargate launch type uses AWS-managed infrastructure to launch tasks. As a customer, you are no longer required to provision and manage cluster instances. With AWS Fargate, each cluster instance is assigned a network interface in your VPC. Amazon ECS launch types require a cluster in your account, which you must manage over time.

Know how to scale running tasks in a cluster. Changing the number of instances in a cluster does not automatically cause the number of running tasks to scale in or out. You can use target tracking policies and step scaling policies to scale tasks automatically based on target metrics. A target tracking policy determines when to scale based on metrics such as CPU utilization or network traffic. Target tracking policies keep metrics within a certain boundary. For example, you can launch additional tasks if CPU utilization is above 75 percent. Step scaling policies can continuously scale as metrics increase or decrease. You can configure a step scaling policy to scale tasks out when CPU utilization reaches 75 percent and again at 80 percent and 90 percent. A single step scaling policy can result in multiple scaling activities.

Know how images are stored in Amazon Elastic Container Repository (Amazon ECR). Amazon ECR is a Docker registry service that is fully compatible with existing Docker tools. Amazon ECR supports resource-level permissions for private repositories, and it allows you to maintain a secure registry without the need to maintain additional instances/applications.

Resources to Review

 

Exercises

Exercise 9.1

Launch a Sample AWS OpsWorks Stacks Environment

  1. Launch the AWS Management Console.
  2. Select ServicesAWS OpsWorks.
  3. Select Add Stack, and select Sample stack.
  4. Select your preferred operating system (Linux or Windows).
  5. Select Add Instance, and monitor the stack’s progress until it enters the online state. This deploys the app to the stack.
  6. Copy the public IP Address, and paste it into a web browser to display the sample app.
  7. Open the instance in the AWS OpsWorks Stacks console, and view the log entries.
  8. Verify that the Chef run was a success and which resources deploy to the instance in the log entries.
  9. Update the recipes of the automatically created layer.
  10. Remove the deploy recipe.
  11. Add a new instance to the stack and monitor its progress.
  12. Once the instance is in the online state, view the run logs to verify that the sample website is not deployed to the instance.

Exercise 9.2

Launch an Amazon ECS Cluster and Containers

  1. Launch the Amazon ECS console.
  2. Create a new cluster with an Amazon EC2 container instances.
  3. Create a new task definition that launches a WordPress and MySQL container.
  4. Use the official images from Docker Hub:
    1. https://registry.hub.docker.com/wordpress/
    2. https://registry.hub.docker.com/mysql/
  5. Create a new service that launches this task definition on the cluster.
  6. Copy the public IP address, and paste it into a web browser to access WordPress on the cluster instance.
  7. Modify the service to launch two tasks.
  8. As the second task attempts to launch, note that this will fail because of the ports configured in the task definition already being registered with the running containers.
  9. Launch an additional cluster instance in your cluster.
  10. Monitor the service status to verify that the second task deploys to the new cluster instance.

Exercise 9.3

Migrate an Amazon RDS Database

  1. Launch the Amazon RDS console.
  2. Create a new database instance.
  3. Connect to your database and create a user with a password. For example, to create a user with full privileges on MySQL, use the following command:
    GRANT ALL PRIVILEGES ON *.* TO 'username'@'localhost' IDENTIFIED BY 'password';
  4. Launch the AWS OpsWorks console.
  5. Create two stacks (one “A” stack and one “B” stack). For ease of use, try the sample Linux stack with a Node.js app.
  6. Register the RDS database instance that you created with stack A, providing the database username and password you created.
  7. Edit the stack’s app to include Amazon RDS as a data source. Select the database you registered and provide the database name.
  8. Verify that you can connect to your database by creating a simple recipe to output the credentials. Specifically, try to output to the database field of the deploy attributes.
  9. Run this recipe to verify that the connection information passes to your nodes.
  10. Pass the same connection information into stack A using custom JSON.
  11. Deregister the database from stack A and register it with stack B.
  12. Perform the same tasks to verify that connection details pass to the instances in stack B.
  13. Remove the custom JSON from stack A to complete the migration.

Exercise 9.4

Configure Auto Healing Event Notifications in AWS OpsWorks Stacks

  1. Launch the Amazon SNS console.
  2. Create a new notification topic with your email address as a recipient.
  3. Launch the Amazon CloudWatch console.
  4. Create an Amazon CloudWatch Rule.
    1. Edit the JSON version of the rule pattern to use:
      {
        "source": [ "aws.opsworks" ],
        "detail": {
          "initiated_by": [
            "auto-healing"
          ]
        }
      }
  5. Add the Amazon SNS topic that you created as a target.
  6. Add permissions to the Amazon SNS topic so that it can be invoked by Amazon CloudWatch Events. An example policy statement is shown here. Replace the value of the Resource block with your topic Amazon Resource Name (ARN).
    {
      "Version": "2008-10-17",
      "Id": "AutoHealingNotificationPolicy",
      "Statement": [{
        "Effect": "Allow",
        "Principal": {
          "Service": "events.amazonaws.com"
        },
        "Action": "sns:Publish",
        "Resource": "arn:aws:sns:REGION:ACCOUNT:MyTopic"
      }]
    }
  7. Create a stack and add an instance. Make sure that Auto Healing is enabled on the stack.
  8. Launch the instance.
  9. SSH or RDP into the instance.
  10. Uninstall the AWS OpsWorks Stacks Agent.
  11. Wait until the instance is stopped and started by AWS OpsWorks Stacks. You will receive a notification shortly after this occurs.

Review Questions

  1. Which of the following AWS OpsWorks Stacks limits cannot be raised?

    1. Maximum stacks per account, per region
    2. Maximum layers per stack
    3. Maximum instances per layer
    4. Maximum apps per stack
    5. None of the above
  2. After submitting changes to your cookbook repository, you notice that executing cookbooks on your AWS OpsWorks instances does not result in any changes taking place, even though the logs show successful Chef runs. What could be the cause of this?

    1. The instances are unable to connect to the cookbook repository or archive location because of networking or permissions errors.
    2. The AWS OpsWorks Stacks agent running on the instance is enforcing cookbook caching, resulting in cached copies being used instead of the new versions.
    3. The version of the cookbook specified in the recipe list for the lifecycle event is incorrect.
    4. The custom cookbooks have not yet been downloaded to the instances.
  3. When will an AWS OpsWorks Stacks instance register and deregister from an Elastic Load Balancing load balancer associated with the layer?

    1. Instances are registered or deregistered manually only.
    2. Instances will be registered when they enter an online state and are deregistered when they leave an online state.
    3. As an administrator, you are responsible for including the registration and deregistration within your Chef recipes and assigning the recipes to the appropriate lifecycle event.
    4. Instances are registered when they are created and not deregistered until they are terminated.
  4. You have an Amazon ECS cluster that runs on a single service with one task. The cluster currently contains enough instances to support the containers you define in your task, with no additional compute resources to spare (other than those needed by the underlying OS and Docker). Currently the service is configured with a maximum in-service percentage of 100 percent and a minimum of 100 percent. When you attempt to update the service, nothing happens for an extended period of time, as the replacement task appears to be stuck as it launches. How would you resolve this? (Select TWO.)

    1. The current configuration prevents new tasks from starting because of insufficient resources. Add enough instances to the cluster to support the additional task temporarily.
    2. The current configuration prevents new tasks from starting because of insufficient resources. Modify the configuration to have a maximum in-service percentage of 200 percent and a minimum of 0 percent.
    3. Configure the cluster to leverage an AWS Auto Scaling group and scale out additional cluster instances when CPU Utilization is over 90 percent.
    4. Submit a new update to replace the one that appears to be failing.
  5. Which party is responsible for patching and maintaining underlying clusters when you use the AWS Fargate launch type?

    1. The customer
    2. Amazon Web Services (AWS)
    3. Docker
    4. Independent software vendors
  6. Why should instances in a single AWS OpsWorks Stacks layer have the same functionality and purpose?

    1. Because all instances in a layer run the same recipes
    2. To keep the console clean
    3. To stop and start at the same time
    4. To all run configure lifecycle events at the same time
  7. Where do instances in an AWS OpsWorks Stacks stack download custom cookbooks?

    1. The Chef Server
    2. They are included in the Amazon Machine Image (AMI).
    3. The custom cookbook repository
    4. Amazon Elastic Container Service (Amazon ECS)
  8. How would you migrate an Amazon Relational Database Service (Amazon RDS) layer between two stacks in the same region?

    1. Supply the connection information to the second stack as custom JSON to ensure that the instances can connect. Remove the Amazon RDS layer from the first stack. Add the Amazon RDS layer to the second stack. Remove the connection custom JSON.
    2. Add the Amazon RDS layer to the second stack and remove it from the first.
    3. Create a new database instance, migrate data to the new instance, and associate it with the second stack using an Amazon RDS layer.
    4. This is not possible.
  9. Which AWS OpsWorks Stacks instance type would you use for predictable increases in traffic or workload for a stack?

    1. 24/7
    2. Load-based
    3. Time-based
    4. On demand
  10. Which AWS OpsWorks Stacks instance type would you use for random, unpredictable increases in traffic or workload for a stack?

    1. 24/7
    2. Load-based
    3. Time-based
    4. Spot
  11. What component is responsible for stopping and starting containers on an Amazon Elastic Container Service (Amazon ECS) cluster instance?

    1. The Amazon ECS agent running on the instance
    2. The Amazon ECS service role
    3. AWS Systems Manager
    4. The customer
  12. What is Service-Oriented Architecture (SOA)?

    1. The use of multiple AWS services to decouple infrastructure components and achieve high availability
    2. A software design practice where applications divide into discrete components (services) that communicate with each other in such a way that individual services do not rely on one another for their successful operation
    3. Involves multiple teams to develop application components with no knowledge of other teams and their components
    4. Leasing services from different vendors instead of doing internal development
  13. How many containers can a single task definition describe?

    1. 1
    2. Up to 3
    3. Up to 5
    4. Up to 10
  14. You have a web proxy application that you would like to deploy in containers with the use of Amazon Elastic Container Service (Amazon ECS). Typically, your application binds to port 80 on the instance on which it runs. How can you use an application load balancer to run more than one proxy container on each instance in your cluster?

    1. Do not configure the container to bind to port 80. Instead, configure Application Load Balancing (ALB) with dynamic host port mapping so that a random port is bound. The ALB will route traffic coming in on port 80 to the port on which the container is listening.
    2. Configure a Port Address Translation (PAT) instance in Amazon Virtual Private Cloud (Amazon VPC).
    3. If the container binds to a specific port, only one copy can launch per instance.
    4. Configure a classic load balancer to use dynamic host port mapping.
  15. Which Amazon Elastic Container Service (Amazon ECS) task placement policy ensures that tasks are distributed as much as possible in a single cluster?

    1. Spread
    2. Binpack
    3. Random
    4. Least Cost
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset