Chapter 15. Managing containers using the Ansible playbook
With Podman 4.2, you can use the Podman RHEL system role to manage Podman configuration, containers, and systemd services which run Podman containers.
RHEL system roles provide a configuration interface to remotely manage multiple RHEL systems. You can use the interface to manage system configurations across multiple versions of RHEL, as well as adopting new major releases. For more information, see the Automating system administration by using RHEL system roles.
15.1. Creating a rootless container with bind mount using the podman RHEL system role
You can use the podman
RHEL system role to create rootless containers with bind mount by running an Ansible playbook and with that, manage your application configuration.
The example Ansible playbook starts two Kubernetes pods: one for a database and another for a web application. The database pod configuration is specified in the playbook, while the web application pod is defined in an external YAML file.
Prerequisites
- You have prepared the control node and the managed nodes
- You are logged in to the control node as a user who can run playbooks on the managed nodes.
-
The account you use to connect to the managed nodes has
sudo
permissions on them. -
The user and group
webapp
exist, and must be listed in the/etc/subuid
and/etc/subgid
files on the host.
Procedure
Create a playbook file, for example
~/playbook.yml
, with the following content:- name: Configure Podman hosts: managed-node-01.example.com tasks: - name: Create a web application and a database ansible.builtin.include_role: name: rhel-system-roles.podman vars: podman_create_host_directories: true podman_firewall: - port: 8080-8081/tcp state: enabled - port: 12340/tcp state: enabled podman_selinux_ports: - ports: 8080-8081 setype: http_port_t podman_kube_specs: - state: started run_as_user: dbuser run_as_group: dbgroup kube_file_content: apiVersion: v1 kind: Pod metadata: name: db spec: containers: - name: db image: quay.io/linux-system-roles/mysql:5.6 ports: - containerPort: 1234 hostPort: 12340 volumeMounts: - mountPath: /var/lib/db:Z name: db volumes: - name: db hostPath: path: /var/lib/db - state: started run_as_user: webapp run_as_group: webapp kube_file_src: /path/to/webapp.yml
The settings specified in the example playbook include the following:
run_as_user
andrun_as_group
- Specify that containers are rootless.
kube_file_content
Contains a Kubernetes YAML file defining the first container named
db
. You can generate the Kubernetes YAML file using thepodman kube generate
command.-
The
db
container is based on thequay.io/db/db:stable
container image. -
The
db
bind mount maps the/var/lib/db
directory on the host to the/var/lib/db
directory in the container. TheZ
flag labels the content with a private unshared label, therefore, only thedb
container can access the content.
-
The
kube_file_src: <path>
-
Defines the second container. The content of the
/path/to/webapp.yml
file on the controller node will be copied to thekube_file
field on the managed node. volumes: <list>
-
A YAML list to define the source of the data to provide in one or more containers. For example, a local disk on the host (
hostPath
) or other disk device. volumeMounts: <list>
- A YAML list to define the destination where the individual container will mount a given volume.
podman_create_host_directories: true
-
Creates the directory on the host. This instructs the role to check the kube specification for
hostPath
volumes and create those directories on the host. If you need more control over the ownership and permissions, usepodman_host_directories
.
For details about all variables used in the playbook, see the
/usr/share/ansible/roles/rhel-system-roles.podman/README.md
file on the control node.Validate the playbook syntax:
$ ansible-playbook --syntax-check --ask-vault-pass ~/playbook.yml
Note that this command only validates the syntax and does not protect against a wrong but valid configuration.
Run the playbook:
$ ansible-playbook --ask-vault-pass ~/playbook.yml
Additional resources
-
/usr/share/ansible/roles/rhel-system-roles.podman/README.md
file -
/usr/share/doc/rhel-system-roles/podman/
directory
15.2. Creating a rootful container with Podman volume using the podman RHEL system role
You can use the podman
RHEL system role to create a rootful container with a Podman volume by running an Ansible playbook and with that, manage your application configuration.
The example Ansible playbook deploys a Kubernetes pod named ubi8-httpd
running an HTTP server container from the registry.access.redhat.com/ubi8/httpd-24
image. The container’s web content is mounted from a persistent volume named ubi8-html-volume
. By default, the podman
role creates rootful containers.
Prerequisites
- You have prepared the control node and the managed nodes
- You are logged in to the control node as a user who can run playbooks on the managed nodes.
-
The account you use to connect to the managed nodes has
sudo
permissions on them.
Procedure
Create a playbook file, for example
~/playbook.yml
, with the following content:- name: Configure Podman hosts: managed-node-01.example.com tasks: - name: Start Apache server on port 8080 ansible.builtin.include_role: name: rhel-system-roles.podman vars: podman_firewall: - port: 8080/tcp state: enabled podman_kube_specs: - state: started kube_file_content: apiVersion: v1 kind: Pod metadata: name: ubi8-httpd spec: containers: - name: ubi8-httpd image: registry.access.redhat.com/ubi8/httpd-24 ports: - containerPort: 8080 hostPort: 8080 volumeMounts: - mountPath: /var/www/html:Z name: ubi8-html volumes: - name: ubi8-html persistentVolumeClaim: claimName: ubi8-html-volume
The settings specified in the example playbook include the following:
kube_file_content
Contains a Kubernetes YAML file defining the first container named
db
. You can generate the Kubernetes YAML file using thepodman kube generate
command.-
The
ubi8-httpd
container is based on theregistry.access.redhat.com/ubi8/httpd-24
container image. -
The
ubi8-html-volume
maps the/var/www/html
directory on the host to the container. TheZ
flag labels the content with a private unshared label, therefore, only theubi8-httpd
container can access the content. -
The pod mounts the existing persistent volume named
ubi8-html-volume
with the mount path/var/www/html
.
-
The
For details about all variables used in the playbook, see the
/usr/share/ansible/roles/rhel-system-roles.podman/README.md
file on the control node.Validate the playbook syntax:
$ ansible-playbook --syntax-check ~/playbook.yml
Note that this command only validates the syntax and does not protect against a wrong but valid configuration.
Run the playbook:
$ ansible-playbook ~/playbook.yml
Additional resources
-
/usr/share/ansible/roles/rhel-system-roles.podman/README.md
file -
/usr/share/doc/rhel-system-roles/podman/
directory
15.3. Creating a Quadlet application with secrets using the podman RHEL system role
You can use the podman
RHEL system role to create a Quadlet application with secrets by running an Ansible playbook.
Prerequisites
- You have prepared the control node and the managed nodes
- You are logged in to the control node as a user who can run playbooks on the managed nodes.
-
The account you use to connect to the managed nodes has
sudo
permissions on them. -
The certificate and the corresponding private key that the web server in the container should use are stored in the
~/certificate.pem
and~/key.pem
files.
Procedure
Display the contents of the certificate and private key files:
$ cat ~/certificate.pem -----BEGIN CERTIFICATE----- ... -----END CERTIFICATE----- $ cat ~/key.pem -----BEGIN PRIVATE KEY----- ... -----END PRIVATE KEY-----
You require this information in a later step.
Store your sensitive variables in an encrypted file:
Create the vault:
$ ansible-vault create vault.yml New Vault password: <vault_password> Confirm New Vault password: <vault_password>
After the
ansible-vault create
command opens an editor, enter the sensitive data in the<key>: <value>
format:root_password: <root_password> certificate: |- -----BEGIN CERTIFICATE----- ... -----END CERTIFICATE----- key: |- -----BEGIN PRIVATE KEY----- ... -----END PRIVATE KEY-----
Ensure that all lines in the
certificate
andkey
variables start with two spaces.- Save the changes, and close the editor. Ansible encrypts the data in the vault.
Create a playbook file, for example
~/playbook.yml
, with the following content:- name: Deploy a wordpress CMS with MySQL database hosts: managed-node-01.example.com vars_files: - vault.yml tasks: - name: Create and run the container ansible.builtin.include_role: name: rhel-system-roles.podman vars: podman_create_host_directories: true podman_activate_systemd_unit: false podman_quadlet_specs: - name: quadlet-demo type: network file_content: | [Network] Subnet=192.168.30.0/24 Gateway=192.168.30.1 Label=app=wordpress - file_src: quadlet-demo-mysql.volume - template_src: quadlet-demo-mysql.container.j2 - file_src: envoy-proxy-configmap.yml - file_src: quadlet-demo.yml - file_src: quadlet-demo.kube activate_systemd_unit: true podman_firewall: - port: 8000/tcp state: enabled - port: 9000/tcp state: enabled podman_secrets: - name: mysql-root-password-container state: present skip_existing: true data: "{{ root_password }}" - name: mysql-root-password-kube state: present skip_existing: true data: | apiVersion: v1 data: password: "{{ root_password | b64encode }}" kind: Secret metadata: name: mysql-root-password-kube - name: envoy-certificates state: present skip_existing: true data: | apiVersion: v1 data: certificate.key: {{ key | b64encode }} certificate.pem: {{ certificate | b64encode }} kind: Secret metadata: name: envoy-certificates
The procedure creates a WordPress content management system paired with a MySQL database. The
podman_quadlet_specs role
variable defines a set of configurations for the Quadlet, which refers to a group of containers or services that work together in a certain way. It includes the following specifications:-
The Wordpress network is defined by the
quadlet-demo
network unit. -
The volume configuration for MySQL container is defined by the
file_src: quadlet-demo-mysql.volume
field. -
The
template_src: quadlet-demo-mysql.container.j2
field is used to generate a configuration for the MySQL container. -
Two YAML files follow:
file_src: envoy-proxy-configmap.yml
andfile_src: quadlet-demo.yml
. Note that .yml is not a valid Quadlet unit type, therefore these files will just be copied and not processed as a Quadlet specification. -
The Wordpress and envoy proxy containers and configuration are defined by the
file_src: quadlet-demo.kube
field. The kube unit refers to the previous YAML files in the[Kube]
section asYaml=quadlet-demo.yml
andConfigMap=envoy-proxy-configmap.yml
.
-
The Wordpress network is defined by the
Validate the playbook syntax:
$ ansible-playbook --syntax-check --ask-vault-pass ~/playbook.yml
Note that this command only validates the syntax and does not protect against a wrong but valid configuration.
Run the playbook:
$ ansible-playbook --ask-vault-pass ~/playbook.yml
Additional resources
-
/usr/share/ansible/roles/rhel-system-roles.podman/README.md
file -
/usr/share/doc/rhel-system-roles/podman/
directory