Docs

Kubernetes

A customer running Kubernetes installs your application with one helm install. The chart runs the Operator, which connects outbound to your manager over HTTPS and deploys each release in the customer's namespace. Nothing in the cluster accepts inbound connections from you.

Define the application

Target the kubernetes platform. Resources that hold the customer's data, such as storage, map to infrastructure the customer already runs, supplied at install time.

alien.ts
import * as alien from "@alienplatform/core"

const bucket = new alien.Storage("bucket").build()

const api = new alien.Container("api")
  .code({ type: "image", image: "ghcr.io/acme/api:latest" })
  .cpu(0.5)
  .memory("512Mi")
  .tunnel(8080)
  .link(bucket)
  .permissions("api")
  .build()

export default new alien.Stack("files")
  .platforms(["kubernetes"])
  .add(bucket, "frozen")
  .add(api, "live")
  .permissions({ profiles: { api: { bucket: ["storage/data-read", "storage/data-write"] } } })
  .build()

Then publish a release. Images go to your manager; you don't need a registry customers can reach.

alien release

Onboard a customer

alien onboard acme --platforms kubernetes

onboard prints a token for this customer and the commands to send to their Kubernetes admin. The commands read the token once and pipe it to Helm, so it stays out of shell history and process arguments:

read -rs ALIEN_TOKEN  # paste acme's token, then Enter
printf '%s' "$ALIEN_TOKEN" | helm registry login manager.example.com --username acme --password-stdin

printf 'management:\n  token: %s\n' "$ALIEN_TOKEN" | \
helm install files oci://manager.example.com/charts/files \
  --namespace files --create-namespace \
  --set management.name=acme \
  --values values.yaml \
  --values -

Send the token separately from the commands.

The chart comes from your manager's OCI registry and is already wired to it. Each release gets a new chart version, so helm pull oci://manager.example.com/charts/files gives a customer a .tgz to review or mirror.

Connect the customer's infrastructure

values.yaml maps each infrastructure resource to what the cluster already has. For storage, that's an S3 bucket or any S3-compatible store:

values.yaml
infrastructure:
  bucket:
    type: storage
    service: s3
    bucketName: acme-files
    # S3-compatible stores (MinIO, Ceph, ...). Omit these three for Amazon S3
    # with the pod's AWS identity (IRSA or EKS Pod Identity).
    endpoint: https://minio.acme.internal
    accessKeyId: ...
    secretAccessKey: ...

Key-value stores map to Redis (service: redis, connectionUrl). To keep credentials out of values files, store the infrastructure map as JSON under the key external-bindings.json in a Secret, and set infrastructureExistingSecret to its name.

After the install

The deployment appears in alien deployments ls once the Operator registers. From then on:

  • Releases. Every alien release reaches the deployments following its channel (production unless you choose another) on the Operator's next sync, about every 30 seconds. Use channels for staged rollouts and pins to hold a customer on one release; see Releases.
  • The Operator. It updates itself to the Operator version your manager serves, so customers don't run helm upgrade for Alien updates. Set runtime.image.selfUpdate=false to require an upgrade instead.
  • Images. Pods pull through your manager with the deployment's token. The chart creates the pull secret.
  • Logs and traces. The Operator collects container logs and your containers' OpenTelemetry, and sends them to the manager, which forwards them to your backend. See Observability.
  • Requests. Your backend calls containers that declare .tunnel(port) through the manager (on self-hosted managers for now). See Tunnels.
  • Commands. Remote commands reach the deployment the same way.

Chart values

ValueDescription
management.tokenThe customer's token from alien onboard
management.existingSecretRead the token from a Secret instead
management.nameDeployment name, shown in alien deployments ls
infrastructureResources the application uses, mapped to the cluster's infrastructure
infrastructureExistingSecretThe same, from a Secret
runtime.image.selfUpdateFollow the Operator version the manager serves (default true)
runtime.image.pullWithManagementTokenPull the Operator image through the manager (default true)
tunnel.enabledAccept tunnel requests from the manager (default true)
logCollector.enabledCollect container logs (default true)
airgapped.enabledTake releases from bundles instead of the manager. See Air-gapped deployments.

helm show values oci://manager.example.com/charts/files lists the rest: resources, scheduling, network policy, security context.

Change values

helm upgrade files oci://manager.example.com/charts/files \
  --namespace files --reset-then-reuse-values --values values.yaml

--reset-then-reuse-values (Helm 3.14 or later) keeps the install's values and takes new defaults from the chart. --reuse-values would keep the old defaults too.

Uninstall

helm uninstall files --namespace files

A cleanup job removes the workloads the Operator created. Persistent volume claims stay unless runtime.cleanup.onUninstall.deletePersistentVolumeClaims=true, and infrastructure mapped in values.yaml, like the bucket, is never touched.

Requirements

  • Helm 3.8 or later (OCI charts)
  • Outbound HTTPS from the cluster to your manager

On this page