mirror of
https://github.com/containers/ansible-podman-collections.git
synced 2026-02-04 07:11:49 +00:00
* Rewrite podman and buildah connections --------- Signed-off-by: Sagi Shnaidman <sshnaidm@redhat.com>
1063 lines
29 KiB
Markdown
1063 lines
29 KiB
Markdown
# Podman and Buildah Connection Plugins
|
|
|
|
This document provides comprehensive information about the Podman and Buildah connection plugins included in the `containers.podman` Ansible collection.
|
|
|
|
## Table of Contents
|
|
|
|
1. [Overview](#overview)
|
|
2. [Installation and Setup](#installation-and-setup)
|
|
3. [Podman Connection Plugin](#podman-connection-plugin)
|
|
4. [Buildah Connection Plugin](#buildah-connection-plugin)
|
|
5. [Configuration Options](#configuration-options)
|
|
6. [Simple Usage Examples](#simple-usage-examples)
|
|
7. [Advanced Usage Examples](#advanced-usage-examples)
|
|
8. [Performance and Best Practices](#performance-and-best-practices)
|
|
9. [Troubleshooting](#troubleshooting)
|
|
10. [Migration from Legacy Plugins](#migration-from-legacy-plugins)
|
|
|
|
## Overview
|
|
|
|
The connection plugins enable Ansible to execute tasks directly inside Podman containers and Buildah working containers. These plugins provide a seamless way to manage containerized environments using standard Ansible playbooks and tasks.
|
|
|
|
### Key Features
|
|
|
|
- **Direct container execution**: Run Ansible tasks inside containers without SSH
|
|
- **Fail-fast error handling**: No implicit retries; commands return rc/stdout/stderr to Ansible
|
|
- **Performance optimization**: Connection caching and mount detection for efficient file operations
|
|
- **Environment management**: Inject environment variables and configure container runtime
|
|
- **Unicode and special character support**: Handle complex file paths and command arguments
|
|
- **Privilege escalation**: Support for sudo and other privilege escalation methods
|
|
- **Timeout configuration**: Optional command timeout (default 0 = no timeout)
|
|
|
|
### Use Cases
|
|
|
|
- **Application deployment**: Deploy applications directly into containers
|
|
- **Container configuration**: Configure running containers with Ansible tasks
|
|
- **Multi-container orchestration**: Manage complex containerized applications
|
|
- **Development environments**: Set up and configure development containers
|
|
- **Testing and CI/CD**: Run tests and build processes inside containers
|
|
- **Container image customization**: Modify and configure container images using Buildah
|
|
|
|
## Installation and Setup
|
|
|
|
### Prerequisites
|
|
|
|
- Ansible 2.9 or later
|
|
- Podman 3.0+ (for Podman connection plugin)
|
|
- Buildah 1.20+ (for Buildah connection plugin)
|
|
- Python 3.6+ on the Ansible control node
|
|
|
|
### Installation
|
|
|
|
```bash
|
|
# Install from Ansible Galaxy
|
|
ansible-galaxy collection install containers.podman
|
|
|
|
# Or install from source
|
|
git clone https://github.com/containers/ansible-podman-collections.git
|
|
cd ansible-podman-collections
|
|
ansible-galaxy collection build
|
|
ansible-galaxy collection install containers-podman-*.tar.gz
|
|
```
|
|
|
|
## Podman Connection Plugin
|
|
|
|
The Podman connection plugin (`containers.podman.podman`) allows Ansible to execute tasks inside running Podman containers.
|
|
|
|
### Podman Connection Plugin Features
|
|
|
|
- **Container lifecycle management**: Automatically detect and connect to running containers
|
|
- **Mount point detection**: Optimize file transfers by detecting shared mounts
|
|
- **Environment variable injection**: Pass environment variables from inventory to container
|
|
- **Connection caching**: Cache container information for improved performance
|
|
- **Multiple execution modes**: Support for different container runtime configurations
|
|
|
|
### Podman Connection Plugin Basic Configuration
|
|
|
|
```yaml
|
|
# inventory.yml
|
|
[containers]
|
|
my-container
|
|
|
|
[containers:vars]
|
|
ansible_connection=containers.podman.podman
|
|
ansible_host=my-container-name
|
|
```
|
|
|
|
## Buildah Connection Plugin
|
|
|
|
The Buildah connection plugin (`containers.podman.buildah`) enables Ansible to execute tasks inside Buildah working containers, perfect for container image building and customization.
|
|
|
|
### Buildah Connection Plugin Features
|
|
|
|
- **Working container management**: Execute tasks in Buildah working containers
|
|
- **Auto-commit functionality**: Optionally commit changes after task execution
|
|
- **Working directory support**: Set and manage working directories
|
|
- **Layer optimization**: Efficient layer creation during image building
|
|
- **Build context management**: Handle build contexts and file transfers
|
|
|
|
### Buildah Connection Plugin Basic Configuration
|
|
|
|
```yaml
|
|
# inventory.yml
|
|
[buildah_containers]
|
|
build-container
|
|
|
|
[buildah_containers:vars]
|
|
ansible_connection=containers.podman.buildah
|
|
ansible_host=build-container-name
|
|
```
|
|
|
|
## Configuration Options
|
|
|
|
### Podman Connection Plugin Options
|
|
|
|
| Option | Type | Default | Description |
|
|
|--------|------|---------|-------------|
|
|
| `ansible_podman_executable` | string | `podman` | Path to podman executable |
|
|
| `ansible_podman_timeout` | int | `0` | Command execution timeout in seconds (0 = no timeout) |
|
|
| `ansible_podman_extra_env` | dict | `{}` | Additional environment variables to inject |
|
|
| `ansible_podman_mount_detection` | bool | `true` | Enable mount point detection for file operations |
|
|
| `ansible_podman_ignore_mount_errors` | bool | `true` | Continue without mount if detection fails |
|
|
|
|
### Buildah Connection Plugin Options
|
|
|
|
| Option | Type | Default | Description |
|
|
|--------|------|---------|-------------|
|
|
| `ansible_buildah_executable` | string | `buildah` | Path to buildah executable |
|
|
| `ansible_buildah_timeout` | int | `0` | Command execution timeout in seconds (0 = no timeout) |
|
|
| `ansible_buildah_extra_env` | dict | `{}` | Additional environment variables to inject |
|
|
| `ansible_buildah_mount_detection` | bool | `true` | Enable mount point detection for file operations |
|
|
| `ansible_buildah_ignore_mount_errors` | bool | `true` | Continue without mount if detection fails |
|
|
| `ansible_buildah_auto_commit` | bool | `false` | Automatically commit changes after tasks |
|
|
| `ansible_buildah_working_directory` | string | | Working directory for command execution |
|
|
|
|
## Simple Usage Examples
|
|
|
|
Note: Modules like `package`, `file`, and `copy` require Python inside the target container. For minimal images without Python, prefer `raw`/`command` tasks or delegate host-side operations (for example, `podman cp`). Examples below assume Python is available unless stated otherwise.
|
|
### Example 1: Basic Container Management
|
|
|
|
```yaml
|
|
---
|
|
- name: Configure web server in container
|
|
hosts: webserver_container
|
|
vars:
|
|
ansible_connection: containers.podman.podman
|
|
ansible_host: nginx-container
|
|
|
|
tasks:
|
|
- name: Install additional packages
|
|
package:
|
|
name: curl
|
|
state: present
|
|
|
|
- name: Create configuration directory
|
|
file:
|
|
path: /etc/nginx/conf.d
|
|
state: directory
|
|
mode: '0755'
|
|
|
|
- name: Copy nginx configuration
|
|
copy:
|
|
src: nginx.conf
|
|
dest: /etc/nginx/conf.d/default.conf
|
|
mode: '0644'
|
|
notify: restart nginx
|
|
|
|
handlers:
|
|
- name: restart nginx
|
|
service:
|
|
name: nginx
|
|
state: restarted
|
|
```
|
|
|
|
### Example 2: Multi-Container Application
|
|
|
|
```yaml
|
|
---
|
|
- name: Deploy multi-tier application
|
|
hosts: localhost
|
|
gather_facts: false
|
|
|
|
tasks:
|
|
- name: Start database container
|
|
containers.podman.podman_container:
|
|
name: app-database
|
|
image: postgres:13
|
|
state: started
|
|
env:
|
|
POSTGRES_DB: myapp
|
|
POSTGRES_USER: appuser
|
|
POSTGRES_PASSWORD: secret
|
|
ports:
|
|
- "5432:5432"
|
|
|
|
- name: Start application container
|
|
containers.podman.podman_container:
|
|
name: app-server
|
|
image: python:3.9
|
|
state: started
|
|
command: sleep infinity
|
|
ports:
|
|
- "8080:8080"
|
|
|
|
- name: Configure database
|
|
hosts: app-database
|
|
vars:
|
|
ansible_connection: containers.podman.podman
|
|
ansible_host: app-database
|
|
|
|
tasks:
|
|
- name: Create application database
|
|
postgresql_db:
|
|
name: myapp
|
|
state: present
|
|
|
|
- name: Configure application
|
|
hosts: app-server
|
|
vars:
|
|
ansible_connection: containers.podman.podman
|
|
ansible_host: app-server
|
|
|
|
tasks:
|
|
- name: Install application dependencies
|
|
pip:
|
|
requirements: /app/requirements.txt
|
|
|
|
- name: Start application service
|
|
shell: |
|
|
cd /app
|
|
python app.py
|
|
async: 3600
|
|
poll: 0
|
|
```
|
|
|
|
### Example 3: Simple Image Building with Buildah
|
|
|
|
```yaml
|
|
---
|
|
- name: Build custom image with Buildah
|
|
hosts: localhost
|
|
gather_facts: false
|
|
|
|
tasks:
|
|
- name: Create working container
|
|
shell: buildah from --name custom-build alpine:latest
|
|
|
|
- name: Configure the image
|
|
hosts: custom-build
|
|
vars:
|
|
ansible_connection: containers.podman.buildah
|
|
ansible_host: custom-build
|
|
ansible_buildah_auto_commit: true
|
|
|
|
tasks:
|
|
- name: Update package index
|
|
apk:
|
|
update_cache: true
|
|
|
|
- name: Install required packages
|
|
apk:
|
|
name:
|
|
- python3
|
|
- py3-pip
|
|
- curl
|
|
state: present
|
|
|
|
- name: Create application user
|
|
user:
|
|
name: appuser
|
|
shell: /bin/sh
|
|
home: /app
|
|
create_home: true
|
|
|
|
- name: Set working directory
|
|
file:
|
|
path: /app
|
|
state: directory
|
|
owner: appuser
|
|
group: appuser
|
|
|
|
- name: Commit custom image with Buildah
|
|
hosts: localhost
|
|
gather_facts: false
|
|
|
|
tasks:
|
|
- name: Commit the image
|
|
shell: buildah commit custom-build custom-alpine:latest
|
|
|
|
- name: Clean up working container
|
|
shell: buildah rm custom-build
|
|
```
|
|
|
|
## Advanced Usage Examples
|
|
|
|
### Example 1: High-Performance Web Application Deployment
|
|
|
|
```yaml
|
|
---
|
|
- name: Deploy high-performance web application
|
|
hosts: localhost
|
|
gather_facts: false
|
|
vars:
|
|
app_replicas: 3
|
|
load_balancer_image: "nginx:alpine"
|
|
app_image: "python:3.9-slim"
|
|
|
|
tasks:
|
|
- name: Create application network
|
|
containers.podman.podman_network:
|
|
name: app-network
|
|
state: present
|
|
|
|
- name: Start application containers
|
|
containers.podman.podman_container:
|
|
name: "app-{{ item }}"
|
|
image: "{{ app_image }}"
|
|
state: started
|
|
command: sleep infinity
|
|
networks:
|
|
- name: app-network
|
|
env:
|
|
FLASK_ENV: production
|
|
WORKERS: "4"
|
|
PORT: "5000"
|
|
healthcheck:
|
|
test: ["CMD", "curl", "-f", "http://localhost:5000/health"]
|
|
interval: 30s
|
|
timeout: 10s
|
|
retries: 3
|
|
loop: "{{ range(1, app_replicas + 1) | list }}"
|
|
|
|
- name: Start load balancer
|
|
containers.podman.podman_container:
|
|
name: load-balancer
|
|
image: "{{ load_balancer_image }}"
|
|
state: started
|
|
ports:
|
|
- "80:80"
|
|
- "443:443"
|
|
networks:
|
|
- name: app-network
|
|
volumes:
|
|
- nginx-config:/etc/nginx/conf.d:ro
|
|
- ssl-certs:/etc/ssl/certs:ro
|
|
|
|
- name: Configure application containers
|
|
hosts: app_containers
|
|
vars:
|
|
ansible_connection: containers.podman.podman
|
|
ansible_podman_extra_env:
|
|
PYTHONPATH: "/app"
|
|
LOG_LEVEL: "INFO"
|
|
ansible_podman_timeout: 60
|
|
|
|
tasks:
|
|
- name: Install system dependencies
|
|
apt:
|
|
name:
|
|
- build-essential
|
|
- python3-dev
|
|
- libpq-dev
|
|
state: present
|
|
update_cache: true
|
|
|
|
- name: Create application directory structure
|
|
file:
|
|
path: "{{ item }}"
|
|
state: directory
|
|
mode: '0755'
|
|
loop:
|
|
- /app
|
|
- /app/logs
|
|
- /app/static
|
|
- /app/templates
|
|
|
|
- name: Copy application code
|
|
copy:
|
|
src: "{{ item.src }}"
|
|
dest: "{{ item.dest }}"
|
|
mode: "{{ item.mode | default('0644') }}"
|
|
loop:
|
|
- { src: "app.py", dest: "/app/app.py", mode: "0755" }
|
|
- { src: "requirements.txt", dest: "/app/requirements.txt" }
|
|
- { src: "config.py", dest: "/app/config.py" }
|
|
- { src: "wsgi.py", dest: "/app/wsgi.py" }
|
|
notify: restart application
|
|
|
|
- name: Install Python dependencies
|
|
pip:
|
|
requirements: /app/requirements.txt
|
|
virtualenv: /app/venv
|
|
virtualenv_python: python3
|
|
|
|
- name: Configure application settings
|
|
template:
|
|
src: app_config.j2
|
|
dest: /app/.env
|
|
mode: '0600'
|
|
notify: restart application
|
|
|
|
- name: Set up log rotation
|
|
copy:
|
|
content: |
|
|
/app/logs/*.log {
|
|
daily
|
|
missingok
|
|
rotate 30
|
|
compress
|
|
delaycompress
|
|
notifempty
|
|
copytruncate
|
|
}
|
|
dest: /etc/logrotate.d/app
|
|
mode: '0644'
|
|
|
|
- name: Start application with gunicorn
|
|
shell: |
|
|
cd /app
|
|
source venv/bin/activate
|
|
gunicorn --bind 0.0.0.0:5000 --workers 4 wsgi:app
|
|
async: 3600
|
|
poll: 0
|
|
register: app_service
|
|
|
|
handlers:
|
|
- name: restart application
|
|
shell: pkill -f gunicorn || true
|
|
|
|
- name: Configure load balancer
|
|
hosts: load-balancer
|
|
vars:
|
|
ansible_connection: containers.podman.podman
|
|
ansible_podman_timeout: 30
|
|
|
|
tasks:
|
|
- name: Generate nginx upstream configuration
|
|
template:
|
|
src: nginx_upstream.conf.j2
|
|
dest: /etc/nginx/conf.d/upstream.conf
|
|
mode: '0644'
|
|
notify: reload nginx
|
|
|
|
- name: Configure SSL certificates
|
|
copy:
|
|
src: "{{ item.src }}"
|
|
dest: "{{ item.dest }}"
|
|
mode: '0600'
|
|
loop:
|
|
- { src: "ssl/app.crt", dest: "/etc/ssl/certs/app.crt" }
|
|
- { src: "ssl/app.key", dest: "/etc/ssl/private/app.key" }
|
|
notify: reload nginx
|
|
|
|
- name: Configure nginx main site
|
|
template:
|
|
src: nginx_site.conf.j2
|
|
dest: /etc/nginx/conf.d/default.conf
|
|
mode: '0644'
|
|
notify: reload nginx
|
|
|
|
handlers:
|
|
- name: reload nginx
|
|
service:
|
|
name: nginx
|
|
state: reloaded
|
|
```
|
|
|
|
### Example 2: Advanced Image Building Pipeline
|
|
|
|
```yaml
|
|
---
|
|
- name: Advanced container image building pipeline
|
|
hosts: localhost
|
|
gather_facts: false
|
|
vars:
|
|
base_image: "alpine:3.18"
|
|
build_args:
|
|
VERSION: "1.0.0"
|
|
BUILD_DATE: "{{ ansible_date_time.iso8601 }}"
|
|
COMMIT_SHA: "{{ lookup('env', 'GITHUB_SHA') | default('local') }}"
|
|
|
|
tasks:
|
|
- name: Create build context directory
|
|
file:
|
|
path: "{{ item }}"
|
|
state: directory
|
|
mode: '0755'
|
|
loop:
|
|
- /tmp/build-context
|
|
- /tmp/build-context/src
|
|
- /tmp/build-context/config
|
|
- /tmp/build-context/scripts
|
|
|
|
- name: Copy build files
|
|
copy:
|
|
src: "{{ item.src }}"
|
|
dest: "{{ item.dest }}"
|
|
mode: "{{ item.mode | default('0644') }}"
|
|
loop:
|
|
- { src: "src/", dest: "/tmp/build-context/src/", mode: "0755" }
|
|
- { src: "config/", dest: "/tmp/build-context/config/" }
|
|
- { src: "scripts/", dest: "/tmp/build-context/scripts/", mode: "0755" }
|
|
- { src: "requirements.txt", dest: "/tmp/build-context/" }
|
|
- { src: "Dockerfile", dest: "/tmp/build-context/" }
|
|
|
|
- name: Create multi-stage build containers
|
|
shell: |
|
|
buildah from --name build-stage {{ base_image }}
|
|
buildah from --name runtime-stage {{ base_image }}
|
|
register: build_containers
|
|
|
|
- name: Mount build context
|
|
shell: |
|
|
buildah copy build-stage /tmp/build-context /build
|
|
buildah config --workingdir /build build-stage
|
|
|
|
- name: Configure build stage
|
|
hosts: build-stage
|
|
vars:
|
|
ansible_connection: containers.podman.buildah
|
|
ansible_host: build-stage
|
|
ansible_buildah_working_dir: /build
|
|
ansible_buildah_extra_env:
|
|
BUILD_MODE: "production"
|
|
PYTHONPATH: "/build/src"
|
|
ansible_buildah_timeout: 300
|
|
|
|
tasks:
|
|
- name: Install build dependencies
|
|
apk:
|
|
name:
|
|
- python3
|
|
- py3-pip
|
|
- python3-dev
|
|
- gcc
|
|
- musl-dev
|
|
- libffi-dev
|
|
- openssl-dev
|
|
- make
|
|
- git
|
|
state: present
|
|
update_cache: true
|
|
|
|
- name: Create virtual environment
|
|
shell: python3 -m venv /build/venv
|
|
|
|
- name: Upgrade pip and install build tools
|
|
pip:
|
|
name:
|
|
- pip
|
|
- wheel
|
|
- setuptools
|
|
state: latest
|
|
virtualenv: /build/venv
|
|
|
|
- name: Install Python dependencies
|
|
pip:
|
|
requirements: /build/requirements.txt
|
|
virtualenv: /build/venv
|
|
|
|
- name: Compile application
|
|
shell: |
|
|
source /build/venv/bin/activate
|
|
python setup.py build_ext --inplace
|
|
python -m compileall src/
|
|
args:
|
|
chdir: /build
|
|
|
|
- name: Run tests
|
|
shell: |
|
|
source /build/venv/bin/activate
|
|
python -m pytest tests/ -v
|
|
args:
|
|
chdir: /build
|
|
|
|
- name: Create distribution package
|
|
shell: |
|
|
source /build/venv/bin/activate
|
|
python setup.py sdist bdist_wheel
|
|
args:
|
|
chdir: /build
|
|
|
|
- name: Prepare runtime artifacts
|
|
shell: |
|
|
mkdir -p /build/runtime-artifacts
|
|
cp -r src/ /build/runtime-artifacts/
|
|
cp -r venv/ /build/runtime-artifacts/
|
|
cp requirements.txt /build/runtime-artifacts/
|
|
cp scripts/entrypoint.sh /build/runtime-artifacts/
|
|
args:
|
|
chdir: /build
|
|
|
|
- name: Configure runtime stage
|
|
hosts: runtime-stage
|
|
vars:
|
|
ansible_connection: containers.podman.buildah
|
|
ansible_host: runtime-stage
|
|
ansible_buildah_working_dir: /app
|
|
ansible_buildah_extra_env:
|
|
PYTHONPATH: "/app/src"
|
|
FLASK_ENV: "production"
|
|
ansible_buildah_auto_commit: false
|
|
|
|
tasks:
|
|
- name: Install runtime dependencies only
|
|
apk:
|
|
name:
|
|
- python3
|
|
- py3-pip
|
|
- curl
|
|
- ca-certificates
|
|
state: present
|
|
update_cache: true
|
|
|
|
- name: Create application user
|
|
user:
|
|
name: appuser
|
|
shell: /bin/sh
|
|
home: /app
|
|
create_home: true
|
|
system: true
|
|
|
|
- name: Create application directories
|
|
file:
|
|
path: "{{ item }}"
|
|
state: directory
|
|
owner: appuser
|
|
group: appuser
|
|
mode: '0755'
|
|
loop:
|
|
- /app
|
|
- /app/logs
|
|
- /app/data
|
|
- /app/tmp
|
|
|
|
- name: Copy runtime artifacts from build stage
|
|
shell: |
|
|
buildah copy --from build-stage runtime-stage /build/runtime-artifacts /app
|
|
|
|
- name: Set proper ownership
|
|
file:
|
|
path: /app
|
|
owner: appuser
|
|
group: appuser
|
|
recurse: true
|
|
|
|
- name: Configure entrypoint
|
|
shell: |
|
|
buildah config --user appuser runtime-stage
|
|
buildah config --workingdir /app runtime-stage
|
|
buildah config --entrypoint '["./entrypoint.sh"]' runtime-stage
|
|
buildah config --cmd '["python", "src/app.py"]' runtime-stage
|
|
|
|
- name: Set labels
|
|
shell: |
|
|
buildah config --label version="{{ build_args.VERSION }}" runtime-stage
|
|
buildah config --label build-date="{{ build_args.BUILD_DATE }}" runtime-stage
|
|
buildah config --label commit-sha="{{ build_args.COMMIT_SHA }}" runtime-stage
|
|
buildah config --label maintainer="DevOps Team" runtime-stage
|
|
|
|
- name: Configure health check
|
|
shell: |
|
|
buildah config --healthcheck 'CMD curl -f http://localhost:5000/health || exit 1' runtime-stage
|
|
buildah config --healthcheck-interval 30s runtime-stage
|
|
buildah config --healthcheck-timeout 10s runtime-stage
|
|
buildah config --healthcheck-retries 3 runtime-stage
|
|
|
|
- name: Finalize and tag image
|
|
hosts: localhost
|
|
gather_facts: false
|
|
|
|
tasks:
|
|
- name: Commit final image
|
|
shell: |
|
|
buildah commit runtime-stage myapp:{{ build_args.VERSION }}
|
|
buildah commit runtime-stage myapp:latest
|
|
|
|
- name: Tag for registry
|
|
shell: |
|
|
buildah tag myapp:{{ build_args.VERSION }} registry.example.com/myapp:{{ build_args.VERSION }}
|
|
buildah tag myapp:latest registry.example.com/myapp:latest
|
|
when: lookup('env', 'REGISTRY_PUSH') == 'true'
|
|
|
|
- name: Push to registry
|
|
shell: |
|
|
buildah push registry.example.com/myapp:{{ build_args.VERSION }}
|
|
buildah push registry.example.com/myapp:latest
|
|
when: lookup('env', 'REGISTRY_PUSH') == 'true'
|
|
|
|
- name: Clean up build containers
|
|
shell: |
|
|
buildah rm build-stage runtime-stage
|
|
|
|
- name: Clean up build context
|
|
file:
|
|
path: /tmp/build-context
|
|
state: absent
|
|
|
|
- name: Display image information
|
|
shell: podman inspect myapp:{{ build_args.VERSION }}
|
|
register: image_info
|
|
|
|
- name: Show build summary
|
|
debug:
|
|
msg: |
|
|
Build completed successfully!
|
|
Image: myapp:{{ build_args.VERSION }}
|
|
Size: {{ (image_info.stdout | from_json)[0].Size | human_readable }}
|
|
Created: {{ (image_info.stdout | from_json)[0].Created }}
|
|
Labels: {{ (image_info.stdout | from_json)[0].Config.Labels }}
|
|
```
|
|
|
|
### Example 3: Container Development Environment
|
|
|
|
```yaml
|
|
---
|
|
- name: Set up development environment
|
|
hosts: localhost
|
|
gather_facts: false
|
|
vars:
|
|
dev_containers:
|
|
- name: dev-database
|
|
image: postgres:13
|
|
ports: ["5432:5432"]
|
|
env:
|
|
POSTGRES_DB: devdb
|
|
POSTGRES_USER: developer
|
|
POSTGRES_PASSWORD: devpass
|
|
- name: dev-redis
|
|
image: redis:alpine
|
|
ports: ["6379:6379"]
|
|
- name: dev-workspace
|
|
image: ubuntu:22.04
|
|
command: sleep infinity
|
|
ports: ["8080:8080", "3000:3000"]
|
|
volumes:
|
|
- "${PWD}:/workspace"
|
|
|
|
tasks:
|
|
- name: Create development network
|
|
containers.podman.podman_network:
|
|
name: dev-network
|
|
state: present
|
|
|
|
- name: Start development containers
|
|
containers.podman.podman_container:
|
|
name: "{{ item.name }}"
|
|
image: "{{ item.image }}"
|
|
state: started
|
|
command: "{{ item.command | default(omit) }}"
|
|
ports: "{{ item.ports | default([]) }}"
|
|
env: "{{ item.env | default({}) }}"
|
|
volumes: "{{ item.volumes | default([]) }}"
|
|
networks:
|
|
- name: dev-network
|
|
loop: "{{ dev_containers }}"
|
|
|
|
- name: Configure development workspace
|
|
hosts: dev-workspace
|
|
vars:
|
|
ansible_connection: containers.podman.podman
|
|
ansible_host: dev-workspace
|
|
ansible_podman_extra_env:
|
|
TERM: "xterm-256color"
|
|
EDITOR: "vim"
|
|
ansible_podman_timeout: 120
|
|
|
|
tasks:
|
|
- name: Update package cache
|
|
apt:
|
|
update_cache: true
|
|
|
|
- name: Install development tools
|
|
apt:
|
|
name:
|
|
- curl
|
|
- wget
|
|
- git
|
|
- vim
|
|
- tmux
|
|
- zsh
|
|
- python3
|
|
- python3-pip
|
|
- nodejs
|
|
- npm
|
|
- build-essential
|
|
- postgresql-client
|
|
- redis-tools
|
|
state: present
|
|
|
|
- name: Install Python development packages
|
|
pip:
|
|
name:
|
|
- ipython
|
|
- jupyter
|
|
- black
|
|
- flake8
|
|
- pytest
|
|
- requests
|
|
- sqlalchemy
|
|
- redis
|
|
state: present
|
|
|
|
- name: Configure Git
|
|
git_config:
|
|
name: "{{ item.name }}"
|
|
value: "{{ item.value }}"
|
|
scope: global
|
|
loop:
|
|
- { name: "user.name", value: "Developer" }
|
|
- { name: "user.email", value: "dev@example.com" }
|
|
- { name: "init.defaultBranch", value: "main" }
|
|
|
|
- name: Set up shell environment
|
|
copy:
|
|
content: |
|
|
export PATH=$PATH:/workspace/bin
|
|
export PYTHONPATH=/workspace/src
|
|
export DATABASE_URL=postgresql://developer:devpass@dev-database:5432/devdb
|
|
export REDIS_URL=redis://dev-redis:6379/0
|
|
|
|
alias ll='ls -la'
|
|
alias ..='cd ..'
|
|
alias gs='git status'
|
|
alias gd='git diff'
|
|
alias gc='git commit'
|
|
alias gp='git push'
|
|
|
|
# Auto-activate virtual environment if it exists
|
|
if [ -d "/workspace/venv" ]; then
|
|
source /workspace/venv/bin/activate
|
|
fi
|
|
dest: /root/.bashrc
|
|
mode: '0644'
|
|
|
|
- name: Create workspace directories
|
|
file:
|
|
path: "{{ item }}"
|
|
state: directory
|
|
mode: '0755'
|
|
loop:
|
|
- /workspace/src
|
|
- /workspace/tests
|
|
- /workspace/docs
|
|
- /workspace/bin
|
|
- /workspace/config
|
|
|
|
- name: Install oh-my-zsh
|
|
shell: |
|
|
sh -c "$(curl -fsSL https://raw.github.com/ohmyzsh/ohmyzsh/master/tools/install.sh)" || true
|
|
chsh -s $(which zsh)
|
|
ignore_errors: true
|
|
|
|
- name: Start Jupyter notebook server
|
|
shell: |
|
|
cd /workspace
|
|
nohup jupyter notebook --ip=0.0.0.0 --port=8080 --no-browser --allow-root &
|
|
async: 10
|
|
poll: 0
|
|
ignore_errors: true
|
|
|
|
- name: Verify development environment
|
|
hosts: localhost
|
|
gather_facts: false
|
|
|
|
tasks:
|
|
- name: Test database connection
|
|
shell: |
|
|
podman exec dev-workspace psql postgresql://developer:devpass@dev-database:5432/devdb -c "SELECT version();"
|
|
register: db_test
|
|
ignore_errors: true
|
|
|
|
- name: Test Redis connection
|
|
shell: |
|
|
podman exec dev-workspace redis-cli -h dev-redis ping
|
|
register: redis_test
|
|
ignore_errors: true
|
|
|
|
- name: Display environment status
|
|
debug:
|
|
msg: |
|
|
Development environment ready!
|
|
|
|
Services:
|
|
- Database: {{ 'OK' if db_test.rc == 0 else 'FAILED' }}
|
|
- Redis: {{ 'OK' if redis_test.rc == 0 else 'FAILED' }}
|
|
- Workspace: Running
|
|
|
|
Access:
|
|
- Jupyter: http://localhost:8080
|
|
- Workspace: podman exec -it dev-workspace /bin/bash
|
|
- Database: psql postgresql://developer:devpass@localhost:5432/devdb
|
|
|
|
Workspace mounted at: /workspace
|
|
```
|
|
|
|
## Performance and Best Practices
|
|
|
|
### Connection Caching
|
|
|
|
Both plugins internally cache lightweight details (for example, container validation) to reduce overhead. There are no user-facing options to control this.
|
|
|
|
### Mount Detection
|
|
|
|
Enable mount detection for efficient file transfers:
|
|
|
|
```yaml
|
|
# Automatically detect shared mounts (default: true)
|
|
ansible_podman_mount_detection: true
|
|
ansible_buildah_mount_detection: true
|
|
|
|
# Ignore mount detection errors
|
|
ansible_podman_ignore_mount_errors: true
|
|
ansible_buildah_ignore_mount_errors: true
|
|
```
|
|
|
|
### Timeout Configuration
|
|
|
|
Configure optional timeouts (default is 0 = no timeout):
|
|
|
|
```yaml
|
|
# Command timeout in seconds (0 = no timeout)
|
|
ansible_podman_timeout: 0
|
|
ansible_buildah_timeout: 0
|
|
```
|
|
|
|
### Environment Variable Management
|
|
|
|
Efficiently pass environment variables:
|
|
|
|
```yaml
|
|
# Method 1: Individual variables
|
|
ansible_podman_extra_env:
|
|
API_KEY: "{{ vault_api_key }}"
|
|
DEBUG: "true"
|
|
LOG_LEVEL: "INFO"
|
|
|
|
# Method 2: From file
|
|
ansible_podman_extra_env: "{{ lookup('file', 'env.json') | from_json }}"
|
|
```
|
|
|
|
### Best Practices
|
|
|
|
1. **Use specific container names**: Avoid generic names to prevent conflicts
|
|
2. **Implement health checks**: Use container health checks for reliability
|
|
3. **Handle secrets securely**: Use Ansible Vault for sensitive data
|
|
4. **Monitor resource usage**: Set appropriate memory and CPU limits
|
|
5. **Use multi-stage builds**: Optimize image size with Buildah multi-stage builds
|
|
6. **Cache dependencies**: Leverage layer caching for faster builds
|
|
7. **Design for fail-fast**: Prefer explicit failed_when/changed_when instead of retries
|
|
|
|
## Troubleshooting
|
|
|
|
### Common Issues
|
|
|
|
#### Container Not Found
|
|
|
|
```text
|
|
Error: Container 'my-container' not found
|
|
```
|
|
|
|
**Solution**: Ensure the container is running and the name/ID is correct.
|
|
|
|
#### Permission Denied
|
|
|
|
```text
|
|
Error: Permission denied when accessing container
|
|
```
|
|
|
|
**Solution**: Check container permissions or run with appropriate privileges.
|
|
|
|
#### Timeout Errors
|
|
|
|
```text
|
|
Error: Command execution timed out
|
|
```
|
|
|
|
**Solution**: Increase timeout values or optimize commands.
|
|
|
|
#### Mount Detection Failures
|
|
|
|
```text
|
|
Warning: Mount detection failed
|
|
```
|
|
|
|
**Solution**: Disable mount detection or ignore mount errors.
|
|
|
|
### Debug Configuration
|
|
|
|
Enable verbose logging for troubleshooting:
|
|
|
|
```yaml
|
|
# Enable debug logging
|
|
ansible_podman_debug: true
|
|
ansible_buildah_debug: true
|
|
|
|
# Increase verbosity
|
|
ansible_verbosity: 3
|
|
```
|
|
|
|
### Testing Connection
|
|
|
|
Test connection plugin functionality:
|
|
|
|
```bash
|
|
# Test Podman connection
|
|
ansible -i inventory -m setup podman_host
|
|
|
|
# Test Buildah connection
|
|
ansible -i inventory -m setup buildah_host
|
|
|
|
# Run connection tests
|
|
./ci/run_connection_test.sh podman
|
|
./ci/run_connection_test.sh buildah
|
|
```
|
|
|
|
## Migration from Legacy Plugins
|
|
|
|
### From Docker Connection Plugin
|
|
|
|
Replace Docker connection configuration:
|
|
|
|
```yaml
|
|
# Old Docker configuration
|
|
ansible_connection: docker
|
|
ansible_docker_extra_args: "--user root"
|
|
|
|
# New Podman configuration
|
|
ansible_connection: containers.podman.podman
|
|
ansible_podman_extra_env:
|
|
USER: root
|
|
```
|
|
|
|
### From Custom Scripts
|
|
|
|
Replace custom container execution scripts:
|
|
|
|
```yaml
|
|
# Old custom script approach
|
|
- name: Run in container
|
|
shell: podman exec my-container {{ command }}
|
|
|
|
# New connection plugin approach
|
|
- name: Run in container
|
|
hosts: my-container
|
|
vars:
|
|
ansible_connection: containers.podman.podman
|
|
tasks:
|
|
- name: Execute command
|
|
command: "{{ command }}"
|
|
```
|
|
|
|
### Configuration Mapping
|
|
|
|
| Legacy Option | Podman Plugin | Buildah Plugin |
|
|
|---------------|---------------|----------------|
|
|
| `ansible_docker_extra_args` | `ansible_podman_extra_env` | `ansible_buildah_extra_env` |
|
|
| `ansible_docker_timeout` | `ansible_podman_timeout` | `ansible_buildah_timeout` |
|
|
| N/A | `ansible_podman_retries` | `ansible_buildah_retries` |
|
|
| N/A | `ansible_podman_mount_detection` | `ansible_buildah_mount_detection` |
|
|
|
|
---
|
|
|
|
For more information and examples, see the [official documentation](https://github.com/containers/ansible-podman-collections) and [test cases](tests/integration/targets/).
|