Red Hat Training

A Red Hat training course is available for RHEL 8

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

You can use the Podman System Role to create rootless containers with bind mount by running an Ansible playbook and with that, manage your application configuration.

Prerequisites

  • Access and permissions to a control node, which is a system from which Red Hat Ansible Engine configures other systems.
  • On the control node:

    • The rhel-system-roles package is installed.
    • An Ansible inventory file listing the hosts to be managed and any other parameters you want to apply.
Note

The ansible-playbook command is provided by the ansible-core package which should be automatically installed as a dependency of the rhel-system-roles package.

Procedure

  1. Create a new playbook.yml file with the following content:

    - hosts: all
      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/db/db:stable
                    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
      roles:
        - linux-system-roles.podman

    This procedure creates a pod with two containers. The podman_kube_specs role variable describes a pod.

    • The run_as_user and run_as_group fields specify that containers are rootless.
    • The kube_file_content field containing a Kubernetes YAML file defines the first container named db. You can generate the Kubernetes YAML file using the podman generate systemd command.

      • The db container is based on the quay.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. The Z flag labels the content with a private unshared label, therefore, only the db container can access the content.
    • The kube_file_src field defines the second container. The content of the /path/to/webapp.yml file on the controller node will be copied to the kube_file field on the managed node.
    • Set the podman_create_host_directories: true to create 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, use podman_host_directories.
  2. Optional: Verify playbook syntax.

    # ansible-playbook --syntax-check playbook.yml -i inventory_file
  3. Run the playbook on your inventory file:

    # ansible-playbook -i inventory_file playbook.yml

Additional resources

15.2. Creating a rootful container with Podman volume

You can use the Podman System Role to create a rootful container with a Podman volume by running an Ansible playbook and with that, manage your application configuration.

Prerequisites

  • Access and permissions to a control node, which is a system from which Red Hat Ansible Engine configures other systems.
  • On the control node:

    • The rhel-system-roles package is installed.
    • An Ansible inventory file listing the hosts to be managed and any other parameters you want to apply.
  • The ubi8-html-volume volume has been created.
Note

The ansible-playbook command is provided by the ansible-core package which should be automatically installed as a dependency of the rhel-system-roles package.

Procedure

  1. Create a new playbook.yml file with the following content:

    - hosts: all
      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
      roles:
        - linux-system-roles.podman

    The procedure creates a pod with one container. The podman_kube_specs role variable describes a pod.

    • By default, the Podman role creates rootful containers.
    • The kube_file_content field containing a Kubernetes YAML file defines the container named ubi8-httpd.

      • The ubi8-httpd container is based on the registry.access.redhat.com/ubi8/httpd-24 container image.

        • The ubi8-html-volume maps the /var/www/html directory on the host to the container. The Z flag labels the content with a private unshared label, therefore, only the ubi8-httpd container can access the content.
        • The pod mounts the existing persistent volume named ubi8-html-volume with the mount path /var/www/html.
  2. Optional: Verify playbook syntax.

    # ansible-playbook --syntax-check playbook.yml -i inventory_file
  3. Run the playbook on your inventory file:

    # ansible-playbook -i inventory_file playbook.yml

Additional resources

15.3. Creating a Quadlet application with secrets

You can use the Podman System Role to create a Quadlet application with secrets by running an Ansible playbook.

Note

The podman_quadlet_specs variable is available beginning with Podman v4.6.

Warning

Quadlets work only with rootful containers.

Prerequisites

  • Access and permissions to a control node, which is a system from which Red Hat Ansible Engine configures other systems.
  • On the control node:

    • The rhel-system-roles package is installed.
    • An Ansible inventory file listing the hosts to be managed and any other parameters you want to apply.
    • Secrets - you must define the following, preferably using Ansible Vault encrypted variables:
    • root password for MySQL ("root_password_from_vault")
    • TLS certificate and key ("cert_from_vault" and "key_from_vault")
Note
  • The ansible-playbook command is provided by the ansible-core package which should be automatically installed as a dependency of the rhel-system-roles package.
  • The files used by this example are provided by the rhel-system-roles package in /usr/share/ansible/roles/rhel-system-roles.podman/tests/files and /usr/share/ansible/roles/rhel-system-roles.podman/tests/templates directories.

Procedure

  1. Create a new playbook.yml file with the following content:

    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_from_vault }}"
      - name: mysql-root-password-kube
        state: present
        skip_existing: true
        data: |
          apiVersion: v1
          data:
            password: "{{ root_password_from_vault | b64encode }}"
          kind: Secret
          metadata:
            name: mysql-root-password-kube
      - name: envoy-certificates
        state: present
        skip_existing: true
        data: |
          apiVersion: v1
          data:
            certificate.key: {{ key_from_vault | b64encode }}
            certificate.pem: {{ cert_from_vault | 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 and file_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 as Yaml=quadlet-demo.yml and ConfigMap=envoy-proxy-configmap.yml.
  2. Optional: Verify playbook syntax.

    # ansible-playbook --syntax-check playbook.yml -i inventory_file
  3. Run the playbook on your inventory file:

    # ansible-playbook -i inventory_file playbook.yml

Additional resources