Skip to content

Kubernetes Integration

EMB provides native Kubernetes integration, allowing you to run tasks directly on pods in your cluster and manage deployments.

The kubernetes executor runs tasks on pods in your Kubernetes cluster, complementing the local and container (Docker Compose) executors.

tasks:
migrate:
script: npm run migrate
executors:
- kubernetes

Use the kubernetes executor when you need to:

  • Run tasks on a deployed instance of your application
  • Execute database migrations on production/staging environments
  • Debug issues in a running cluster
  • Run one-off commands without local setup
tasks:
db-migrate:
description: Run database migrations on the cluster
executors:
- kubernetes
script: npm run migrate
console:
description: Open Rails console on production
interactive: true
executors:
- kubernetes
script: rails console

Use the --executor flag to run tasks on Kubernetes:

Terminal window
# Run migration on the cluster
emb run db-migrate --executor kubernetes

Configure Kubernetes defaults in your .emb.yml:

defaults:
kubernetes:
namespace: staging # Default namespace
selectorLabel: app.kubernetes.io/component # Label for pod selection (default)

Override settings per component:

api/Embfile.yml
kubernetes:
selector: app=api,tier=backend # Custom label selector
container: main # For multi-container pods
OptionDescriptionDefault
namespaceDefault Kubernetes namespacedefault
selectorLabelLabel name used to find component podsapp.kubernetes.io/component
OptionDescription
selectorCustom label selector (e.g., app=api,env=prod)
containerContainer name for multi-container pods

EMB resolves the namespace in this order of precedence:

  1. CLI flag: -n, --namespace
  2. Environment variable: K8S_NAMESPACE
  3. Configuration: defaults.kubernetes.namespace
  4. Default: default
Terminal window
# The --namespace flag wins over everything else
emb kubernetes logs api --namespace production
# Set environment variable
export K8S_NAMESPACE=production
emb run migrate --executor kubernetes
# Or configure in .emb.yml
# defaults:
# kubernetes:
# namespace: production

By default, EMB finds pods using the label app.kubernetes.io/component={component-name}:

Terminal window
# For component "api", EMB looks for pods with:
# app.kubernetes.io/component=api

If your pods use different labels, configure a custom selector:

# Component with custom selector
kubernetes:
selector: app=my-api,environment=production

To change the default label name project-wide:

.emb.yml
defaults:
kubernetes:
selectorLabel: app # Now uses: app={component-name}

For pods with multiple containers (sidecars, init containers, etc.), specify which container to use:

worker/Embfile.yml
kubernetes:
container: main # Execute in the 'main' container, not the sidecar

If not specified and the pod has multiple containers, EMB will error with a helpful message listing available containers.

EMB provides commands for interacting with your Kubernetes deployments:

Open a shell in a running pod:

Terminal window
emb kubernetes shell <COMPONENT> [OPTIONS]

Options:

  • -n, --namespace <name> - Target namespace
  • -s, --shell <shell> - Shell to use (default: bash; pass --shell sh for images without bash)

Examples:

Terminal window
emb kubernetes shell api
emb kubernetes shell api --namespace production
emb kubernetes shell api --shell sh

View logs from pods:

Terminal window
emb kubernetes logs <COMPONENT> [OPTIONS]

Options:

  • -n, --namespace <name> - Target namespace
  • -f, --follow / --no-follow - Follow log output (default: follow). The last 50 lines are always shown.

Examples:

Terminal window
emb kubernetes logs api
emb kubernetes logs api --no-follow
emb kubernetes logs api --namespace production

List all pods in the target namespace. This command is namespace-scoped, not component-scoped: it takes no arguments, and any argument you pass is ignored rather than used as a filter.

Terminal window
emb kubernetes ps [OPTIONS]

Options:

  • -n, --namespace <name> - Target namespace
  • --watch / --no-watch - Accepted by the parser but currently has no effect: the pod list is printed once and the command exits

Examples:

Terminal window
emb kubernetes ps
emb kubernetes ps --namespace production

Restart pods of one or more Kubernetes deployments. The arguments are deployment names as they exist in the cluster, not EMB component names. Omit the argument to restart every deployment in the target namespace.

Terminal window
emb kubernetes restart [DEPLOYMENT...] [OPTIONS]

Options:

  • -n, --namespace <name> - Target namespace

Examples:

Terminal window
emb kubernetes restart api worker --namespace production
emb kubernetes restart # Restarts every deployment in the namespace

For tasks requiring user input, mark them as interactive:

tasks:
console:
description: Open application console
interactive: true
executors:
- kubernetes
script: rails console

This ensures:

  • TTY is allocated for the pod exec
  • stdin is connected for interactive input
  • SIGINT (Ctrl+C) is properly handled
.emb.yml
project:
name: myapp
defaults:
kubernetes:
namespace: ${env:K8S_NAMESPACE:-staging}
selectorLabel: app.kubernetes.io/component
components:
api:
kubernetes:
container: app # Multi-container pod
tasks:
migrate:
description: Run database migrations
executors:
- kubernetes
script: npm run db:migrate
console:
description: Open Rails console
interactive: true
executors:
- kubernetes
script: rails console
worker:
kubernetes:
selector: app=worker,tier=background
tasks:
process:
description: Process pending jobs
executors:
- kubernetes
script: npm run jobs:process
Error: No ready pods found for component "api" in namespace "production"

Solutions:

  • Check pod status: kubectl get pods -n production -l app.kubernetes.io/component=api
  • Verify the label selector matches your pod labels
  • Ensure pods are in Ready state
Error: Pod "api-xyz" has multiple containers, explicit container config required

Solution: Add container to your component’s kubernetes config:

kubernetes:
container: main
Error: Container "main" not found in pod "api-xyz"

Solution: Check available containers and update your config:

Terminal window
kubectl get pod api-xyz -o jsonpath='{.spec.containers[*].name}'