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.
執筆者紹介
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.
チャンネル別に見る
自動化
テクノロジー、チームおよび環境に関する IT 自動化の最新情報
AI (人工知能)
お客様が AI ワークロードをどこでも自由に実行することを可能にするプラットフォームについてのアップデート
オープン・ハイブリッドクラウド
ハイブリッドクラウドで柔軟に未来を築く方法をご確認ください。
セキュリティ
環境やテクノロジー全体に及ぶリスクを軽減する方法に関する最新情報
エッジコンピューティング
エッジでの運用を単純化するプラットフォームのアップデート
インフラストラクチャ
世界有数のエンタープライズ向け Linux プラットフォームの最新情報
アプリケーション
アプリケーションの最も困難な課題に対する Red Hat ソリューションの詳細
オリジナル番組
エンタープライズ向けテクノロジーのメーカーやリーダーによるストーリー
製品
ツール
試用、購入、販売
コミュニケーション
Red Hat について
エンタープライズ・オープンソース・ソリューションのプロバイダーとして世界をリードする Red Hat は、Linux、クラウド、コンテナ、Kubernetes などのテクノロジーを提供しています。Red Hat は強化されたソリューションを提供し、コアデータセンターからネットワークエッジまで、企業が複数のプラットフォームおよび環境間で容易に運用できるようにしています。
言語を選択してください
Red Hat legal and privacy links
- Red Hat について
- 採用情報
- イベント
- 各国のオフィス
- Red Hat へのお問い合わせ
- Red Hat ブログ
- ダイバーシティ、エクイティ、およびインクルージョン
- Cool Stuff Store
- Red Hat Summit