Migrate from Kubernetes to Temps

To move a workload from Kubernetes to Temps, create a read-only ServiceAccount, paste a kubeconfig built around its token into the Temps import wizard, pick the Deployment, StatefulSet or CronJob, review the plan, and execute it. Temps recreates the workload as a Temps project that runs the same image with its environment variables, Ingress hosts and resource limits. Database and persistent-volume data stay in the cluster, so you dump and restore those yourself before switching traffic.


When this makes sense

Kubernetes earns its overhead at fleet scale. A handful of small, simple services running on a full cluster — control plane, etcd, scheduler, all the YAML that comes with it — is a lot of operational surface for workloads that don't need it. If that's your cluster, importing those workloads into Temps trades the cluster's operational overhead for a single binary and a wizard-driven redeploy. If you need more than one server, Temps joins extra worker nodes over your private network instead; see multi-node.


What Temps discovers from a cluster

Discovery lists Deployments, StatefulSets and CronJobs in every non-system namespace. When you import one, its namespace becomes the project boundary:

  • The workload you pick: its primary container's image, ports, command, resource limits and probes.
  • Environment variables from the pod spec and ConfigMaps, with their values. Variables from Secrets come across as key names only: Temps never reads Secret values out of the cluster, so you re-enter them in Temps after the import.
  • Other workloads in the namespace. Workloads running a database image (PostgreSQL, MySQL/MariaDB, MongoDB, Redis) become Temps-managed services; the rest become additional deployments.
  • Ingress hosts, imported as domains.

The imported project runs the discovered container image. There's no build step.


Will my data come across?

No, not automatically. A database in the cluster usually isn't reachable from outside the cluster network, so Temps creates the managed service empty and the plan marks the data as not migrated. For PostgreSQL it gives you the command to run once the Temps service is up:

kubectl exec <postgres-pod> -- pg_dump -U <user> <db> | psql "<temps connection url>"

For MySQL, use mysqldump the same way. Data in PersistentVolumeClaims is not copied either. Temps app containers have no persistent volumes, so move files to object storage such as Temps managed S3 before you cut over.

The plan also lists what has no Temps equivalent:

  • HorizontalPodAutoscalers. Temps doesn't autoscale replicas. Size the environment from measured usage and set replicas yourself; see scaling.
  • Replicas. A workload running several replicas imports as a single container per environment.
  • Sidecar containers. Only the primary container is imported. Service-mesh sidecars aren't needed behind the Temps proxy.
  • fieldRef / resourceFieldRef variables. Values taken from pod introspection are skipped.

Before you start

You need a kubeconfig with either an embedded bearer token or a client certificate.

exec-based authentication (the AWS EKS and Google GKE credential plugins) is not supported — the plugin binary Temps would need to invoke doesn't exist on the Temps server. Mint a ServiceAccount token instead and build a kubeconfig around it.

Discovery lists workloads across the whole cluster, so it needs a small ClusterRole. Reading the namespace you import from needs a Role that can get Secrets: Temps reads them only to learn which keys an envFrom Secret injects, and never copies their values. The built-in view ClusterRole isn't enough, because it excludes Secrets. The nodes, pods and metrics.k8s.io rules feed the plan's cost analysis and can be left out; the import still works without them.

# temps-import-rbac.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: temps-import-discover
rules:
  - apiGroups: ["apps"]
    resources: ["deployments", "statefulsets"]
    verbs: ["list"]
  - apiGroups: ["batch"]
    resources: ["cronjobs"]
    verbs: ["list"]
  # Optional: cost analysis
  - apiGroups: [""]
    resources: ["nodes", "pods"]
    verbs: ["list"]
  - apiGroups: ["metrics.k8s.io"]
    resources: ["nodes"]
    verbs: ["list"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: temps-import
  namespace: your-namespace
rules:
  - apiGroups: [""]
    resources: ["configmaps", "secrets"]
    verbs: ["get"]
  - apiGroups: ["apps"]
    resources: ["deployments", "statefulsets"]
    verbs: ["get", "list"]
  - apiGroups: ["batch"]
    resources: ["cronjobs"]
    verbs: ["get", "list"]
  - apiGroups: ["networking.k8s.io"]
    resources: ["ingresses"]
    verbs: ["list"]
  - apiGroups: ["autoscaling"]
    resources: ["horizontalpodautoscalers"]
    verbs: ["list"]
kubectl apply -f temps-import-rbac.yaml
kubectl create serviceaccount temps-import -n your-namespace
kubectl create clusterrolebinding temps-import-discover --clusterrole=temps-import-discover --serviceaccount=your-namespace:temps-import
kubectl create rolebinding temps-import --role=temps-import --serviceaccount=your-namespace:temps-import -n your-namespace
kubectl create token temps-import -n your-namespace --duration=24h

Embed the resulting token in a kubeconfig alongside your cluster's server URL and certificate-authority-data.

The Temps import wizard's Connect to Kubernetes credentials form, showing the kubeconfig paste textarea

Step 1: Connect and discover

Discover what's running in the cluster

  1. 1

    In the Temps dashboard, go to Projects, then click Import.

  2. 2

    Select Kubernetes as the source.

  3. 3

    Paste the kubeconfig YAML into the credentials textarea.

  4. 4

    Click Discover Workloads.

Temps queries the Kubernetes API server directly — nothing is created on this step.


Step 2: Review the plan

Pick the workload to import and Temps shows the plan it will execute: the project name, the image it will pull, the container's resource limits translated into Temps limits, every environment variable it found (Secret-backed ones redacted), any database it will create as a managed service, and the unsupported items listed above. The repository step is optional; without a linked repository the plan shows the project as image-based (Type: docker).

If the workload depends on a database running in the same cluster, that database usually isn't reachable from outside the cluster network — the plan says so explicitly and gives you the pg_dump / psql commands to move the data by hand instead of silently skipping it.


Step 3: Execute the import

Run the import end to end

  1. 1

    Review the plan and click Execute Import.

  2. 2

    Temps creates the project and its services, pulls the discovered image, and starts the container.

  3. 3

    Wait for the deployment to reach a healthy state — Temps verifies the app actually answers before reporting the import complete.

Your cluster keeps running the whole time — the import only reads from it. Verify the imported app on its Temps-provided address before touching DNS or scaling down the original workload.


After the import

Before you send traffic, re-enter the Secret values the plan lists, and restore your database into the Temps service. Then point DNS for the imported Ingress hosts at the Temps server; Temps issues TLS certificates once the records resolve. To add another domain, use the dashboard or bunx @temps-sdk/cli custom-domains create --project-id <id> -d app.example.com -y, as shown in moving the production domain. Keep the original Deployment or StatefulSet running (scaled down if you want to save resources) until you've verified normal traffic on Temps, then delete the temps-import ServiceAccount and its bindings.

For the general import flow that applies across every supported platform, see Import an Existing Platform.

Last updated

Was this page helpful?