, , ,

Customize your Podman Machine with Ansible Playbooks

With the release of Podman 5.4, Podman Machine introduces a new option called --playbook for the podman machine init command. With --playbook, you can take advantage of Ansible Playbooks to customize your Podman Machines when they boot for the first time.

Virtual Machine customization prior to 5.4

Leading up to the release of Podman 5.4, there were limited ways for you to customize or modify the way your virtual machine looked when it booted for the first time. Based on user feedback, people wanted a simple way to automatically:

  • add files like certificates
  • create custom systemd services (that are not container based) 
  • edit configuration files

One way you could have done this was through the --image option. The --image option allows you to specify a bootable image for the Machine. You could build this image to include the certificates or configuration files you wanted to add to the Podman Machine. You could also use the --ignition-path option and write your own ignition file. By writing custom systemd units or services, you could further customize the Machine and get the expected behavior. These are great options, but image generation can be a difficult and time consuming task.  Moreover, changing the ignition file can be complex and can have a negative performance hit. 

We needed a customization solution that was both simple and performant. After various unsuccessful attempts to solve this problem for our users, we concluded that Ansible would “check the boxes.”  Its documentation has an excellent quote: “Ansible offers open-source automation that is simple, flexible, and powerful.”  It has its roots at Red Hat, but is mature and well known in open source communities.

Customization with Ansible Playbooks

Before diving into how to use Ansible Playbooks with Podman Machine, it might be helpful to recap what Ansible Playbooks are: “Ansible Playbooks offer a repeatable, reusable, simple configuration management and multi-machine deployment system”. In the case of Podman Machine, they provide an understandable method for configuring your virtual machines.

One scenario where this feature really shines is when you need to use a certificate to authenticate a registry. For this example, assume we have a registry at IP address 10.0.0.218 on port 5000, and the credentials are user:password. 

Lets start by initializing and starting a Podman Machine without a playbook to demonstrate the problem at hand:

$ podman machine init --now
...

Machine "podman-machine-default" started successfully

Now, try to pull an alpine image from the registry:

$ podman pull --creds=user:password 10.0.0.218:5000/alpine
Trying to pull 10.0.0.218:5000/alpine:latest...
Error: initializing source docker://10.0.0.218:5000/alpine:latest: pinging container registry 10.0.0.218:5000: Get "https://10.0.0.218:5000/v2/": tls: failed to verify certificate: x509: certificate signed by unknown authority

Here, Podman is trying to authenticate the registry, but it can’t because we don’t have the certificate inside the Podman Machine. It’s important to have the certificate inside the Machine, because that’s where Podman is going to be running the containers. 

With the addition of --playbook, this problem becomes very easy to solve! You can write the following playbook.yaml file to pull a certificate from a server and write it into the Machine:

# playbook.yaml
- name: Pull registry certificate
  hosts: localhost
  tasks:
	- name: Pull the registry's certificate
  	  ansible.builtin.uri:
    	    url: "http://internal.mycompany.org/get-cert"
    	    return_content: true
    	    method: GET
  	register: cert
       - name: Make the /etc/containers/certs.d/10.0.0.218:5000 directory
         become: true
         ansible.builtin.command: mkdir /etc/containers/certs.d/10.0.0.218:5000
	- name: Put the certificate in the desired location
         become: true
  	  ansible.builtin.copy:
    	  content: "{{ cert.content }}"
    	  dest: /etc/containers/certs.d/10.0.0.218:5000/ca.crt

Let’s remove the previous Podman Machine and create a new one, but this time you’re going to use the playbook you just wrote:

$ podman machine rm -f
... 
$ podman machine init --playbook playbook.yaml --now
...
Machine "podman-machine-default" started successfully

It’s important to note that Podman does not block the Machine from completing the boot sequence in order for the playbook to finish. Therefore, you may run into the scenario where the Machine finishes starting, but your playbook hasn’t completed. If you are using a provider that uses systemd (QEMU, AppleHV, Libkrun, or HyperV), you can check if playbook.service is still active:

$ podman machine ssh systemctl is-active playbook.service
inactive

If the output of the command is “inactive”, then your playbook has finished. 

Once the Machine has started and you have verified the playbook has completed, you can SSH into the Machine to verify the certificate has been copied to the desired location:

$ podman machine ssh ls /etc/containers/certs.d/10.0.0.218:5000/
ca.crt

Now that you have the certificate inside your Machine, let’s try and pull the alpine image from the registry:

$ podman pull --creds=user:password 10.0.0.218:5000/alpine
Trying to pull 10.0.0.218:5000/alpine:latest...
Getting image source signatures
Copying blob 210a2ae1a75e done   |
Copying config b0c9d60fc5 done   |
Writing manifest to image destination
b0c9d60fc5e3fa2319a86ccc1cdf34c94c7e69766e8cebfb4111f7e54f39e8ff

Success! This is just one example of how the new --playbook option provides an opportunity to customize your Podman Machine, but we’re looking forward to seeing all the creative ways you use it!

For more information on Ansible Playbooks, please see the official documentation.

Leave a Reply

Subscribe

Sign up with your email address to receive updates by email from this website.


Categories


Search