Deployment Terminology#
It's probably a good idea to be familar with a few core Chef concepts, though digging deeply into Chef is definitely not something I encourage Python developers to do.
Resource
: The basic building block in Chef (and also Ansible); defines files, directories, installed packaes, services, etc.
Recipe
: A collection of resource definitions with some logic to connect them. These can be very simple or extraordinarily complex; A recipe can depend on other recipes. These basically play the same role asTasks
in Ansible.
Cookbook
: A collection of recipes required to setup a service or similar. These play a similar role toRoles
in Ansible. These generally can be found in the Chef Supermarket like Roles from the Ansible Galaxy.
Berkshelf
: A single file configuration defining the set of cookbooks needed for a deployment. It consists of aBerksfile
which defines locations and versions of all cookbooks required for a deployment.
Attributes
: The deployment specific configuration for the cookbook and recipes. This is essentially a collection of JSON like primitives, similar to YAML group/hostVars
.
Opsworks#
Amazon OpsWorks takes this basic configuration framework and provides its own set of concepts, to implement cluster orchestration.
When using OpsWorks, you will be making use built-in OpsWorks Chef Cookbooks provided by Amazon. These built-in Cookbooks provide a number of Recipes for configuring and deploying many types of applications using TTW (Through-The-Web) configuration from the OpsWorks control panel.
These include Node.js, Rails, PHP , and Java applications, but not Python [1].
I've created a couple supplemental Cookbooks that extend the existing OpsWorks deployment recipes to support Python and Plone along with other supporting services that are useful when making production deployments of Plone.
OpsWorks has its own vocabulary of concepts related to deploying and orchestrating clusters of servers.
The building blocks of OpsWorks are:
Stack
: The fundamental container for your configuration, this lives in a particular EC2 region and contains all the configuration for your cluster. Typically you would have a separate production stack and development stack. Creating this is the first step in the process of defining your cluster. Stacks can be cloned to replicate configuration across regions.Layers
: A Layer defines a discrete set of functionality that may be provided by a server Instance. For example, a Plone cluster may have a frontend Layer running an Nginx web server, Varnish proxy cache and HAProxy load balancer [2] , an Application Layer for your ZEO client instances, an Application Layer for your ZEO server, and a maintenance layer to manage database backups and packs. Layers define what recipes will be run on an instance, and which OS packages it requires, along with any Amazon resources and permissions are required to provide a service (e.g. static IP addresses, additional EBS storage volumes).Instances
: An OpsWorks Instance is similar to an EC2 instance, it has a type (e.g. from micro to xlarge), an OS and an Availability Zone, but it is an abstraction. It becomes an actual EC2 instance once it's been started, but before that it's simply a metadata about a desired server. Instances are assigned to one or more Layers, and come in three varieties, 24/7, time-based and load-based.Apps
: An App points to a code repository (in our case a buildout) which you want to deploy to a specific Application Layer. Typically you would have an App for your Plone instances and another for your Zeoserver. Both these Apps would typically point to the same buildout repository. You might also create an App to configure a Plone specific Solr server or to run a additional applications within the cluster.Resources
: A set of Amazon EC2 resources that will be used by the stack by being attached/assigned to Instances when they are started. These include Elastic IP addresses, EBS storage volumes and RDS databases (useful you are running Relstorage).
A Stack can be configured with a single Instance running all the Layers, or multiple Instances each running different Layers. You might, for example, have a production stack with five Instances running the Plone ZEO client Application Layer, a single instance running the ZEO server Application Layer, and two Instances running the front end proxy/loadbalancer Layer (with an Elastic Load Balancer in front of those).
You might also have a staging stack with all the same Layers applied to a single modest server. Other than the Instance definitions (and perhaps the App repository branch), these Stacks would be essentially identical.
Instance Lifecycle#
Each OpsWorks Instance goes through a few phases during its lifecycle:
setup
deploy
configure
undeploy
shutdown
Each of these lifecycle phases runs recipes assigned to that phase in the assigned Layers. When these recipes are run, the Stack configuration is passed to the server.
This configuration includes complete information about the state of the entire Stack and all of its running Instances.
When an Instance starts, it first goes through a setup
phase: installing all package dependencies
for all assigned Layers and running all the recipes assigned to the setup
phase of those Layers.
Once the setup
phase is complete, a deploy
phase is automatically started.
Running all the recipes assigned to the deploy
phase of any assigned Layers.
Subsequently, you may manually run a deploy
for a specific Application on
any or all of the instances to update the application code and reconfigure services.
The shutdown
phase is run automatically before an instance is stopped.
The undeploy
phase is rarely used. It is triggered when an application is manually removed from an instance.
Whenever an Instance is started or stopped and it's setup
or shutdown
phase has completed a configure
phase is initiated on all running
instances.
As with all recipe runs, the configure
phase recipes are passed data about all the currently running Instances and their Layers so that they
can automatically reconfigure themselves based on the updated state of the Stack.
For example, a load balancer may need to automatically add or remove Plone ZEO clients from it's list of active backends, a ZEO client may need to change its ZEO server or its Relstorage Memcache if configuration for those services have changed.
This configure
phase, during which the current cluster state is automatically shared with all the instances, is where the orchestration magic
happens.