Search

Chapter 15. Managing containers using the Ansible playbook

download PDF

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 RHEL system role to create rootless containers with bind mount by running an Ansible playbook and with that, manage your application configuration.

Prerequisites

Procedure

  1. Create a playbook file, for example ~/playbook.yml, with the following content:

    - hosts: managed-node-01.example.com
      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.podma

    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 kube generate 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. 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.

  3. 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

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.

Prerequisites

Procedure

  1. Create a playbook file, for example ~/playbook.yml, with the following content:

    - hosts: managed-node-01.example.com
      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. 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.

  3. 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

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

  1. 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.

  2. Store your sensitive variables in an encrypted file:

    1. Create the vault:

      $ ansible-vault create vault.yml
      New Vault password: <vault_password>
      Confirm New Vault password: <vault_password>
    2. 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 and key variables start with two spaces.

    3. Save the changes, and close the editor. Ansible encrypts the data in the vault.
  3. 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 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.
  4. 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.

  5. 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
Red Hat logoGithubRedditYoutubeTwitter

Learn

Try, buy, & sell

Communities

About Red Hat Documentation

We help Red Hat users innovate and achieve their goals with our products and services with content they can trust.

Making open source more inclusive

Red Hat is committed to replacing problematic language in our code, documentation, and web properties. For more details, see the Red Hat Blog.

About Red Hat

We deliver hardened solutions that make it easier for enterprises to work across platforms and environments, from the core datacenter to the network edge.

© 2024 Red Hat, Inc.