Puppet is an open source platform for provisioning, configuring, and patching applications and OS components. A Puppet deployment has two components: Puppet master and Puppet client. The Puppet master is a centralized configuration server that holds the definitions and instructions needed to install your applications. A Puppet client connects to the Puppet server and downloads the necessary instructions to install and update the software running on it.
In Puppet, you have to describe machine configurations in Puppet's own Domain Specific Language (DSL). Central to using Puppet is declaring resources. Each resource describes some aspect of a system, like a file that must be copied or a package that must be installed. Resources are often grouped into classes that are organized into modules. Groups of resource declarations and conditional statements can be specified in a class.
Manifests are files containing Puppet code and are text files saved with a .pp
extension. Most manifests are arranged into modules so that they can be automatically located and loaded by the Puppet master. Modules can contain many Puppet classes.
You can find hundreds of modules in the puppet forge website. Puppet comes with a module tool to interact with forge. Geppeto is an Eclipse-based editor for writing Puppet code. Before starting these recipes, you must have a working Puppet master setup with Puppet Version 3.4 or greater and Ruby Version 1.9.
Execute the following steps to install the Puppet AWS module:
gem install aws-sdk-core
gem install retries
export AWS_ACCESS_KEY_ID=Access Key Id
export AWS_SECRET_ACCESS_KEY=Secret Access Key
puppet module install puppetlabs-aws
Execute the following steps in the Puppet master. Our Puppet master is running on an Ubuntu 12.04 LTS machine.
/etc/puppet/modules
folder.aws_prod
.aws_prod
module folder, create a new folder called manifests
.manifests
folder, create a file called init.pp
with the following content:class aws_prod { ec2_instance { 'instance-02': ensure => present, key_name => 'ApacheServerKeyPair', region => 'us-east-1', image_id => 'ami-a6afb8ce', instance_type => 't1.micro', user_data => template('aws_prod/install-agent.sh') } }
The Puppet AWS module allows you to manage AWS using the Puppet DSL. The following code sets up a very basic instance. Here we are passing a shell script that installs Puppet agent in this new EC2 instance.
templates
inside the aws_prod
module folder.templates
folder, create a new file with the name install-agent.sh
.install-agent.sh
file. Replace Puppet server URL with your Puppet server URL.#!/bin/bash set -e -x PuppetServer=Puppet Server URL AgentCertName=$(curl -s http://169.254.169.254/latest/meta-data/instance-id) cd ~; wget https://apt.puppetlabs.com/puppetlabs-release-trusty.deb dpkg -i puppetlabs-release-trusty.deb apt-get update apt-get -y install puppet echo " [agent] server=$PuppetServer certname=$AgentCertName runinterval=5 " >> /etc/puppet/puppet.conf sed -i /etc/default/puppet -e 's/START=no/START=yes/' service puppet restart
puppet apply --modulepath=/etc/puppet/modules -e "include aws_prod"
After executing the preceding command, you can see the new EC2 instance, preconfigured with Puppet agent, in the AWS console.
Instead of writing our own module, we can also install the module hosted on the Puppet Module Forge using the following commands. For example, if we want to install Apache server on EC2 instance, then execute the following command on Puppet master:
puppet module install puppetlabs-apache
Create a sample index.html
file in the folder specified at path /etc/puppet/modules/apache/files
.
In the /etc/puppet/manifests/site.pp
file add the following content:
node 'i-6e3553b8' { class { 'apache': default_vhost => false } apache::vhost { 'example.com': port => '80', docroot => '/var/www' } file { '/var/www/index.html': source => "puppet:///modules/apache/index.html" } }
When the Puppet agent runs, it will install Apache server on your EC2 instance, and you can browse your index.html
at http://EC2 Instance Public DNS/
.
Before installing Puppet AWS module, you must install AWS Ruby SDK gem and the Retries gem. If you are using the open source puppet, these gems should be installed into the same Ruby instance used by Puppet. The Puppet module allows you to specify AWS resource types in your manifest files. You can configure AWS resources such as EC2 instances, security groups, VPCs, and so on.
The first time Puppet runs in an agent node, it will send a certificate-signing request to the Puppet master. Before the master is able to communicate and control the agent node, it must sign that particular agent node's certificate. If you want to autosign any new client certificates that are sent to the puppet master, add the following configuration in the [master]
section of puppet configuration file (by default, it is located at /etc/puppet/puppet.conf
):
autosign = true
We also specified the key/pair name, AWS region, image ID, and instance type for our new EC2 instance. When you launch an instance in Amazon EC2, you have the option of passing user data to the instance that can be used to perform common automated configuration tasks and even run scripts after the instance starts.
We created the install-agent.sh
file in the templates
folder of the aws_prod
Puppet module. This shell script gets the instance ID from EC2 instance metadata URL. This is also used for the certificate name, install Puppet agent [Puppet agent Version 3.7.5], and roll out the node with Puppet. The frequency with which the puppet agent applies the catalog is based on the run interval value; here, we have specified it to be 5 minutes (the default value is 30 minutes).
In the case of installing from the Puppet Module Forge, a node statement allows you to assign specific configurations to specific nodes. We specify the previously created EC2 instance ID as the node value and add a virtual host, specify a port, and copy the index.html
file from the Apache module to the Apache document root folder.
Puppet integrates with AWS CloudFormation. CloudFormation provisions the resources required for your applications. You can use a CloudFormation template to bootstrap a Puppet master. The template specifies the location for content that is used to populate the Puppet master with the application and OS configurations. These configurations can be downloaded to Puppet clients.
AWS CloudFormation also provides a facter plugin that interprets the template metadata to configure applications and roles deployed via Puppet. Using template metadata, you can bootstrap a base OS and the Puppet client, configure roles for the client, and install and run the software packages.
For installing the Puppet client, you can create a template that creates an EC2 instance running the Puppet client (configured to install a server role from the Puppet master). Note that for highly available and scalable applications, you can create multiple instances using an autoscaling group and span across multiple availability zones. You will need to provide the security group and Puppet master DNS name. The Puppet client metadata defines the packages to run, deploy, and configure the client software to access the Puppet master.
AWS CodeDeploy deploys your application code to EC2 instances while ensuring it leaves as many of your instance online as possible. CodeDeploy can also be used in conjunction with Puppet scripts.