Creating the Apache and MySQL playbooks – Immutable Infrastructure with Packer
As our goal is to spin up a scalable LAMP stack in this chapter, we must start by defining Ansible playbooks that would run on the build VM. We’ve already created some roles for Apache and MySQL in Chapter 9, Configuration Management with Ansible. We will use the same roles within this setup as well.
Therefore, we will have the following directory structure within the ch10 directory:
├── ansible
├── dbserver-playbook.yaml
├── roles
│ ├── apache
│ ├── common
│ └── mysql
└── webserver-playbook.yaml ├── packer
├── dbserver.pkr.hcl
├── plugins.pkr.hcl
├── variables.pkr.hcl
├── variables.pkrvars.hcl
└── webserver.pkr.hcl
└── terraform
├── main.tf
├── outputs.tf
├── terraform.tfvars
└── vars.tf
We have two playbooks within the ansible directory – webserver-playbook.yaml and dbserver-playbook.yaml. Let’s look at each to understand how we write our playbooks for Ansible.
webserver-playbook.yaml looks like the following:
hosts: default
become: true roles:
common
apache
dbserver-playbook.yaml looks like the following:
hosts: default
become: true roles:
common
mysql
As we can see, both playbooks have hosts set to default. That is because we will not define the inventory for this playbook. Instead, Packer will use the build VM to build the image and dynamically generate the inventory.
Note
Packer will also ignore any remote_user attributes within the task and use the user present in the Ansible provisioner’s config.
As we’ve already tested this configuration in the previous chapter, all we need to do now is define the Packer configuration, so let’s go ahead and do that in the next section.
Building the Apache and MySQL images using Packer and Ansible provisioners
We will now use Packer to create the Apache and MySQL images. Before defining the Packer configuration, we have a few prerequisites to allow Packer to build custom images.
Prerequisites
We must create an Azure service principal for Packer to interact with Azure and build the image.
First, log in to your Azure account using the Azure CLI with the following command:
$ az login
Now, set the subscription to the subscription ID we got in response to the az login command to an environment variable using the following:
$ export SUBSCRIPTION_ID=<SUBSCRIPTION_ID>
Next, let’s set the subscription ID using the following command:
$ az account set –subscription=”${SUBSCRIPTION_ID}”
Then, create the service principal with contributor access using the following command:
$ az ad sp create-for-rbac –role=”Contributor” \
–scopes=”/subscriptions/${SUBSCRIPTION_ID}”
{“appId”: “00000000-0000-0000-0000-00000”, “name”: “http://azure-cli-2021-01-07-05-59-24”, “password”: “xxxxxxxxxxxxxxxxxxxxxxxx”, “tenant”: “00000000-0000-0000-0000-0000000000000”}
We’ve successfully created the service principal. The response JSON consists of appId, password, and tenant values that we will use in the subsequent sections.
Note
You can also reuse the service principal we created in Chapter 8, Infrastructure as Code (IaC) with Terraform, instead.
Now, let’s go ahead and set the values of these variables in the packer/variables.pkrvars.
hcl file with the details:
client_id = “”
client_secret = “”
tenant_id = “”
subscription_id = “”
We will use the variable file in our Packer build. We also need a resource group for storing the built images.
To create the resource group, run the following command:
$ az group create -n packer-rg -l eastus
Now, let’s go ahead and define the Packer configuration.