From c462dac0d86e8a4720104ff0f409afcacb6fbd48 Mon Sep 17 00:00:00 2001 From: Daniel Akulenok Date: Fri, 12 Sep 2025 11:12:57 +0200 Subject: [PATCH] Readme --- README.md | 529 +++++++++++++++++++++++++++++------------------------- 1 file changed, 285 insertions(+), 244 deletions(-) diff --git a/README.md b/README.md index f461331..e140dfa 100644 --- a/README.md +++ b/README.md @@ -1,182 +1,163 @@ -Podman -====== +# Podman Role -This Ansible role installs and configures Podman container runtime, and provides comprehensive container, pod, network, and volume management capabilities. +**Bootstrap containerized applications with Podman in minutes.** -Requirements ------------- - -- Ansible 2.11 or higher -- Target systems: Ubuntu 20.04+, Debian 11+ -- containers.podman collection (for container management tasks) - -Role Variables --------------- - -### Package Installation - -* `podman_packages`: List of Podman packages to install (includes core and additional packages for Debian/Ubuntu) - -### Configuration Variables - -* `podman_configure_registries`: Configure container registries (default: `true`) -* `podman_registries_conf_path`: Path to registries configuration (default: `/etc/containers/registries.conf`) -* `podman_registries_additional`: Additional registry configurations for special cases - -**Note**: Registry configuration is now unified with the image signature policy through `podman_policy_trusted_registries`. Each registry in the policy configuration includes both security settings (signature verification) and registry behavior (insecure, blocked, unqualified search). - -* `podman_configure_storage`: Configure storage settings (default: `true`) -* `podman_storage_conf_path`: Path to storage configuration (default: `/etc/containers/storage.conf`) -* `podman_storage_driver`: Storage driver to use (default: `overlay`) -* `podman_storage_runroot`: Runtime storage path (default: `/run/containers/storage`) -* `podman_storage_graphroot`: Persistent storage path (default: `/var/lib/containers/storage`) - -* `podman_configure_policy`: Configure container policy (default: `true`) -* `podman_policy_path`: Path to policy configuration (default: `/etc/containers/policy.json`) - -### Image Signature Policy Variables - -* `podman_policy_default_type`: Default policy for unlisted registries (`"insecureAcceptAnything"` or `"reject"`) -* `podman_policy_reject_unknown_registries`: Reject images from unlisted registries (default: `false`) -* `podman_policy_trusted_registries`: Unified registry configuration for both policy and registries.conf - -Each registry in `podman_policy_trusted_registries` supports: - -**Security Policy Options:** -- `type`: Verification type (`"insecureAcceptAnything"`, `"signedBy"`, `"reject"`) -- `keyPath`: Path to GPG key file (for `signedBy` type) -- `keyData`: Inline GPG key data (alternative to `keyPath`) - -**Registry Configuration Options:** -- `insecure`: Allow insecure (HTTP) connections (default: `false`) -- `blocked`: Block access to this registry (default: `false`) -- `unqualified_search`: Include in unqualified image searches (default: `true`) -- `mirror`: List of mirror registries for redundancy/performance +## 🚀 Quick Start +### 1. Basic Setup ```yaml -# Unified registry and policy configuration -podman_policy_trusted_registries: - - registry: "docker.io" - # Policy settings - type: "insecureAcceptAnything" - # Registry settings - insecure: false - blocked: false - unqualified_search: true - - - registry: "internal-registry.company.com" - # Policy settings - type: "signedBy" - keyPath: "/etc/pki/containers/company.gpg" - # Registry settings - insecure: false - blocked: false - unqualified_search: true - # Mirror configuration - mirror: - - location: "backup-registry.company.com" - insecure: false - -# Development configuration (default) -podman_policy_default_type: "insecureAcceptAnything" -podman_policy_reject_unknown_registries: false - -# Production configuration with signature verification -podman_policy_default_type: "reject" -podman_policy_reject_unknown_registries: true +- hosts: servers + roles: + - podman ``` -### Service Variables +### 2. Run Your First Container +```yaml +- hosts: servers + roles: + - role: podman + vars: + podman_containers: + - name: nginx + image: nginx:latest + state: started + ports: + - "80:80" +``` -* `podman_enable_socket`: Enable Podman socket service (default: `false`) -* `podman_enable_api_service`: Enable Podman API service (default: `false`) +### 3. Common Patterns -### Container Management Variables +**Web application with database:** +```yaml +podman_containers: + - name: webapp + image: myapp:latest + state: started + ports: + - "8080:8080" + env: + DATABASE_URL: "postgresql://postgres@db:5432/app" + + - name: database + image: postgres:15 + state: started + volumes: + - "db-data:/var/lib/postgresql/data" + env: + POSTGRES_DB: app + POSTGRES_PASSWORD: secret + +podman_volumes: + - name: db-data +``` + +**That's it!** Podman will be installed, configured, and your containers will be running with systemd services automatically created. + +--- + +## 📋 Requirements + +- **Ansible**: 2.11+ +- **Target OS**: Ubuntu 20.04+, Debian 11+ +- **Collection**: `containers.podman` (auto-installed) + +--- + +## 🔧 Complete Feature Reference + +### Container Management ```yaml podman_containers: - - name: nginx - image: docker.io/nginx:latest - state: started + - name: my-app + image: nginx:latest + state: started # started|stopped|present|absent ports: - "8080:80" + - "443:443" volumes: - - "/etc/nginx/conf.d:/etc/nginx/conf.d:ro" + - "/host/path:/container/path" + - "volume-name:/data" env: - NGINX_HOST: example.com - restart_policy: always - user: nginx + ENV_VAR: value networks: - - podman + - app-network + restart_policy: always # no|always|on-failure|unless-stopped + user: "1000:1000" labels: - app: webserver - version: "1.0" + app: web + environment: prod + memory: "1g" + cpu_shares: 1024 + device: + - "/dev/sda:/dev/xvda:rwm" + security_opt: + - "seccomp=unconfined" + healthcheck: + test: ["CMD", "curl", "-f", "http://localhost"] + interval: 30s + timeout: 10s + retries: 3 + # Systemd service generation (optional) + generate_systemd: + path: "/etc/systemd/system" + restart_policy: always + after: ["network.target"] + wants: ["network-online.target"] ``` -### Network Management Variables +### Network Management ```yaml podman_networks: - name: app-network - driver: bridge - subnet: "10.89.0.0/24" - gateway: "10.89.0.1" state: present - internal: false - disable_dns: false + driver: bridge # bridge|macvlan|ipvlan + subnet: "172.20.0.0/16" + gateway: "172.20.0.1" + internal: false # true for isolated networks dns: - "8.8.8.8" + - "1.1.1.1" options: mtu: 1500 vlan: 100 - ipam_driver: "host-local" - interface_name: "podman1" - route: - - "10.10.0.0/16,192.168.1.1" + + # Advanced networking - name: macvlan-net driver: macvlan - macvlan: "eth0" + macvlan: "eth0" # Parent interface subnet: "192.168.1.0/24" + - name: ipv6-net driver: bridge subnet: "fd00::/64" ipv6: true - recreate: false ``` -### Volume Management Variables +### Volume Management ```yaml podman_volumes: - name: app-data state: present - driver: local + driver: local # local|tmpfs labels: - environment: production backup: daily + environment: prod options: - "device=/dev/sdb1" - "type=ext4" - "o=rw" + - name: tmpfs-volume - state: present driver: tmpfs options: - "tmpfs-size=100m" - "tmpfs-mode=1777" - - name: quadlet-volume - state: quadlet - driver: local - quadlet_filename: "custom-volume" - quadlet_file_mode: "0640" - quadlet_options: - - "Group=192" - - "Copy=true" - recreate: false - debug: false ``` -### Pod Management Variables +### Pod Management ```yaml podman_pods: @@ -184,7 +165,6 @@ podman_pods: state: started ports: - "8080:80" - - "3306:3306" networks: - frontend hostname: webapp @@ -192,162 +172,223 @@ podman_pods: - "8.8.8.8" labels: app: webapp - tier: frontend volumes: - "webapp-data:/data" - infra: true - infra_image: "k8s.gcr.io/pause:3.1" memory: "2g" - cpu_shares: "1024" - security_opt: - - "seccomp=unconfined" - add_host: - - "database.local:127.0.0.1" - share: "net,ipc" - userns: "auto" - device: - - "/dev/sda:/dev/xvda:rwm" - sysctl: - net.core.somaxconn: "1024" - exit_policy: "stop" - - name: quadlet-pod - state: quadlet - quadlet_filename: "custom-pod" - quadlet_options: - - "AutoUpdate=registry" - generate_systemd: - path: "/etc/systemd/system" - restart_policy: "always" + cpu_shares: 1024 + share: "net,ipc" # Shared namespaces + infra: true # Use infra container + infra_image: "registry.k8s.io/pause:3.9" ``` -### Systemd Service Generation - -The role can automatically generate systemd service files for containers and pods. This functionality helps in managing container lifecycle through systemd. - -* `podman_generate_systemd`: Enable systemd service generation (default: `true`) -* `podman_systemd_dir`: Directory for generated service files (default: `/etc/systemd/system`) - -**Global Systemd Options** (`podman_systemd_options`): +### Advanced Configuration +#### Registry & Security Policy ```yaml +# Basic registry setup (development) +podman_policy_default_type: "insecureAcceptAnything" +podman_policy_reject_unknown_registries: false + +# Production security (with signatures) +podman_policy_default_type: "reject" +podman_policy_reject_unknown_registries: true +podman_policy_trusted_registries: + - registry: "docker.io" + type: "insecureAcceptAnything" + unqualified_search: true + + - registry: "internal.company.com" + type: "signedBy" + keyPath: "/etc/pki/containers/company.gpg" + insecure: false + mirror: + - location: "backup.company.com" +``` + +#### Systemd Service Generation +```yaml +# Global systemd settings +podman_generate_systemd: true podman_systemd_options: - new: true # Generate new service files - force: true # Overwrite existing files - restart_policy: always # Default restart policy - stop_timeout: 120 # Stop timeout in seconds - no_header: false # Include header in service files - wants: [] # Systemd unit Wants - after: [] # Systemd unit After - requires: [] # Systemd unit Requires - container_prefix: "container-" # Prefix for container service names - pod_prefix: "pod-" # Prefix for pod service names - restart_sec: 30 # Restart delay in seconds + restart_policy: always + stop_timeout: 120 + after: ["network.target"] + wants: ["network-online.target"] + container_prefix: "container-" + pod_prefix: "pod-" ``` -**Per-Container/Pod Configuration:** - -You can override global systemd options for individual containers or pods: - -```yaml -podman_containers: - - name: webapp - image: nginx:latest - systemd: - restart_policy: always - after: ["network.target"] - wants: ["network-online.target"] - restart_sec: 10 - -podman_pods: - - name: database - systemd: - restart_policy: on-failure - requires: ["network.target"] - time: 180 -``` - -When `systemd` is defined for a container or pod, the role will: -1. Generate a systemd service file -2. Place it in the specified directory -3. Reload systemd daemon -4. (Optional) Enable and start the service - -**Note:** Container/pod-specific options take precedence over global options defined in `podman_systemd_options`. - -### Resource Pruning - -The role can automatically clean up unused Podman resources to free up disk space and maintain system hygiene. - -* `podman_prune_enabled`: Enable automatic pruning of unused resources (default: `true`) -* `podman_prune_options`: Configuration for what should be pruned - +#### Resource Cleanup ```yaml +# Auto-cleanup unused resources +podman_prune_enabled: true podman_prune_options: container: true # Remove stopped containers image: true # Remove unused images network: true # Remove unused networks - system: true # Prune all unused data - system_all: true # Prune all unused data including build cache volume: true # Remove unused volumes + system: true # Full system cleanup ``` -You can selectively disable certain types of pruning by setting their values to `false`: - +#### Storage Configuration ```yaml -podman_prune_options: - container: true # Still remove containers - image: false # Keep all images - network: true # Remove unused networks - system: false # Keep system data - system_all: false # Keep build cache - volume: false # Keep all volumes +podman_configure_storage: true +podman_storage_driver: overlay +podman_storage_graphroot: /var/lib/containers/storage +podman_storage_runroot: /run/containers/storage ``` -Dependencies ------------- - -* `containers.podman` collection for container management tasks - -Example Playbook ----------------- - +#### API & Socket Services ```yaml -- hosts: servers +podman_enable_socket: true # Enable Podman socket +podman_enable_api_service: true # Enable REST API +``` + +--- + +## 🏷️ Available Tags + +Run specific parts of the role: + +```bash +# Install only +ansible-playbook -t podman-install playbook.yml + +# Configure only +ansible-playbook -t podman-configure playbook.yml + +# Manage containers only +ansible-playbook -t podman-containers playbook.yml + +# Manage networks only +ansible-playbook -t podman-networks playbook.yml +``` + +**Available tags:** +- `podman` - Run everything +- `podman-install` - Package installation +- `podman-configure` - Configuration files +- `podman-services` - System services +- `podman-networks` - Network management +- `podman-volumes` - Volume management +- `podman-pods` - Pod management +- `podman-containers` - Container management +- `podman-systemd` - Systemd service generation +- `podman-prune` - Resource cleanup + +--- + +## 📚 Example Playbooks + +### Development Environment +```yaml +- hosts: dev-servers roles: - - role: keepit.podman + - role: podman vars: + # Permissive for development + podman_policy_default_type: "insecureAcceptAnything" podman_enable_socket: true + podman_containers: - - name: web-server + - name: dev-web image: nginx:latest state: started ports: - - "80:80" + - "8080:80" volumes: - - "/var/www/html:/usr/share/nginx/html:ro" - podman_networks: - - name: web-network - subnet: "172.20.0.0/16" + - "./web:/usr/share/nginx/html" ``` -Tags ----- +### Production Environment +```yaml +- hosts: prod-servers + roles: + - role: podman + vars: + # Strict security for production + podman_policy_default_type: "reject" + podman_policy_reject_unknown_registries: true + podman_policy_trusted_registries: + - registry: "registry.company.com" + type: "signedBy" + keyPath: "/etc/pki/containers/prod.gpg" + + podman_containers: + - name: prod-app + image: registry.company.com/app:v1.2.3 + state: started + restart_policy: always + memory: "2g" + cpu_shares: 2048 + healthcheck: + test: ["CMD", "curl", "-f", "http://localhost/health"] + interval: 30s + timeout: 10s + retries: 3 +``` -* `podman` - Run all tasks -* `podman-install` - Install packages only -* `podman-configure` - Configure Podman only -* `podman-services` - Manage services only -* `podman-networks` - Manage networks only -* `podman-volumes` - Manage volumes only -* `podman-pods` - Manage pods only -* `podman-containers` - Manage containers only +### Multi-Service Application +```yaml +- hosts: app-servers + roles: + - role: podman + vars: + podman_networks: + - name: app-network + subnet: "172.20.0.0/16" + + podman_volumes: + - name: postgres-data + - name: redis-data + - name: app-uploads + + podman_containers: + # Database + - name: postgres + image: postgres:15 + state: started + networks: + - app-network + volumes: + - "postgres-data:/var/lib/postgresql/data" + env: + POSTGRES_DB: myapp + POSTGRES_PASSWORD: "{{ vault_db_password }}" + + # Cache + - name: redis + image: redis:7-alpine + state: started + networks: + - app-network + volumes: + - "redis-data:/data" + + # Application + - name: app + image: myapp:latest + state: started + networks: + - app-network + ports: + - "80:8080" + volumes: + - "app-uploads:/app/uploads" + env: + DATABASE_URL: "postgresql://postgres:{{ vault_db_password }}@postgres:5432/myapp" + REDIS_URL: "redis://redis:6379" + depends_on: + - postgres + - redis +``` -License -------- +--- + +## 📄 License MIT -Author Information ------------------- +## 👤 Author Daniel Akulenok