Skip to content

How to modify stack templates with config overrides ​

Prerequisites

  • You have a working stack created with Stack.fromTemplate
  • You can run kubricate generate successfully
  • You understand basic Kubernetes resource structure

Override service configuration ​

To change service settings that the template doesn't expose as inputs:

ts
// src/stacks.ts
import { simpleAppTemplate } from '@kubricate/stacks'
import { Stack } from 'kubricate'

const webApp = Stack.fromTemplate(simpleAppTemplate, {
  name: 'web-app',
  imageName: 'nginx',
  namespace: 'frontend'
})
.override({
  service: {
    spec: {
      type: 'LoadBalancer'
    }
  }
})

Result: Your service becomes a LoadBalancer instead of the template's default ClusterIP.

Add resource limits to containers ​

To add memory and CPU constraints that the template doesn't provide:

ts
const apiServer = Stack.fromTemplate(simpleAppTemplate, {
  name: 'api-server',
  imageName: 'api',
  namespace: 'backend'
})
.override({
  deployment: {
    spec: {
      template: {
        spec: {
          containers: [{
            name: 'api-server',         // Must match template's data.name
            image: 'api:latest',        // Must match template's imageName
            resources: {
              requests: {
                memory: '128Mi',
                cpu: '50m'
              },
              limits: {
                memory: '256Mi',
                cpu: '100m'
              }
            }
          }]
        }
      }
    }
  }
})

Result: Your deployment now has resource requests and limits applied to the container.

Handle array replacement behavior ​

Important: When you override an array, you completely replace it. Include all required fields:

ts
// ❌ This BREAKS - incomplete container definition
.override({
  deployment: {
    spec: {
      template: {
        spec: {
          containers: [{
            resources: { limits: { memory: '512Mi' } }
            // Missing required: name, image!
          }]
        }
      }
    }
  }
})

// ✅ Include ALL required container fields
.override({
  deployment: {
    spec: {
      template: {
        spec: {
          containers: [{
            name: 'my-app',                    // Required: matches template
            image: 'my-app:latest',            // Required: matches template
            resources: {
              limits: { memory: '512Mi', cpu: '200m' }
            }
          }]
        }
      }
    }
  }
})

Result: Your container gets resource limits while maintaining all required fields.

Override multiple resources ​

To modify both deployment and service in one override:

ts
const multiOverrideApp = Stack.fromTemplate(simpleAppTemplate, {
  name: 'multi-override-app',
  imageName: 'app',
  namespace: 'production'
})
.override({
  deployment: {
    spec: {
      replicas: 5,
      template: {
        spec: {
          containers: [{
            name: 'multi-override-app',  // Must match template's data.name
            image: 'app:latest',         // Must match template's imageName
            env: [
              { name: 'NODE_ENV', value: 'production' },
              { name: 'REPLICAS', value: '5' }
            ]
          }]
        }
      }
    }
  },
  service: {
    spec: {
      type: 'LoadBalancer',
      ports: [{
        port: 80,
        targetPort: 3000,
        protocol: 'TCP'
      }]
    }
  }
})

Result: Your deployment runs 5 replicas with environment variables, and your service is a LoadBalancer.

Debug override issues ​

ProblemCauseFix
Override not appliedWrong resource keyCheck Object.keys(stack.build())
TypeScript errorsInvalid resource structureMatch Kubernetes resource schema
Deployment brokenIncomplete array replacementInclude all required fields in arrays

Check your overrides are working:

ts
// Verify override path exists
const resources = stack.build()
console.log('Generated resources:', JSON.stringify(resources, null, 2))

// Check specific resource structure
console.log('Service spec:', resources.service?.spec)

When to use overrides vs template inputs ​

Use template inputs for:

  • Core configuration (name, image, namespace)
  • Commonly needed customizations
  • Simple, well-defined values

Use overrides for:

  • Environment-specific tweaks
  • Kubernetes-specific configurations not exposed by template
  • One-off modifications that don't warrant template changes

Next Steps ​

Related how-to guides: