<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Packer &#8211; Johnny Morano&#039;s Tech Articles</title>
	<atom:link href="https://jmorano.moretrix.com/tag/packer/feed/" rel="self" type="application/rss+xml" />
	<link>https://jmorano.moretrix.com</link>
	<description>Ramblings of an old-fashioned space cowboy</description>
	<lastBuildDate>Sat, 09 Apr 2022 06:58:20 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.6.2</generator>

<image>
	<url>https://jmorano.moretrix.com/wp-content/uploads/2022/04/cropped-jmorano_emblem-32x32.png</url>
	<title>Packer &#8211; Johnny Morano&#039;s Tech Articles</title>
	<link>https://jmorano.moretrix.com</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>Using Ansible to finalize Hashicorp Packer images</title>
		<link>https://jmorano.moretrix.com/2022/04/using-ansible-to-finalize-hashicorp-packer-images/</link>
					<comments>https://jmorano.moretrix.com/2022/04/using-ansible-to-finalize-hashicorp-packer-images/#respond</comments>
		
		<dc:creator><![CDATA[Johnny Morano]]></dc:creator>
		<pubDate>Fri, 08 Apr 2022 09:23:30 +0000</pubDate>
				<category><![CDATA[Automation]]></category>
		<category><![CDATA[Blog]]></category>
		<category><![CDATA[Terraform]]></category>
		<category><![CDATA[Ansible]]></category>
		<category><![CDATA[Azure]]></category>
		<category><![CDATA[Cloud]]></category>
		<category><![CDATA[DevOps]]></category>
		<category><![CDATA[Hashicorp]]></category>
		<category><![CDATA[Packer]]></category>
		<guid isPermaLink="false">https://jmorano.moretrix.com/?p=1430</guid>

					<description><![CDATA[Ansible provides a more flexible way to fine-tune Hashicorp Packer images compared to cloud-init. Playbooks can be executed&#8230;]]></description>
										<content:encoded><![CDATA[
<p><a rel="noreferrer noopener" href="https://www.ansible.com/" data-type="URL" data-id="https://www.ansible.com/" target="_blank">Ansible</a> provides a more flexible way to fine-tune <a rel="noreferrer noopener" href="https://www.packer.io/" data-type="URL" data-id="https://www.packer.io/" target="_blank">Hashicorp Packer</a> images compared to <a rel="noreferrer noopener" href="https://cloudinit.readthedocs.io/en/latest/" data-type="URL" data-id="https://cloudinit.readthedocs.io/en/latest/" target="_blank">cloud-init</a>. Playbooks can be executed once the guest image building is ready and boots up for the first time. This allows to create different types of Packer images based on different playbooks.</p>



<p>In this article, Packer images will created for <a href="https://azure.microsoft.com/en-us/" data-type="URL" data-id="https://azure.microsoft.com/en-us/" target="_blank" rel="noreferrer noopener">Azure</a> using <a href="https://www.packer.io/plugins/builders/azure/arm" data-type="URL" data-id="https://www.packer.io/plugins/builders/azure/arm" target="_blank" rel="noreferrer noopener">azure-arm</a> build type. The images will use an <a href="https://ubuntu.com/" data-type="URL" data-id="https://ubuntu.com/" target="_blank" rel="noreferrer noopener">Ubuntu</a> image available on Azure, as base image.</p>



<p>Let&#8217;s consider the following head of a Packer <a rel="noreferrer noopener" href="https://www.packer.io/docs/templates" data-type="URL" data-id="https://www.packer.io/docs/templates" target="_blank">template</a> file:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="json" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">{  
  "builders": [{
      "type": "azure-arm",

      "use_azure_cli_auth": true,
      "subscription_id": "{{ user `subscription_id` }}",

      "managed_image_resource_group_name": "{{user `resource_group`}}",
      "managed_image_name": "{{user `managed_image_name`}}",

      "os_type": "{{user `basevm_os_type`}}",
      "image_publisher": "{{user `basevm_publisher`}}",
      "image_offer": "{{user `basevm_offer`}}",
      "image_sku": "{{user `basevm_sku`}}",

      "virtual_network_name": "{{user `virtual_network_name`}}",
      "virtual_network_resource_group_name": "{{user `virtual_network_resource_group_name`}}",
      "virtual_network_subnet_name": "{{user `virtual_network_subnet_name`}}",

      "azure_tags": {
        "dept": "DevOps",
        "task": "My custom base image"
      },

      "location": "{{user `location`}}",
      "vm_size": "{{user `vm_size`}}",

      "os_disk_size_gb": "{{user `os_disk_size_gb`}}",

      "shared_image_gallery_destination": {
        "subscription": "{{ user `subscription_id` }}",
        "resource_group": "{{user `resource_group`}}",
        "gallery_name": "{{user `gallery_name`}}",
        "image_name": "{{user `base_image`}}",
        "image_version": "{{user `base_image_version`}}",
        "replication_regions": "{{user `replication_regions`}}"
      },
      "shared_image_gallery_timeout": "2h1m1s"
    }],
</pre>



<p>All the variables surrounded by <code>{{user `` }}</code> are template variables, and must be configured in a separate file, example <code>my_base_image_vars.json</code>, which will be included later-on when initiating the Packer <a href="https://www.packer.io/docs/commands/build" data-type="URL" data-id="https://www.packer.io/docs/commands/build" target="_blank" rel="noreferrer noopener">build</a> command. The final image will be stored in <a href="https://azure.microsoft.com/" data-type="URL" data-id="https://azure.microsoft.com/" target="_blank" rel="noreferrer noopener">Azure</a>, in a <a href="https://docs.microsoft.com/en-us/azure/virtual-machines/shared-image-galleries" data-type="URL" data-id="https://docs.microsoft.com/en-us/azure/virtual-machines/shared-image-galleries" target="_blank" rel="noreferrer noopener">Shared Image Gallery</a>.</p>



<p>Packer however allows to configure extra <a rel="noreferrer noopener" href="https://www.packer.io/docs/provisioners" data-type="URL" data-id="https://www.packer.io/docs/provisioners" target="_blank">provisioners</a>, which will be executed once the initial virtual machine has been created and before the final image will be created.</p>



<p>One of those provisioner types is the <a rel="noreferrer noopener" href="https://www.packer.io/plugins/provisioners/ansible/ansible-local" data-type="URL" data-id="https://www.packer.io/plugins/provisioners/ansible/ansible-local" target="_blank">ansible-local</a> type. This provisioner allows to execute Ansible playbooks (and roles) once the virtual machine is booted, directly on the guest machine.</p>



<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">    "provisioners": [
      {
        "type": "shell",
        "inline_shebang": "/bin/sh -x",
        "execute_command": "chmod +x {{ .Path }}; {{ .Vars }} sudo -E sh '{{ .Path }}'",
        "script": "presetup.sh"
      },
      {
        "type": "ansible-local",
        "playbook_file": "./ansible/default_setup.yml",
        "playbook_dir": "./ansible",
        "role_paths": ["./ansible/defaults"],
        "clean_staging_directory": true,
        "staging_directory": "/tmp/packer-provisioner-ansible-local",
        "extra_arguments" : [ "--extra-vars", "ansible_python_interpreter=/usr/bin/python3" ]
      },
</pre>



<p>The first provisioner called, is the <a rel="noreferrer noopener" href="https://www.packer.io/docs/provisioners/shell" data-type="URL" data-id="https://www.packer.io/docs/provisioners/shell" target="_blank">shell</a> provisioner. This provisioner will upload and execute the script <code>presetup.sh</code>. This script could for instance ensure that the Ansible package is already installed before the next provisioner is called.</p>



<p>The second provisioner is the <a rel="noreferrer noopener" href="https://www.packer.io/plugins/provisioners/ansible/ansible-local" data-type="URL" data-id="https://www.packer.io/plugins/provisioners/ansible/ansible-local" target="_blank">ansible-loca</a>l type. The provisioner requires some parameters that must be configured:</p>



<ul class="wp-block-list"><li><code>playbook_file</code>: the Ansible playbook which will be executed</li><li><code>playbook_dir</code>: the base directory of the Ansible playbooks, roles, static_files, &#8230;</li><li><code>role_paths</code>: the path of the role which will be called in playbook_file (when required)</li></ul>



<p>The above example will upload all files in the <code>./ansible</code> directory (parameter <code>playbook_dir</code>) to the new guest virtual machine, to the directory configured in <code>staging_directory</code>, and will call the Ansible playbook <code>default_setup.yml</code>.</p>



<pre class="EnlighterJSRAW" data-enlighter-language="yaml" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">---
- name: Default post installation
  hosts: all
  connection: local
  become: yes
  tasks:
    - name: Import the Microsoft signing key into apt
      apt_key:
        url: "https://packages.microsoft.com/keys/microsoft.asc"
        state: present

    - name: Add the Azure CLI software repository
      apt_repository:
        repo: "deb [arch=amd64] https://packages.microsoft.com/repos/azure-cli/ {{ansible_distribution_release}} main"
        filename: azure-cli
        state: present

  roles:
    - defaults
</pre>



<p>The above Ansible playbook use the parameter <code><mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-vivid-red-color">connection: local</mark></code>. This is very important and must be included in each playbook executed by the ansible-local provisioner.</p>



<p>At first the playbook will execute two tasks which will ensure that the <a href="https://docs.microsoft.com/en-us/cli/azure/install-azure-cli-linux?pivots=apt" data-type="URL" data-id="https://docs.microsoft.com/en-us/cli/azure/install-azure-cli-linux?pivots=apt" target="_blank" rel="noreferrer noopener">Microsoft Azure-CLI APT repository</a> is installed and properly set up.</p>



<p>Afterwards, it will call the <code><mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-vivid-red-color">defaults</mark></code> Ansbile <a href="https://docs.ansible.com/ansible/latest/user_guide/playbooks_reuse_roles.html" data-type="URL" data-id="https://docs.ansible.com/ansible/latest/user_guide/playbooks_reuse_roles.html" target="_blank" rel="noreferrer noopener">role</a>. This role is set up as a typical <a href="https://docs.ansible.com/ansible/latest/user_guide/playbooks_reuse_roles.html" data-type="URL" data-id="https://docs.ansible.com/ansible/latest/user_guide/playbooks_reuse_roles.html" target="_blank" rel="noreferrer noopener">Ansible role</a>:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="shell" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">ansible/defaults:
tasks  templates  vars

ansible/defaults/tasks:
main.yml

ansible/defaults/templates:
modprobe_blacklist.j2  policy-rc.d.conf.j2  policy-rc.d.j2  securetty.j2  sysctl_base.j2

ansible/defaults/vars:
main.yml
</pre>



<p>The <code>main.yml</code> in the <code><mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-vivid-red-color">tasks</mark></code> sub-directory is used to configure the required post installation steps.</p>



<p>Example:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="yaml" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">---
- name: Ensure default packages
  apt:
    name: "{{ default_packages }}"
    state: latest

- name: Ensure latest version of all packages
  apt:
    upgrade: dist
    force_apt_get: yes
    dpkg_options: 'force-confold,force-confdef'
    autoremove: yes
    autoclean: yes

- name: Update python alternatives (for Log Analytics)
  shell: |
    update-alternatives --remove-all python
    update-alternatives --install /usr/bin/python python /usr/bin/python2 1

- name: Forward Syslog-NG logs to Log Analytics
  ansible.builtin.copy:
    src: static_files/syslog-ng-lad.conf
    dest: /etc/syslog-ng/conf.d/syslog-ng-lad.conf
    owner: root
    group: root
    mode: '0644'

...</pre>
]]></content:encoded>
					
					<wfw:commentRss>https://jmorano.moretrix.com/2022/04/using-ansible-to-finalize-hashicorp-packer-images/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
	</channel>
</rss>
