From dbece43dc536ba49ae47fd5235447419b11269a8 Mon Sep 17 00:00:00 2001 From: Pranay Sanghvi Date: Tue, 24 Feb 2026 13:55:33 +0530 Subject: [PATCH 1/3] Add staging config override how-to and reference note Introduce a new how-to (docs/howtos/customization/staging_config_override.md) that explains how to override staging workload configurations at build trigger-time via the staging API (StageRequest.stagingConfig). The guide covers fields, merge semantics, validation, examples, cURL usage, and verification steps. Also update docs/references/customization/staging.md to include an info callout linking to the new how-to. --- .../customization/staging_config_override.md | 356 ++++++++++++++++++ docs/references/customization/staging.md | 4 + 2 files changed, 360 insertions(+) create mode 100644 docs/howtos/customization/staging_config_override.md diff --git a/docs/howtos/customization/staging_config_override.md b/docs/howtos/customization/staging_config_override.md new file mode 100644 index 0000000000..25e914ff86 --- /dev/null +++ b/docs/howtos/customization/staging_config_override.md @@ -0,0 +1,356 @@ +--- +sidebar_label: Staging configuration override +title: Staging configuration override at trigger time +description: Override staging workload configurations at build trigger-time using the Epinio API. +keywords: [kubernetes, epinio, staging, customization, API, StageRequest] +doc-type: [how-to] +doc-topic: [epinio, how-to, customize, staging] +doc-persona: [epinio-operator] +--- + +This guide explains how to override staging workload configurations at build trigger-time using the Epinio API. + +## Overview + +Epinio allows you to override staging workload configurations when triggering a build, without modifying the base configuration stored in ConfigMaps. This enables per-build customization for specific use cases such as: + +- Different resource requirements for specific builds +- Testing with different node selectors +- Temporary configuration changes without modifying base settings +- Build-specific optimizations + +## Base Configuration + +Staging workload configurations are typically defined in ConfigMaps with the label `app.kubernetes.io/component=epinio-staging`. These provide the default configuration for all staging jobs. The base configuration includes: + +- Resource requests and limits +- Node selectors +- Tolerations +- Affinity rules +- TTL (time-to-live) for completed jobs +- Storage configuration + +## Override Configuration + +You can override any of these settings by including a `stagingConfig` field in your `StageRequest` when calling the staging API endpoint. + +### API Endpoint + +``` +POST /api/v1/namespaces/{namespace}/applications/{app}/stage +``` + +### Request Body + +```json +{ + "app": { + "name": "myapp", + "namespace": "workspace" + }, + "blobuid": "abc123...", + "stagingConfig": { + "resources": { + "requests": { + "cpu": "500m", + "memory": "2Gi" + }, + "limits": { + "cpu": "1000m", + "memory": "4Gi" + } + }, + "nodeSelector": { + "kubernetes.io/os": "linux" + }, + "ttlSecondsAfterFinished": 600 + } +} +``` + +## Configuration Fields + +### Resources + +Override CPU and memory requests and limits: + +```json +{ + "stagingConfig": { + "resources": { + "requests": { + "cpu": "500m", + "memory": "2Gi" + }, + "limits": { + "cpu": "1000m", + "memory": "4Gi" + } + } + } +} +``` + +- **Partial overrides**: You can override only `requests` or only `limits`; the other will be preserved from base configuration +- **Format**: Use Kubernetes quantity format (e.g., "500m", "1Gi", "1000") +- **Validation**: Invalid quantities are logged as warnings and base values are used + +### NodeSelector + +Completely replace the node selector: + +```json +{ + "stagingConfig": { + "nodeSelector": { + "kubernetes.io/os": "linux", + "node-type": "gpu" + } + } +} +``` + +- **Note**: NodeSelector is completely replaced (not merged) when provided +- **Empty map**: An empty map is treated as "not provided" and base values are preserved + +### Tolerations + +Override pod tolerations: + +```json +{ + "stagingConfig": { + "tolerations": [ + { + "key": "special-node", + "operator": "Equal", + "value": "true", + "effect": "NoSchedule" + } + ] + } +} +``` + +- **Format**: Standard Kubernetes Toleration objects +- **Empty array**: An empty array is treated as "not provided" and base values are preserved + +### Affinity + +Override pod affinity rules: + +```json +{ + "stagingConfig": { + "affinity": { + "nodeAffinity": { + "requiredDuringSchedulingIgnoredDuringExecution": { + "nodeSelectorTerms": [ + { + "matchExpressions": [ + { + "key": "kubernetes.io/arch", + "operator": "In", + "values": ["amd64"] + } + ] + } + ] + } + } + } + } +} +``` + +- **Format**: Standard Kubernetes Affinity object +- **Validation**: Invalid affinity configurations are logged as warnings and base values are used + +### TTLSecondsAfterFinished + +Override the time-to-live for completed jobs: + +```json +{ + "stagingConfig": { + "ttlSecondsAfterFinished": 600 + } +} +``` + +- **Values**: Must be >= 0 +- **0**: Means no TTL (job will not be automatically deleted) +- **Validation**: Negative values are rejected and base configuration is used + +### ServiceAccountName + +Override the service account: + +```json +{ + "stagingConfig": { + "serviceAccountName": "custom-sa" + } +} +``` + +- **Validation**: Must follow DNS-1123 subdomain format (lowercase alphanumeric, hyphens, dots, max 253 chars) +- **Invalid names**: Are rejected with a warning and base configuration is used + +### Storage Configuration + +Override storage settings for cache and source blobs: + +```json +{ + "stagingConfig": { + "storage": { + "cache": { + "size": "2Gi", + "storageClassName": "fast-ssd", + "volumeMode": "Filesystem", + "accessModes": ["ReadWriteOnce"], + "emptyDir": false + }, + "sourceBlobs": { + "size": "1Gi", + "storageClassName": "standard", + "volumeMode": "Filesystem", + "accessModes": ["ReadWriteOnce", "ReadOnlyMany"], + "emptyDir": false + } + } + } +} +``` + +#### Storage Fields + +- **size**: Storage size (e.g., "1Gi", "500Mi") +- **storageClassName**: Kubernetes storage class name +- **volumeMode**: Either "Filesystem" or "Block" +- **accessModes**: Array of valid access modes: + - `ReadWriteOnce` + - `ReadOnlyMany` + - `ReadWriteMany` +- **emptyDir**: Boolean - if true, use emptyDir volume instead of PVC + +**Validation**: +- Invalid `VolumeMode` values are rejected (must be "Filesystem" or "Block") +- Invalid `AccessModes` are skipped; valid ones are used +- Empty arrays are treated as "not provided" and base values are preserved + +## Merge Semantics + +The override configuration is merged with the base configuration using the following rules: + +1. **Scalar fields** (ServiceAccountName, TTLSecondsAfterFinished): Override completely replaces base if provided +2. **Maps** (NodeSelector): Override completely replaces base (not merged) +3. **Arrays** (Tolerations, AccessModes): Override replaces base if provided and non-empty +4. **Structs** (Resources, Storage, Affinity): Fields are merged individually; override values take precedence +5. **Empty values**: Empty arrays/maps/strings are treated as "not provided" and base values are preserved + +## Examples + +### Example 1: Override Resources Only + +```json +{ + "app": {"name": "myapp", "namespace": "workspace"}, + "blobuid": "abc123", + "stagingConfig": { + "resources": { + "requests": {"cpu": "500m", "memory": "2Gi"} + } + } +} +``` + +This will: +- Use override for CPU/memory requests +- Preserve base configuration for limits +- Preserve all other base settings + +### Example 2: Override Multiple Fields + +```json +{ + "app": {"name": "myapp", "namespace": "workspace"}, + "blobuid": "abc123", + "stagingConfig": { + "resources": { + "requests": {"cpu": "500m", "memory": "2Gi"}, + "limits": {"cpu": "1000m", "memory": "4Gi"} + }, + "nodeSelector": {"kubernetes.io/os": "linux"}, + "ttlSecondsAfterFinished": 600 + } +} +``` + +### Example 3: Using cURL + +```bash +curl -X POST "https://your-epinio-server/api/v1/namespaces/workspace/applications/myapp/stage" \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer YOUR_TOKEN" \ + -d '{ + "app": {"name": "myapp", "namespace": "workspace"}, + "blobuid": "YOUR_BLOB_UID", + "stagingConfig": { + "resources": { + "requests": {"cpu": "500m", "memory": "2Gi"} + } + } + }' +``` + +## Error Handling + +When invalid values are provided: + +1. **Warnings are logged** in the Epinio server logs +2. **Base configuration is used** for the invalid field +3. **Request still succeeds** - the staging job is created with valid overrides and base values for invalid ones + +### Common Validation Errors + +- **Invalid ServiceAccountName**: Must be DNS-1123 compliant +- **Invalid resource quantities**: Must be valid Kubernetes quantity format +- **Invalid AccessModes**: Must be one of ReadWriteOnce, ReadOnlyMany, ReadWriteMany +- **Invalid VolumeMode**: Must be "Filesystem" or "Block" +- **Negative TTL**: Must be >= 0 + +## Verifying Overrides + +After staging, you can verify the configuration was applied: + +```bash +# List staging jobs +kubectl get jobs -n epinio -l app.kubernetes.io/name=myapp + +# Check resources +kubectl get job -n epinio -o jsonpath='{.spec.template.spec.containers[0].resources}' + +# Check nodeSelector +kubectl get job -n epinio -o jsonpath='{.spec.template.spec.nodeSelector}' + +# Check TTL +kubectl get job -n epinio -o jsonpath='{.spec.ttlSecondsAfterFinished}' +``` + +## Server Logs + +Check Epinio server logs for merge warnings and validation messages: + +```bash +kubectl logs -n epinio deployment/epinio-server | grep "staging config override" +``` + +## Backward Compatibility + +This feature is **fully backward compatible**. Existing API calls without `stagingConfig` continue to work unchanged, using only the base ConfigMap configuration. + +## See Also + +- [API reference](../../references/api.md) for the full OpenAPI spec and staging endpoint details diff --git a/docs/references/customization/staging.md b/docs/references/customization/staging.md index 910f9b3633..cf64730045 100644 --- a/docs/references/customization/staging.md +++ b/docs/references/customization/staging.md @@ -9,6 +9,10 @@ keywords: [kubernetes, epinio, application development, buildpacks] This customization interacts with the [customization of staging scripts](staging-scripts.md). ::: +:::info Trigger-time overrides +You can override staging workload configuration (resources, nodeSelector, tolerations, affinity, TTL, storage, and more) at build trigger-time via the staging API, without changing ConfigMap defaults. See [Staging configuration override at trigger time](../../howtos/customization/staging_config_override.md). +::: + By default, Epinio's staging process uses the [jammy full stack paketo builder image](https://github.com/paketo-buildpacks/builder-jammy-full) for Paketo [Cloud Native Buildpacks](https://buildpacks.io/). This converts application sources into deployable application images. From 2bd1b6251f9c5a2c4a8efa109385cef95bfa727f Mon Sep 17 00:00:00 2001 From: David Johnson Date: Wed, 25 Feb 2026 14:56:19 -0500 Subject: [PATCH 2/3] retrigger checks From dd48b179d60cffded8e36ac87f9742a297220cf9 Mon Sep 17 00:00:00 2001 From: David Johnson Date: Thu, 26 Feb 2026 10:50:15 -0500 Subject: [PATCH 3/3] retrigger build