Migrating Infrastructure to the Cloud using AWS and Chef


This is a guest post from Kamalika Majumder, an Independent Cloud and DevOps Consultant and founder of CloudKata (previously Senior Consultant at ThoughtWorks). For the past seven odd years, she has been helping enterprise customers apply DevOps practices and culture in their organisations and have also been helping them go to Cloud securely with scale.

You can check out Kamalika’s blog here: http://blogs.kamalika.net/. To read more of Kamalika’s case studies, go to CloudKata – an independent Cloud advisory on how to build, secure, scale and enable your applications on the cloud.

Discover the acclaimed Team Guides for Software – practical books on operability, business metrics, testability, releasability


One of the most common questions that organisations are trying to answer today is “How do I scale up to N number of customers?” and before even they find answer to that, there comes the next one “How do I reduce infrastructure and operational costs?”.

That’s where the cloud, in this instance as an IaaS (Infrastructure as a Service) provider comes into the picture.

On one of my recent projects, I had the opportunity to migrate a complete product suite to the cloud. In this article I share my experience on the various key factors that were involved in that process.

Key Achievements

As a result of moving this product to the cloud, here are some of the key benefits that were achieved:

  • Environment On Demand in less than an hour, which otherwise would take weeks.
  • Faster deployments cutting down the release cycles from months to weeks.
  • Onboarding new clients became much easier and could scale up to 10 times in a month.
  • All environments from dev to prod followed a standard architecture diagram bringing consistency in development and testing of application.

Tools and Tech

The Cloud provider chosen for this migration was AWS, which is by far the best among the public cloud service providers (???). It provides just about any infrastructure that you need as a service and exposes api endpoints enabling programmatic configuration. Some of the services that were consumed on AWS for this migration were:

  • VPC and EC2 for compute and networking,
  • Route53 for DNS, ELB for load balancing,
  • S3 and EBS for storage,
  • IAM and KMS for identity and key management.
  • RDS for database

In order to keep the orchestration and deployment process independent of any cloud platform, Chef was used as the orchestration and configuration management tool for the following:

  • Chef Provisioning, a library for creating machines and infrastructures idempotently in Chef was used to automate infrastructure provisioning like creation of VPC, subnets, instances, elastic load balancers, security groups, route 53 entries etc. on AWS.
  • Chef provisioning can be used as a driver for most cloud providers as AWS, Azure and more, and also can be used bare metal hypervisors such as VMware, Virtualbox etc.
  • Chef roles and environments were used to orchestrate the deployment.
  • Chef cookbooks and LWRPs were used for configuring the application and softwares. This workflow looked something like the diagram below.
  • Chef DK comes with a built in test framework, test-kitchen, which can be used to run Test driven infrastructure development.

The Operating Systems included both Microsoft Windows and enterprise Linux (RHEL series) flavors. Decisions around the above deployment tool choice were driven by the fact that the application can be deployed and supported in multiple cloud providers as well as on premise datacenters. A logical workflow diagram of this migration is described in the section below, followed by some example Chef code.

Logical Architecture Diagram:


As described above, Chef provisioning can be used to create each of the AWS services mentioned in the diagram. These are referred to as resources in Chef. For example, a resource to create VPC looks like this:

aws_route_table 'ref-main-route-table' do
  vpc 'ref-vpc'
  routes '' => :internet_gateway

aws_vpc 'ref-vpc' do
  main_route_table 'ref-main-route-table'
  main_routes '' => :internet_gateway

Below is a sample setup recipe creates a batch of ec2 instances with private IP, in a web subnet, assigns an IAM role, a web server Security Group, enables cloudwatch monitoring, and then bootstraps it with Chef.

Sample Chef Provisioning Code – setup.rb

require 'chef/provisioning/aws_driver' 
with_chef_server node['infra']['chef_server_url'],
                 client_name: client_name,
                 signing_key_filename: signing_key_filename

  convergence_options: {
    ssl_verify_mode: ssl_verify_mode,
  bootstrap_options:  {
    image_id: image_id,
    key_name: key_name,
  ssh_username: ssh_user_name,
  transport_address_location: :private_ip


machine_batch do
 1.upto(web_srv_count) do |i|
    machine "#{ppv_tenant_web_srv_name}#{i}-srv" do
      add_machine_options bootstrap_options: {
        block_device_mappings: [{
          device_name: device_name,
          ebs: {
            volume_size: 30,
            volume_type: 'gp2',
            delete_on_termination: true,
        instance_type: instance_type,
        security_group_ids: [web_srv_security_group_name],
        subnet_id: web_subnet_ids[i % web_subnet_ids.length],
        iam_instance_profile: {
          name: web_iam_role,
        monitoring: {
          enabled: true,
        disable_api_termination: true,
        user_data: "#{ppv_tenant_web_srv_name}#{i}-srv",
      files '/etc/chef/encrypted_data_bag_secret' => databag_secret
      chef_environment chef_environment
      run_list ppv_tenant_web_srv_runlist

The above code can be executed from a chef workstation as below:

$ chef-client -z -r setup.rb

Similar examples can be found here: https://github.com/chef/chef-provisioning-aws/tree/master/docs/examples.

Thus, as you can see in the diagram above,  a complete environment can be launched in AWS using a single chef client run in minutes, which in general might take you days to weeks if you are in an on premise datacenter, not to mention the overall operation costs and lack of consistency between dev and prod environments.

Lessons Learned:

  • Choose the tools and technologies to be as Cloud-provider agnostic as possible. The less they are dependent of the provider, the more they will be portable across various cloud platforms.
  • Package and Publish the app such that it can support multiple platforms.
  • Design Infrastructure Provisioning to support deployment at scale up.
  • Implement automated processes to achieve Continuous deployments of the application.
  • Ensure Security of both the application and the infrastructure to avoid compromise and loss of intellectual property and customer data.

Valuable links and references:

Chef-provisoning: https://github.com/chef/chef-provisioning

Leave a Reply

Please log in using one of these methods to post your comment:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: