Knife EC2: Manage Amazon EC2 Instances With Chef

by on August 3, 2015 · 22 comments

Chef enables you to automate your infrastructure. It provides a command line tool called knife to help you manage your configurations. Using the knife EC2 plugin you can manage your Amazon EC2 instances with Chef. knife EC2 makes it possible to create and bootstrap Amazon EC2 instances in just one line – if you go through a few setup steps. In this article, I want to show you how to setup your Chef installation and AWS configuration so that you can easily bootstrap new Amazon EC2 instances with Chef’s knife.

Prepare SSH Access To Your Amazon EC2 Instances

Configure Your Amazon Security Group
As Amazon blocks all incoming traffic to your EC2 instances by default. you’ll need to open the SSH port for knife to access a newly created instance. This is pretty easy. Just login to the AWS management console and navigate to EC2 under Services > Compute. Go to Security Groups and select the default group.

Open the Actions drop-down and choose Edit inbound rules:
AWS Security Group: Choose menu - Edit inbound rules

Then add a rule for Type SSH with Source Anywhere and save the new inbound rule:
AWS Security Group: Edit inbound rules screen

This enables SSH connections from anywhere (0.0.0.0/0) in the world. If you want to limit access to just your home or work network, choose Custom IP instead of Anywhere and enter the corresponding net mask.

When you’re done, your default security group should look like this:
AWS security setting SSH

Generate Key Pair in AWS Console
To enable SSH access to your Amazon EC2 instances you need to create a key pair. Amazon will install the public key of that key pair on every EC2 instance. knife will use the private key of that key pair to connect to your Amazon EC2 instances.

Just select Key Pairs under NETWORK & SECURITY in your AWS management console and press Create Key Pair. Give it a name (e.g. knife so you know that this key pair will be used by knife) and press Create. This will create the key pair and download the private key to your local workstation.

AWS management - create key pair

Store the downloaded private key knife.pem in ~/.ssh/knife.pem

Prepare your SSH configuration to avoid host key mismatch errors
Open your ~/.ssh/config and add:

Host ec2*compute-1.amazonaws.com
  StrictHostKeyChecking no
  User ubuntu
  IdentityFile  /Users/mm/.ssh/knife.pem

(make sure you fix the path to your home dir)

Now, SSH access to your Amazon EC2 instances will work. Time to move on to the next step.

Configure knife Enabling it to Manage EC2 Instances

Install the knife EC2 plugin
To enable knife to manage Amazon EC2 instances you need to install the knife EC2 plugin.

Either add it to your Gemfile or install it using gem:

$ gem install knife-ec2

The knife EC2 plugin adds the ec2 sub-command to knife, which we’ll use to manage our Amazon EC2 instances.

Tell knife about your AWS credentials
Create a new user for knife in your AWS management console under Services > Administration & Security. You’ll use this user’s AWS credentials (access key ID and secret access key) to manage your Amazon EC2 instances with knife EC2.

Add the AWS credentials of your knife user to your knife configuration file ~/.chef/knife.rb:

knife[:aws_access_key_id] = "..."
knife[:aws_secret_access_key] = "........."

Now, knife should be able to use the Amazon AWS API to manage Amazon EC2 instances.

Choose an AMI for your Amazon EC2 instances
We’re going to instantiate an Amazon EC2 instance running Ubuntu 14.04 LTS.

Look here for Ubuntu 14.04 LTS AMI IDs which you can use to instantiate Amazon EC2 instances with knife.

You need to choose the right AMI for your region, architecture and root storage. Note down the AMI ID (ami-XXXXXXXX) to use it with knife.

Create an EC2 instance using Chef knife
Now, it’s time to use knife to fire up and configure a new Amazon EC2 instance.

$ knife ec2 server create -r "role[ubuntu]" -I  ami-1ed88f69 -f t2.small \
  -S knife -i ~/.ssh/knife.pem --ssh-user ubuntu --region eu-west-1 -Z eu-west-1a
  • "role[ubuntu]" is the run_list I want to associate with the newly created node. You can put any roles and recipes you like here
  • -I is the AMI ID you selected earlier
  • -f is the Amazon EC2 instance type (see Model)
  • -S is the name you gave to the SSH key pair generated in the AWS management console
  • -i points to the private key file of that SSH key pair as downloaded when the key pair was created in the AWS management console
  • --ssh-user the official Ubuntu EC2 AMIs use ubuntu as the default user
  • --region eu-west-1 If you want your instances to be deployed in any specific Amazon AWS region, add this parameter and the desired region
  • -Z eu-west-1a is the availability zone within your region

ATTENTION: make sure to kill the instance again if not needed anymore 😉

Managing Amazon EC2 Instances With knife

Once you’ve started up at least one Amazon EC2 instance with knife, you can use knife to find running EC2 instances like this:

$ knife ec2 server list --region eu-west-1

(make sure you use the correct --region parameter)

And, if you want to get rid of an instance (terminate instance and delete the corresponding Chef node), it’s as easy as:

$ knife ec2 server delete i-XXXXXXXX --region eu-west-1
$ knife node delete i-XXXXXXXX

(i-XXXXXXXX is the ID of the instance as found in the AWS management console or a knife ec2 server list call)

After getting the initial setup right it’s a breeze to start, list, and stop your EC2 instances at Amazon with Chef’s knife ec2. With just a single command you can instantiate a new server, bootstrap it as a Chef client and run all Chef recipes defined in the run_list. Pretty sweet. What are your experiences with knife and Amazon EC2 (or other cloud providers)? Let us know in the comments…

Did you enjoy this article? Get new articles for free by email:

Comments

  1. Sean Gallagher says

    Thanks for the post!
    Check your command for:
    “Create the EC2 instance using opscode chef knife”
    >> should be -I (capital) for ami and -i (lowercase) for pem file

  2. Rajat says

    Hi Matthias

    Thanks for the post. I have a ques. I want to use my own custom ami to launch the ec2 machine. How to do that?

    Thanks in advance
    Rajat

  3. anoldguy says

    I think you’re missing a ‘-r’ before “role[ubuntu]” in your knife command. It should look like this:

    knife ec2 server create -r “role[ubuntu]” -I ami-399ca94d -f m1.small -S knife -i ~/.ssh/knife.pem –ssh-user ubuntu –region eu-west-1 -Z eu-west-1a

  4. EJC says

    No matter what I do, I keep getting the message:

    ERROR: You have not provided a valid image (AMI) value. Please note the short option for this value recently changed from ‘-i’ to ‘-I’.

    I even tried the exact example you guys gave as well as with some of the ami’s I’ve created with no luck. Any suggestions? Adding -VV doesn’t help either…

  5. EJC says

    hmmmm- interesting – but I’m not using any double dashes anywhere. The help output suggests -I = the AMI for the server and the -i = the identitiy file – so I’m NOT mixing those up either.

    Any other suggestions?

  6. EJC says

    Ok, started over, created a new ami and left it running. From there I took note of zone and region. Then I could run the command with the region and zone options and now it’s sitting waiting for sshd…

    I get the feeling it’s going to crash out…

  7. EJC says

    Yeah, not sure what else to do, but the ssh portion never seems to connect/get set up properly.

    Any final suggestions?

  8. EJC says

    ok, got it – enabled the ssh rule for the default security group (doh!).

    Next issue is we’re hosting our own chef server – this writeup is ONLY good for people NOT hosting their own chef server?

  9. Cassiano Leal says

    Also, you might try to specify on the command line parameters such as region and availability_zone, maybe others.
    Currently there’s a bug in knife-ec2 that overrides some parameters set in knife.rb.

  10. Ran says

    Hi, thanks for the post, this was very useful!

    But I’m having trouble, and google didn’t help…
    I get the following error:
    ERROR: Fog::Compute::AWS::Error: SignatureDoesNotMatch => The request signature we calculated does not match the signature you provided. Check your AWS Secret Access Key and signing method. Consult the service documentation for details.

    I get this error for all knife ec2 commands (server create, server list etc)
    But when using the same key ID and secret access key with the EC2 command line tools provided by amazon, all is well! So I’m a bit confused…
    I tried two different amz accounts and the same problem.
    I tried using -A and -K explicitly, didn’t work. I tried putting them in ~/.chef/knife.rb file and still no dice.

    I haven’t found anyone else with the same error on google. Any idea how to proceed?

    $ knife -v
    Chef: 10.14.2

    thank you!

  11. says

    Just the tutorial I needed. Thanks for the great writeup! One small issue I run into (it doesn’t effect the creation/deletion of instances but was curious if you had a solution) is that I get errors as chef tries to create a node in the chef server. I’m using chef solo so I was wondering if there was a setting I’m missing to prevent knife from trying to create/remove the nodes on the server. Any insight is appreciated. Thanks again for the good writeup!

  12. dflower says

    Did you ever find the solution to this? I have the same issue, but it only happens when I run knife/chef from behind my companies firewall. At home the exact same command/scripts work fine.

  13. Chris Olido says

    Ih having problems with the validation.pem. Technically my validation.pem is correct and identical to the chef server and to the client when i compare it.

    When im issuing:

    knife ec2 server create -r “role[wordpress]” -E staging -S www-sg -I ami-b2a2**** –flavor t1.micro –region ap-southeast-1 -G public_www -x ubuntu -N testme

    im having an error like this:

    Chef::Exceptions::InvalidPrivateKey: The file /etc/chef/validation.pem does not contain a correctly formatted private key.
    The key file should begin with ‘—–BEGIN RSA PRIVATE KEY—–‘ and end with ‘—–END RSA PRIVATE KEY—–‘
    /opt/chef/embedded/lib/ruby/gems/1.9.1/gems/chef-10.16.2/lib/chef/rest/auth_credentials.rb:68:in `rescue in load_signing_key’
    /opt/chef/embedded/lib/ruby/gems/1.9.1/gems/chef-10.16.2/lib/chef/rest/auth_credentials.rb:60:in `load_signing_key’
    /opt/chef/embedded/lib/ruby/gems/1.9.1/gems/chef-10.16.2/lib/chef/rest/auth_credentials.rb:34:in `initialize’
    /opt/chef/embedded/lib/ruby/gems/1.9.1/gems/chef-10.16.2/lib/chef/rest.rb:64:in `new’
    /opt/chef/embedded/lib/ruby/gems/1.9.1/gems/chef-10.16.2/lib/chef/rest.rb:64:in `initialize’
    /opt/chef/embedded/lib/ruby/gems/1.9.1/gems/chef-10.16.2/lib/chef/client.rb:325:in `new’
    /opt/chef/embedded/lib/ruby/gems/1.9.1/gems/chef-10.16.2/lib/chef/client.rb:325:in `register’
    /opt/chef/embedded/lib/ruby/gems/1.9.1/gems/chef-10.16.2/lib/chef/client.rb:407:in `do_run’
    /opt/chef/embedded/lib/ruby/gems/1.9.1/gems/chef-10.16.2/lib/chef/client.rb:176:in `run’
    /opt/chef/embedded/lib/ruby/gems/1.9.1/gems/chef-10.16.2/lib/chef/application.rb:140:in `run_chef_client’
    /opt/chef/embedded/lib/ruby/gems/1.9.1/gems/chef-10.16.2/lib/chef/application/client.rb:274:in `block in run_application’
    /opt/chef/embedded/lib/ruby/gems/1.9.1/gems/chef-10.16.2/lib/chef/application/client.rb:267:in `loop’
    /opt/chef/embedded/lib/ruby/gems/1.9.1/gems/chef-10.16.2/lib/chef/application/client.rb:267:in `run_application’
    /opt/chef/embedded/lib/ruby/gems/1.9.1/gems/chef-10.16.2/lib/chef/application.rb:72:in `run’
    /opt/chef/embedded/lib/ruby/gems/1.9.1/gems/chef-10.16.2/bin/chef-client:26:in `’
    /usr/bin/chef-client:23:in `load’

    any recommendation would be appreciated.

    By the way Thanks again for the good writeup…