Skip to content

Deploy an app

An App is a container image with a URL. Apply one and, by default, you get a Knative Service that scales to zero when idle and back up on the first request, with TLS on its URL from the start.

apiVersion: paas.paasbox.com/v1alpha1
kind: App
metadata: { name: shop, namespace: shop }
spec:
image: registry.example.com/acme/shop:1.4.2
port: 8000
env:
- { name: DJANGO_SETTINGS_MODULE, value: config.production }
uses: [{ name: db, kind: ManagedPostgres, prefix: DB_ }]
scale: { min: 0, max: 5, target: 100 }
resources: { plan: s }
status:
conditions: [Reconciled, Ready, Degraded, RoutesReady]
phase: Ready
url: https://shop.shop.apps.acme.paasbox.app

kubectl apply -f app.yaml is enough; pb app deploy shop --image registry.example.com/acme/shop:1.4.3 --wait is the shortcut for the one thing you do most often, bumping the image, and it waits for the new revision and prints the URL.

  • image — the only way to get code onto the cluster today: your CI builds and pushes it. A build step that turns a source checkout into an image is planned, so this will become optional later.
  • command / args — override the image’s entrypoint, plain Kubernetes semantics.
  • port — the port your process listens on. Default 8080.
  • env — a list of Kubernetes EnvVar entries, passed through as written, including valueFrom.secretKeyRef for your own secrets. A web app additionally receives PAAS_APP_NAME, PAAS_APP_HOST and PAAS_APP_URL (its own default URL) automatically, for ALLOWED_HOSTS and CSRF origin settings.
  • envFrom — load a whole Secret or ConfigMap as environment: your twelve-factor .env, SECRET_KEY and the rest, as one Secret you manage.
  • uses — dependencies. See databases and caches for what each kind injects.
  • scalemin (0 by default: scale-to-zero), max (5 by default) and target, the per-instance concurrency the autoscaler aims for (100 by default). min ≥ 1 keeps at least one instance warm, at the cost of paying for it while idle.
  • resources — a plan name (xs, s, m or l, a row of cpu/memory) or explicit requests/limits. Absent means plan s.
  • suspendedtrue stops serving and removes the public route while keeping everything else (the object, its revisions, its dependencies): the equivalent of “off, not gone”.
  • traffic — a Knative-style split across revisions (revision, percent, an optional tag for its own URL), for blue/green rollouts. Absent means 100% to the latest ready revision. Editing this by hand with kubectl works today; a pb app promote shortcut is planned.

The default type: web renders a Knative Service with a URL. type: worker renders a plain Deployment with a fixed replica count (scale.min, no scale-to-zero) and no port, no route: a Celery worker, a queue consumer, anything that only needs to run, not to answer HTTP.

apiVersion: paas.paasbox.com/v1alpha1
kind: App
metadata: { name: shop-worker, namespace: shop }
spec:
type: worker
image: registry.example.com/acme/shop:1.4.2
command: [celery]
args: [-A, project, worker, -l, INFO]
uses: [{ name: broker, kind: ManagedValkey, prefix: REDIS_ }]
scale: { min: 2 }

spec.release runs a command as a Job, with the app’s image and environment, before a new image reaches the Service or Deployment — a Django migrate --noinput, for example. The Job must succeed for the new image to roll out; while it runs, or if it fails, the previous image keeps serving.

spec:
release:
command: [python, manage.py]
args: [migrate, --noinput]
timeoutSeconds: 300

status.release reports the release Job’s name, phase (Running, Succeeded, Failed) and which image last succeeded — the image that is allowed to serve while a newer release is still running.

  • Reconciled — the current spec was rendered into the Service or Deployment.
  • Ready — computed from the real state, not just the object’s own status: a Knative Ready=True with zero pods is correct for scale.min: 0, and only counts as serving once an actual pod is available when scale.min ≥ 1.
  • Degraded — it works, but a promise is broken.
  • RoutesReady — a web app only: the route is programmed and the URL answers.
  • Released — present when spec.release is set: whether the release Job for the current image has succeeded.

status.effective reports the defaults the controller actually applied (port, scale, plan, resources) without ever writing them back into spec, so your applied YAML never drifts from what you wrote.

If you edit the Knative Service or Deployment that an App owns, the controller reverts it on the next reconcile and records an Event so you can see it happened. Change the App instead. If you want to manage a workload’s underlying object yourself, do not put an App in front of it at all — see both ways.