Usage Guide
This guide covers the practical aspects of using mpy-metapackage to deploy and manage applications on Kubernetes.
Critical: Service Discovery
Never hardcode service names! Always use @{ obj.key }@-{part}-svc pattern:
❌ WRONG: mongodb://mongodb:27017
✅ RIGHT: "mongodb://@{ obj.key }@-mongodb-svc:27017"
Without this, your parts cannot communicate with each other!
Basic Workflow
1. Configuration Design
Before deploying, plan your application architecture:
Identify Your Parts:
- Web frontend → server part with HTTP routes
- API backend → server part with different routes
- Background jobs → worker part
- Scheduled tasks → cronjob part
- External service routing → http part
2. Configuration Files
Create your configuration files:
your-project/
├── values.yaml # Helm values (TLS, common settings)
├── mpy_meta_config.yaml # Parts configuration
└── values-secrets.yaml # Environment-specific overrides
3. Basic Deployment Pattern
Minimal Configuration:
# mpy_meta_config.yaml
mpy_meta_config:
parts:
web:
deployment:
resources:
requests:
cpu: 100m
memory: 128Mi
ports:
- name: http
port: 80
routes:
- name: main
pathPrefix: PathPrefix(`/`)
port_name: http
Development Workflow
Local Development
# 1. Validate configuration
make dbg_template VALUES_FILE=your-values.yaml
# 2. Test deployment (dry-run)
make dbg_install VALUES_FILE=your-values.yaml
# 3. Deploy to development
make install VALUES_FILE=your-values.yaml NAMESPACE=dev
Persistent development volume
Run an application whose code lives on a volume instead of inside the image, so a fix made in
a running pod survives a restart. Declare it once in the Parts Config, then switch it on per
Release with dev_mode:
mpy_meta_config:
requires_m2p: "3.1.0"
parts:
gui:
volumes:
- name: dev-code
mountPath: "/opt/app" # where the image keeps the code
dev_mode: true # mounted only while the Release has dev_mode on
seed_from: "/opt/app" # filled from the image, once
# ... same block on every part that must run the same code
volumesDefinition:
- name: dev-code
description: Application code - persistent dev volume # REQUIRED, see below
dev_mode: true # no PVC at all unless dev_mode is on
co_locate: true # every part mounting it stays on one node
claim:
accessModes: [ReadWriteOnce]
size: 20Gi
With dev_mode off nothing exists — no PVC, no mount. With it on, the volume is filled from the
image on first use and never overwritten afterwards: the application keeps serving, normally,
from the volume. Edit, commit, let CI/CD rebuild the image for the parts that have no volume.
Three things decide whether this works, all covered in Parts Configuration Reference:
descriptionon thevolumesDefinitionentry — without it the PVC is deleted the moment the volume leaves the manifest;accessModesandstorageClassNameare immutable once deployed — settle them first;co_locatelets several parts share aReadWriteOnceclaim, and is what makes the whole thing deployable on a storage class that cannot do RWX.
Production Deployment
# 1. Build and package
make build
# 2. Deploy with production values
helm install production-app . \
-f values.yaml \
-f values-production.yaml \
-f mpy_meta_config.yaml \
--namespace production
Common Patterns
Single Web Application
Simple web app with database:
mpy_meta_config:
parts:
webapp:
deployment:
env_vars:
- name: DATABASE_URL
value: "postgresql://..."
resources: { ... }
ports:
- name: http
port: 8080
routes:
- name: web
pathPrefix: PathPrefix(`/`)
port_name: http
middlewares:
ipwhitelist: true
Microservices Architecture
Multiple services with shared configuration:
mpy_meta_config:
parts:
api:
host_prefix: "api-" # Creates api-{main-fqdn}
deployment: { ... }
routes:
- name: api
pathPrefix: PathPrefix(`/api`)
port_name: http
frontend:
deployment: { ... }
routes:
- name: web
pathPrefix: PathPrefix(`/`)
port_name: http
Background Processing
Web app with workers and scheduled tasks:
mpy_meta_config:
parts:
web:
deployment: { ... }
ports: [...]
routes: [...]
worker:
type: worker
deployment:
args: ["--worker-mode"]
resources: { ... }
scheduler:
type: cronjob
cronjob:
schedule: "0 2 * * *"
args: ["--daily-cleanup"]
resources: { ... }
Configuration Management
Environment-Specific Values
Use multiple values files for different environments:
# values-base.yaml (common settings)
package_release:
name: myapp
key: myapp-{{ env }}
# values-dev.yaml
package_gui_fqdn: myapp-dev.example.com
resources:
requests:
cpu: 100m
memory: 128Mi
# values-prod.yaml
package_gui_fqdn: myapp.example.com
resources:
requests:
cpu: 500m
memory: 512Mi
Secret Management
Use Muppy Vault for sensitive configuration:
# Declare vault objects in parts config
mpy_meta_config:
vault_objects:
- name: app-secrets
type: secret
- name: app-config
type: configmap
parts:
webapp:
envFrom:
- secretRef:
name: app-secrets
- configMapRef:
name: app-config
Debugging and Troubleshooting
Template Debugging
# Debug template rendering
helm template my-app . -f values.yaml -f mpy_meta_config.yaml
# Save debug output
make dbg_template > debug-output.yaml
Runtime Debugging
Enable debug mode in parts configuration:
parts:
webapp:
debug_mode_available: basic # or 'codr' for VSCode
debug_config:
args: ["sleep", "infinity"]
Then activate through Muppy dashboard or values:
Common Issues
Part code too long:
# ❌ Wrong - code too long
parts:
my-very-long-service-name: # > 8 chars
# ✅ Correct - short code
parts:
webapi: # ≤ 8 chars
Missing deployment properties:
# ❌ Wrong - empty deployment
parts:
webapp:
deployment:
# ✅ Correct - at least one property
parts:
webapp:
deployment:
resources: {}
Integration Patterns
With Existing Helm Charts
Use mpy-metapackage as a subchart:
With External Services
Route to services outside the chart:
parts:
database-ui:
type: http
routes:
- name: dbadmin
pathPrefix: PathPrefix(`/dbadmin`)
service:
name: postgresql-admin
port: 8080
Next Steps
- Parts Configuration Reference - Complete configuration options
- Advanced Features - Volumes, debugging, and custom manifests
[Additional usage patterns and examples will be added here based on common use cases]