Docs

Kubernetes

A Kubernetes deployment runs your stack as pods in one namespace of your customer's cluster, on-prem or in EKS, GKE, or AKS. The customer's admin sets it up once with Helm, and every release after that arrives over outbound HTTPS: nobody runs helm upgrade, and nothing in the cluster accepts inbound connections.

Architecture diagram. Customer cluster (Operator, Your pods) connects outbound to the Alien manager (Releases, Images, Charts), via https 443, outbound.

The Operator pulls releases; nothing connects into the cluster

The Helm chart runs the Operator, a small service that connects out to Alien's manager (the service that holds your releases and deployments) and deploys each release into the namespace. This is pull: a component inside the environment fetches releases, instead of Alien calling in.

A deployment's life has two parts:

  • Initial setup: the one-time step the admin runs with their own cluster credentials, using Helm, or Terraform or CloudFormation to create a managed cluster first.
  • Ongoing management: everything after. The Operator applies each release, sends logs, and runs commands, without the admin.

How the admin reaches initial setup is your Deployment UX choice: a link you send, a Deploy button in your product, or your own setup screen. What happens in the cluster is the same either way, and this guide follows it from requirements to removal.

What the customer needs

  • A cluster, or a cloud account to create one in: EKS on AWS, GKE on Google Cloud, or AKS on Azure.
  • Helm 3.8 or later (OCI charts). --reset-then-reuse-values needs Helm 3.14.
  • Rights to install the chart into its namespace. Turning on the Remote Operator adds a custom resource definition, which may need cluster-admin approval.
  • Outbound HTTPS from the cluster to Alien. Nothing needs to reach into the cluster.
  • The infrastructure your frozen resources map to, such as an S3 bucket. See Connect the customer's infrastructure.

Your stack

Target the kubernetes platform. On other platforms, initial setup creates the frozen resources, the ones that hold the customer's data, like a bucket. On Kubernetes, each frozen resource maps to infrastructure the customer already runs, and the admin supplies it during initial setup.

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

// Maps to a bucket the customer already runs, supplied at initial setup.
const files = new alien.Storage("files").build()

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

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

Publish a release with alien release.

Set up

The Helm chart, Terraform modules, and CloudFormation template are setup packages, which Alien builds from your release. The deployment portal, the branded setup page Alien hosts for the admin, hands out the right one.

Setting up on an existing Kubernetes cluster with Helm: the values.yaml to keep and the helm install command.
The Helm method in the deployment portal: the values.yaml to keep and the helm install command.

To create a setup link that offers only Kubernetes:

alien onboard customer-2 --platforms kubernetes

In the portal, the admin reaches Kubernetes from On-Prem or from a cloud:

  • On-Prem, then Compute → Kubernetes: deploy into a cluster they operate, with Helm.
  • AWS, Google Cloud, or Azure, then Compute → Amazon EKS, Google Kubernetes Engine, or Azure Kubernetes Service, and a Cluster source: create a new cluster or use an existing one.

Helm on an existing cluster

  1. Prepare values: save the generated values.yaml. It holds the deployment's token and name. Keep it for later upgrades.
  2. Install chart: set the Kubernetes namespace and run the command from a shell with the target cluster's context.
helm install acme-files <chart-from-portal> \
  --namespace acme-files --create-namespace \
  --values values.yaml

The portal fills in the chart reference and namespace. The Operator starts, registers the deployment, fetches the release, and deploys it. The deployment shows Running in a minute or two.

New EKS, GKE, or AKS cluster

A new EKS cluster is set up with CloudFormation (the default) or Terraform. A new GKE or AKS cluster is set up with Terraform.

  • With Install chart automatically (Terraform only), terraform apply creates the cluster and installs the chart.
  • With Install chart separately, or after the CloudFormation stack registers, the portal shows Connect your cluster: save values.yaml, then install the chart with kubectl pointed at the new cluster.

Existing EKS, GKE, or AKS cluster

Terraform only. The admin sets the cluster in the generated main.tf (eks_cluster_name, gke_cluster_name and gke_cluster_location, or aks_cluster_name and aks_cluster_resource_group_name), then runs terraform init && terraform apply with TF_VAR_token set.

What initial setup creates

  • The Operator, in the deployment's namespace, registered with Alien under the token in values.yaml.
  • Your workloads, which the Operator creates in that namespace from the release.
  • A new cluster, only when the admin chose to create one with Terraform or CloudFormation.

Frozen resources aren't created: they map to the customer's infrastructure. See Connect the customer's infrastructure.

Chart versions

Each release gets a new chart version. Alien serves the images and the chart, so you don't need a registry that customers can reach.

Connect the customer's infrastructure

The infrastructure map in the values file binds each frozen resource to something the cluster already has. For storage, that is S3 or any S3-compatible store:

values.yaml
infrastructure:
  files:
    type: storage
    service: s3
    bucketName: customer-2-files
    # For S3-compatible stores (MinIO, Ceph). Omit these three for Amazon S3
    # with the pod's own AWS identity.
    endpoint: https://minio.customer-2.internal
    accessKeyId: <access-key-id>
    secretAccessKey: <secret-access-key>

To keep credentials out of values files, store the map as JSON under the key external-bindings.json in a Kubernetes Secret, and set infrastructureExistingSecret to the Secret's name.

How updates arrive

Ongoing management on Kubernetes uses pull: the Operator connects out to Alien and applies what it finds on the deployment's release channel. Nobody runs helm upgrade for a release. See Push, pull, and air-gapped.

  • Releases. Every alien release on the deployment's channel reaches the cluster on the Operator's next sync, about every 30 seconds. Use channels and pins to stage rollouts. See Releases.
  • The Operator. It updates itself to the version Alien serves. Set runtime.image.selfUpdate=false to require a helm upgrade instead.
  • Images. Pods pull through Alien with the deployment's token. The cluster needs no credentials for your registry.
  • Logs. The Operator collects your containers' logs and OpenTelemetry data and sends them out over the same connection.
  • Commands. Commands reach your containers through the Operator.
  • Requests. Your backend can call HTTP ports that a container declares with .tunnel(port). See Tunnels.
  • Changes that need initial setup again. A release that needs a new frozen resource or permission can't be applied by a helm upgrade. The portal tells the admin to keep the current release and contact you, so keep such changes out of releases for Helm installs.
  • Remote Operator. The chart can also run the Remote Operator for operations and access requests. It's off by default. Turning it on may need cluster-admin approval, because it adds a custom resource definition for access requests.

Tunnels

A tunnel lets your backend call an HTTP service inside the customer's cluster without anything opening inbound. The Operator holds an outbound WebSocket connection to the manager. Requests you send to the manager travel over it to the container.

Architecture diagram. Left: Your side, Your backend, Manager. Right: Customer cluster containing Operator; api :8080.

The Operator opens the connection. Your backend reaches port 8080 through the manager, and nothing is exposed on the customer's network.

Declare the port your backend may reach. Only declared ports are reachable, and nothing is exposed on the customer's network:

alien.ts
const api = new alien.Container("api")
  .code({ type: "image", image: "ghcr.io/acme/api:1.4.0" })
  .port(8080)
  .tunnel(8080)
  .build()

Create a token that can call tunnels and nothing else, then call the container:

alien tokens create --tunnel                         # every deployment
alien tokens create --tunnel --customer customer-2   # one customer's deployments

curl "https://<manager-host>/v1/deployments/customer-2/tunnels/api/objects?prefix=reports/" \
  -H "Proxy-Authorization: Bearer ax_tunnel_..." \
  -H "Authorization: Bearer <your application's own token>"
  • The path is /v1/deployments/{deployment}/tunnels/{container}/{path}. {deployment} is the deployment's ID, or its name when that is unique. Everything after the container name, including the query string, is the path the container receives.
  • Proxy-Authorization authenticates you to the manager, which removes it before forwarding. Authorization and other end-to-end headers reach the container unchanged, so your application keeps its own authentication.
  • The container sees X-Forwarded-Proto and X-Forwarded-Host for the manager's public URL.
  • Bodies stream in both directions with flow control, and many requests share one connection. Tunnels carry HTTP requests only: WebSocket upgrades and raw TCP are not forwarded.
  • A tunnel token can't read releases, deployments, or logs. alien tokens revoke <id> takes effect on the next request.

Tunnels are served by a manager you run with alien serve or the alien-manager image.

Errors from the tunnel itself, rather than from your container, carry an alien-tunnel-error header:

StatusCodeMeaning
401Missing or invalid Proxy-Authorization
403The token can't call this deployment's tunnels
404TUNNEL_TARGET_NOT_FOUNDThe container declares no tunnel
502TUNNEL_UPSTREAM_UNAVAILABLEThe container didn't answer
502TUNNEL_REQUEST_FAILEDThe connection to the Operator broke mid-request
503TUNNEL_NOT_CONNECTEDThe deployment's Operator isn't connected, or initial setup set tunnel.enabled=false

The Operator reconnects on its own after network interruptions and manager restarts.

If a proxy or load balancer sits in front of the manager, allow WebSocket upgrades on /v1/tunnel/connect. Set idle timeouts well above 20 seconds, the interval of the tunnel's keepalive pings.

Remove it

Delete the deployment from your side: Delete deployment, or alien deployments delete customer-2/customer-2. The deployment then shows Teardown required until the admin uninstalls the chart:

helm uninstall acme-files --namespace acme-files

A cleanup job removes the workloads the Operator created.

  • Persistent volume claims stay unless runtime.cleanup.onUninstall.deletePersistentVolumeClaims=true.
  • Infrastructure mapped in values.yaml, like the bucket, is never touched.
  • A cluster that initial setup created with Terraform is removed with terraform destroy.

Chart values

ValueDescription
management.tokenThe deployment's token from the portal
management.existingSecretRead the token from a Secret instead
management.nameDeployment name shown in the dashboard
infrastructureFrozen resources mapped to the cluster's infrastructure
infrastructureExistingSecretThe same map, from a Secret
runtime.image.selfUpdateFollow the Operator version Alien serves. Default true.
logCollector.enabledCollect container logs. Default false. Set logCollector.mode to podApi (reads selected Pod logs through the Kubernetes API, no DaemonSet) or nodeAgent (a Fluent Bit DaemonSet).
tunnel.enabledAccept tunnel requests from the manager. Default true.
airgapped.enabledTake releases from sync bundles instead. See Air-gapped.

helm show values <chart> lists the rest, including resources, scheduling, network policy, and security context.

To change values later:

helm upgrade acme-files <chart-from-portal> \
  --namespace acme-files --reset-then-reuse-values --values values.yaml

Next

On this page