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.
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 releaseOnboard a customer
alien onboard acme --platforms kubernetesonboard 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:
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 releasereaches the deployments following its channel (productionunless 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 upgradefor Alien updates. Setruntime.image.selfUpdate=falseto 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
| Value | Description |
|---|---|
management.token | The customer's token from alien onboard |
management.existingSecret | Read the token from a Secret instead |
management.name | Deployment name, shown in alien deployments ls |
infrastructure | Resources the application uses, mapped to the cluster's infrastructure |
infrastructureExistingSecret | The same, from a Secret |
runtime.image.selfUpdate | Follow the Operator version the manager serves (default true) |
runtime.image.pullWithManagementToken | Pull the Operator image through the manager (default true) |
tunnel.enabled | Accept tunnel requests from the manager (default true) |
logCollector.enabled | Collect container logs (default true) |
airgapped.enabled | Take 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 filesA 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