Pages

Sunday, April 22, 2018

immutable infrastructure with Packer

Immutable infrastructure is an approach to manage services and software deployments on IT resources wherein components are replaced rather than changed. In a production environment when we try to deploy application, we usually undeploy the existing application and then deploy a new version. We usually make the changes in the existing infrastructure only.


In immutable infra , we deploy a new infrastructure with new version of code rather than making changes ( deploying new version of code ) to the existing infrastructure. This immutable infra is managed by the images. Once we want to deploy a new version of code, we make changes to the image and built infra from the Images.


These Images can be Aws , Docker or any cloud. We need a tool for creating these machine images. The tool should also allow to get the application source code and give a complete image with application source code even where we can build the machine.


Packer is one such tool. This is Image creation tool which can automate the process image creation with various on-premise and cloud services. The tool is from the HashiCorp. This helps in building identical machine images for multiple platform from a single source configuration. The tool is lightweight , run on every major operating system. Packer comes out of the box with support to many platforms. The tool is written in GO language. Packer takes advantage of an extensible plugin architecture to allow the same source templates to be used with multiple builders, provisioners, and post-processors to create artifacts.


In this article we will see how we can create a container image file.


1. Install the Packer tool
Packer tool can be downloaded from “https://www.packer.io/downloads.html”. Choose the download based on your operating system.


2. Configure the Packer tool
Set the PATH pointing to Packer
Export PATH=$PATH:<Path to the Packer tool>


3. Confirm the packer version using
[root@kube-master packer]$  packer version
Packer v1.1.1


Building the Image
Packer configuration is written on templates in JSON format. The template has 3 main parts


Variables - This is the place where we define custom variables
Builders - This is the place where we mention all the required AMI parameters
Provisioners - This is the place where we can integrate a Shell script, ansible playbook or a chef cookbook

A sample example using all 3 parts is


{
 "variables": {
   "aws_access_key": "",
   "aws_secret_key": ""
},
{
   "builders":[{
       "type": "docker",
       "image": "centos"
    }],


   "provisioners":[
       {
           "type": "shell",
           "inline": [
               "yum -y update",
               "yum install ansible"
           ]
       },
       {
           "type": "ansible-local",
           "playbook_file": "playbooks/local.yml"
       }
   ]


Variables -  The Variable block holds all the default variables within a template. An simple example


“Variables”: {
   “Instance_type”: “t2_medium”
   “region” : “mumbai”
}


The declared variables can be accessed in other parts of the template using “{{ instance_type }}’


Environment variables can be set and accessed from the template as


“variables” : {
   “Script_path” : “{{ env `SCRIPT_PATH` }}
}

Provisioners  - Provisioners are used to execute scripts on a local or remote machine as part of resource creation or destruction. Provisioners can be used to bootstrap a resource, cleanup before destroy, run configuration management, etc.


"provisioners": [  {
   "type": "shell",
   "script": "/tmp/hello..sh"
   }]


Packer supports multiple provisioners like ansible ,shell , chef , puppet etc


Builders - This section contain an array of the builders that packer should use to generate a machine images for the template


{
   "builders":[{
       "type": "docker",
       "image": "centos"
}],


In this section we are trying to create a Docker image by defining in the builder section.


Docker Image file based on Centos
Based on the builders, variables and provisioners of Packer , below is an example of the packer template file for creating a docker images. This will use the centos image and will use the shell provisioner to update packages and install ansible.


We are then using the ansible playbook as another provisioner. We are running local.yml file as a provisioner


[root@ip-10-149-70-139 opt]# cat machine_ansible.json
{
   "builders":[{
       "type": "docker",
       "image": "centos",
       "export_path": "image.tar"
   }],
   "provisioners":[
       {
           "type": "shell",
           "inline": [
               "yum -y update",
               "yum install ansible"
           ]
       },
       {
           "type": "ansible-local",
           "playbook_file": "playbooks/local.yml"
       }
   ],
   "post-processors": [
       {
           "type": "docker-import",
           "repository": "example/packer-ansible",
           "tag": "0.1"
       }
   ]
}


In the Post-processors section , we are importing that created images and added to the repository.


Validate the Packer template using,
[root@kube-master packer]$  ./packer validate centos_docker_image.json
Template validated successfully.


Inspect the Packer template using,
[root@kube-master packer]$  ./packer inspect centos_docker_image.json
Optional variables and their defaults:


 base_image     =
 java_version   =
 tomcat_version =
 yum_package    =


Builders:
 docker


Provisioners:
 shell
 ansible-local
 shell


Note: If your build names contain user variables or template functions such as 'timestamp', these are processed at build time, and therefore only show in their raw form here.


The local.yml ansible file looks like,
[root@kube-master playbooks]$  cat local.yml
---
- hosts: 127.0.0.1
  remote_user: root
  gather_facts: no
  tasks:
   - name: Displayout
     shell: echo "helloworld" >> /hello


Build the Image using.
./packer build  -var 'base_image=centos' -var 'java_version=7' -var 'tomcat_version=7' -var 'yum_package="vim,git"' centos_docker_image.json


Once the build is successfully ran ,we can see a docker image as,
[root@kube-master packer]$  docker images
REPOSITORY          TAG IMAGE ID            CREATED SIZE
docker.io/centos    latest e934aafc2206        2 weeks ago 199 MB


There are the basics of the Packer tool and how they work. More to come. Happy Learning.

1 comment :

  1. Having read this I believed it was extremely enlightening.
    I appreciate you spending some time and energy to put this short article together.

    I once again find myself personally spending a significant amount of time both reading and posting comments.
    But so what, it was still worthwhile!

    ReplyDelete