Two of the hottest topics in the Enable Sysadmin community are Podman and Ansible. It's no surprise as both bring compelling features and functionality for a variety of needs. With Podman, you have everything you need to manage your containers and pods, while Ansible offers everything you need to automate all the things. So what would be the product of the sum of the benefits of these two tools? Of course: automated and orchestrated management of your container and pod infrastructure!
Take, for instance, my article How to create multidomain web applications with Podman and Nginx. Although it's a relatively simple setup, imagine you need to replicate it in other environments or scale it to a large number of machines. Needless to say, doing all of that by hand is not practical at all, right? That's why automation is great for doing such things, and that's why I'll show how to use Ansible to automate Podman for container and pod deployments, using my previous article's environment as an example.
[ Download now: A system administrator's guide to IT automation. ]
Automate deploying prerequisites
Since I set out to automate everything, I'll automate creating the directories and files I previously created using this Ansible playbook (prereq.yaml
):
---
- name: "Playbook to create the prerequisites"
hosts: localhost
gather_facts: false
vars:
homedir: /home/localuser
hostip: 192.168.1.30
tasks:
- name: "Create the directories"
ansible.builtin.file:
path: "{{ homedir }}/{{ item }}"
state: directory
loop:
- syscom
- sysorg
- nginx
- name: "Create the httpd syscom file"
ansible.builtin.copy:
dest: "{{ homedir }}/syscom/index.html"
content: |
<html>
<header>
<title>SysAdmin.com</title>
</header>
<body>
<p>This is the SysAdmin website hosted on the .com domain</p>
</body>
</html>
- name: "Create the httpd sysorg file"
ansible.builtin.copy:
dest: "{{ homedir }}/sysorg/index.html"
content: |
<html>
<header>
<title>SysAdmin.org</title>
</header>
<body>
<p>This is the SysAdmin website hosted on the .org domain</p>
</body>
</html>
- name: "Create the Nginx syscom config"
ansible.builtin.copy:
dest: "{{ homedir }}/nginx/syscom.conf"
content: |
server {
listen 80;
server_name sysadmin.com;
location / {
proxy_pass http://{{ hostip }}:8080;
}
}
- name: "Create the Nginx sysorg config"
ansible.builtin.copy:
dest: "{{ homedir }}/nginx/sysorg.conf"
content: |
server {
listen 80;
server_name sysadmin.org;
location / {
proxy_pass http://{{ hostip }}:8081;
}
}
- name: "Create the Nginx default config"
ansible.builtin.copy:
dest: "{{ homedir }}/nginx/default.conf"
content: |
server {
listen 80;
listen [::]:80;
server_name localhost;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
}
[ Write your first playbook in this hands-on interactive lab. ]
Before running it, update variables homedir
and hostip
to match your environment. Then, run the playbook to create the directories and files:
$ ansible-playbook prereq.yaml
[WARNING]: provided hosts list is empty, only localhost is available. Note that the implicit localhost does not match 'all'
PLAY [Playbook to create the prerequisites] ***********************************
TASK [Create the directories] *************************************************
changed: [localhost] => (item=syscom)
changed: [localhost] => (item=sysorg)
changed: [localhost] => (item=nginx)
TASK [Create the httpd syscom file] *******************************************
changed: [localhost]
TASK [Create the httpd sysorg file] *******************************************
changed: [localhost]
TASK [Create the Nginx syscom config] *****************************************
changed: [localhost]
TASK [Create the Nginx sysorg config] *****************************************
changed: [localhost]
TASK [Create the Nginx default config] ****************************************
changed: [localhost]
PLAY RECAP ********************************************************************
localhost : ok=6 changed=6 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
$ ls -lR
.:
total 12
drwxr-xr-x. 2 localuser localuser 64 mar 2 13:13 nginx
-rw-r--r--. 1 localuser localuser 2541 mar 2 13:12 prereq.yaml
drwxr-xr-x. 2 localuser localuser 24 mar 2 13:13 syscom
drwxr-xr-x. 2 localuser localuser 24 mar 2 13:13 sysorg
./nginx:
total 12
-rw-r--r--. 1 localuser localuser 311 mar 2 13:13 default.conf
-rw-r--r--. 1 localuser localuser 116 mar 2 13:13 syscom.conf
-rw-r--r--. 1 localuser localuser 116 mar 2 13:13 sysorg.conf
./syscom:
total 4
-rw-r--r--. 1 localuser localuser 163 mar 2 13:13 index.html
./sysorg:
total 4
-rw-r--r--. 1 localuser localuser 163 mar 2 13:13 index.html
To proceed with the next steps, you'll need two distinct Ansible collections: ansible.posix to manipulate kernel parameters with sysctl
; and the collection containers.podman to automate Podman with Ansible. Install both collections:
$ for i in ansible.posix containers.podman; \
do ansible-galaxy collection install $i; \
done
Check the available modules for each of these collections:
$ ansible-doc -l | grep -e posix -e podman
ansible.posix.acl Set and retrieve ...
ansible.posix.at Schedule the exec...
ansible.posix.authorized_key Adds or removes a...
ansible.posix.firewalld Manage arbitrary ...
ansible.posix.firewalld_info Gather informatio...
ansible.posix.mount Control active an...
ansible.posix.patch Apply patch files...
ansible.posix.rhel_facts Facts module to s...
ansible.posix.rhel_rpm_ostree Ensure packages e...
ansible.posix.rpm_ostree_upgrade Manage rpm-ostree...
ansible.posix.seboolean Toggles SELinux b...
ansible.posix.selinux Change policy and...
ansible.posix.synchronize A wrapper around ...
ansible.posix.sysctl Manage entries in...
community.general.udm_user Manage posix user...
containers.podman.podman_container Manage podman con...
containers.podman.podman_container_info Gather facts abou...
containers.podman.podman_containers Manage podman con...
containers.podman.podman_export Export a podman c...
containers.podman.podman_generate_systemd Generate systemd ...
containers.podman.podman_image Pull images for u...
containers.podman.podman_image_info Gather info about...
containers.podman.podman_import Import Podman con...
containers.podman.podman_load Load image from a...
containers.podman.podman_login Login to a contai...
containers.podman.podman_login_info Return the logged...
containers.podman.podman_logout Log out of a cont...
containers.podman.podman_network Manage podman net...
containers.podman.podman_network_info Gather info about...
containers.podman.podman_play Play kubernetes Y...
containers.podman.podman_pod Manage Podman pod...
containers.podman.podman_pod_info Gather info about...
containers.podman.podman_save Saves podman imag...
containers.podman.podman_secret Manage podman sec...
containers.podman.podman_tag Add an additional...
containers.podman.podman_volume Manage Podman vol...
containers.podman.podman_volume_info Gather info about...
I won't detail what each of these modules do, as I'd need several articles for that. Instead, I'll focus on the containers.podman.podman_container
module for creating containers in an automated way.
Automate Podman with Ansible
To automate the creation of Podman containers using Ansible, create a playbook to deploy every single container with its proper parameters (as described in the previous article). Use the specific collections and respective modules for this. You'll also create another playbook to delete all containers when you don't need them anymore. Start with the playbook create_httpd_nginx.yaml
:
---
- name: "Playbook to create two httpd containers with one nginx container as a reverse proxy"
hosts: localhost
gather_facts: yes
vars:
homedir: /home/localuser
container_registry: docker.io/library
tasks:
- name: "Create the syscom container"
containers.podman.podman_container:
name: syscom
hostname: syscom
image: "{{ container_registry }}/httpd"
publish: 8080:80
volume:
- "{{ homedir }}/syscom:/usr/local/apache2/htdocs:Z"
state: started
- name: "Create the sysorg container"
containers.podman.podman_container:
name: sysorg
hostname: sysorg
image: "{{ container_registry }}/httpd"
publish: 8081:80
volume:
- "{{ homedir }}/sysorg:/usr/local/apache2/htdocs:Z"
state: started
- name: "Allow the nginx container to run in the 80 port of the host"
become: true
become_user: root
become_method: sudo
ansible.posix.sysctl:
name: net.ipv4.ip_unprivileged_port_start
value: "80"
sysctl_set: true
reload: true
- name: "Create the nginx container"
containers.podman.podman_container:
name: nginx
hostname: nginx
image: "{{ container_registry }}/nginx"
publish: 80:80
volume:
- "{{ homedir }}/nginx:/etc/nginx/conf.d:Z"
state: started
- name: "Disable the use of lower ports for containers again"
become: true
become_user: root
become_method: sudo
ansible.posix.sysctl:
name: net.ipv4.ip_unprivileged_port_start
value: "1024"
sysctl_set: true
reload: true
Then write a playbook called stop-remove_httpd_nginx.yaml
to stop and remove the containers:
---
- name: "Playbook to delete a container"
hosts: localhost
gather_facts: yes
tasks:
- name: "Stop and remove all containers"
containers.podman.podman_container:
name: "{{ item }}"
state: absent
loop:
- syscom
- sysorg
- nginx
Finally, test your playbooks by creating the containers and validating access to the applications. Use option -K
with the ansible-playbook
command to input the sudo
password, as this playbook changes the kernel setting to allow the Nginx container to bind to privileged port 80:
$ ansible-playbook create_httpd_nginx.yaml -K
[WARNING]: provided hosts list is empty, only localhost is available. Note that the implicit localhost does not match 'all'
PLAY [Playbook to create two httpd containers with one nginx container as a reverse proxy]
**********************************************************
TASK [Gathering Facts] ********************************************************
ok: [localhost]
TASK [Create the syscom container] ********************************************
changed: [localhost]
TASK [Create the sysorg container] ********************************************
changed: [localhost]
TASK [Allow the nginx container to run in the 80 port of the host] ************
changed: [localhost]
TASK [Create the nginx container] *********************************************
changed: [localhost]
TASK [Disable the use of lower ports for containers again] ********************
changed: [localhost]
PLAY RECAP ********************************************************************
localhost : ok=6 changed=5 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
$ podman ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
2038ad4e5c9e docker.io/library/httpd:latest httpd-foreground 7 seconds ago Up 6 seconds 0.0.0.0:8080->80/tcp syscom
5a01d9bdc5ae docker.io/library/httpd:latest httpd-foreground 5 seconds ago Up 4 seconds 0.0.0.0:8081->80/tcp sysorgp
3c816ebb9bcb docker.io/library/nginx:latest nginx -g daemon o... 3 seconds ago Up 2 seconds 0.0.0.0:80->80/tcp nginx
$ curl http://sysadmin.com
<html>
<header>
<title>SysAdmin.com</title>
</header>
<body>
<p>This is the SysAdmin website hosted on the .com domain</p>
</body>
</html>
$ curl http://sysadmin.org
<html>
<header>
<title>SysAdmin.org</title>
</header>
<body>
<p>This is the SysAdmin website hosted on the .org domain</p>
</body>
</html>
Nice and done. And to delete all of that, run the other playbook:
$ ansible-playbook stop-remove_httpd_nginx.yaml
[WARNING]: provided hosts list is empty, only localhost is available. Note that the implicit localhost does not match 'all'
PLAY [Playbook to create a container] *****************************************
TASK [Gathering Facts] ********************************************************
ok: [localhost]
TASK [Stop and remove all containers] *****************************************
changed: [localhost] => (item=syscom)
changed: [localhost] => (item=sysorg)
changed: [localhost] => (item=nginx)
PLAY RECAP ********************************************************************
localhost : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
$ podman ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
$ curl http://sysadmin.com
curl: (7) Failed to connect to sysadmin.com port 80 after 0 ms: Connection refused
$ curl http://sysadmin.org
curl: (7) Failed to connect to sysadmin.org port 80 after 0 ms: Connection refused
And just like that, you created and deleted the same environment as in my previous article, but faster, by leveraging the power of Ansible for Podman. Explore the other modules available in the containers.podman
collection to take advantage of the facilities it provides even more.
Wrap up
Podman and Ansible are very good tools individually for managing containers and automating all things respectively. They are even better together for enabling automation and orchestration of the container and pod lifecycles in simpler scenarios.
For more sophisticated scaling, orchestration, routing, balancing, and automation of many container-based applications and services, you can use a Kubernetes-based enterprise orchestration platform such as Red Hat OpenShift Container Platform.
À propos de l'auteur
Alexon has been working as a Senior Technical Account Manager at Red Hat since 2018, working in the Customer Success organization focusing on Infrastructure and Management, Integration and Automation, Cloud Computing, and Storage Solutions. He is a part of the TAM Practices LATAM team based in São Paulo, Brazil, where his job is partnering with, advocating, trust-advising, and supporting customers in their success goals while making use of the complete portfolio. He also contributes to produce and enhance documentation, knowledge-base articles, blog posts, presentations, webinars, and workshops. He is a member of numerous communities in addition to the Sudoers, like Red Hat Academy and Red Hat Accelerators. When he’s not at work, he enjoys spending quality time with his family (wife, daughter, and cat) and participating in several volunteer jobs.
Contenu similaire
Parcourir par canal
Automatisation
Les dernières nouveautés en matière d'automatisation informatique pour les technologies, les équipes et les environnements
Intelligence artificielle
Actualité sur les plateformes qui permettent aux clients d'exécuter des charges de travail d'IA sur tout type d'environnement
Cloud hybride ouvert
Découvrez comment créer un avenir flexible grâce au cloud hybride
Sécurité
Les dernières actualités sur la façon dont nous réduisons les risques dans tous les environnements et technologies
Edge computing
Actualité sur les plateformes qui simplifient les opérations en périphérie
Infrastructure
Les dernières nouveautés sur la plateforme Linux d'entreprise leader au monde
Applications
À l’intérieur de nos solutions aux défis d’application les plus difficiles
Programmes originaux
Histoires passionnantes de créateurs et de leaders de technologies d'entreprise
Produits
- Red Hat Enterprise Linux
- Red Hat OpenShift
- Red Hat Ansible Automation Platform
- Services cloud
- Voir tous les produits
Outils
- Formation et certification
- Mon compte
- Assistance client
- Ressources développeurs
- Rechercher un partenaire
- Red Hat Ecosystem Catalog
- Calculateur de valeur Red Hat
- Documentation
Essayer, acheter et vendre
Communication
- Contacter le service commercial
- Contactez notre service clientèle
- Contacter le service de formation
- Réseaux sociaux
À propos de Red Hat
Premier éditeur mondial de solutions Open Source pour les entreprises, nous fournissons des technologies Linux, cloud, de conteneurs et Kubernetes. Nous proposons des solutions stables qui aident les entreprises à jongler avec les divers environnements et plateformes, du cœur du datacenter à la périphérie du réseau.
Sélectionner une langue
Red Hat legal and privacy links
- À propos de Red Hat
- Carrières
- Événements
- Bureaux
- Contacter Red Hat
- Lire le blog Red Hat
- Diversité, équité et inclusion
- Cool Stuff Store
- Red Hat Summit