KUBERNETES → STACKIT SKE · CROSS-CLOUD GUIDE

Kubernetes migration to STACKIT SKE, from any of six clouds

Your manifests are portable; everything the cloud wrapped around them is not. Whatever the source (EKS, AKS, GKE, CCE, ACK or OKE), StackToIT classes the cluster as REPLATFORM. For EKS, AKS and GKE it writes an SKE cluster with its node pools and lists each cloud-specific setting it does not carry; for CCE, ACK and OKE it records the mapping in the assessment. This guide shows the output side by side.

EKS: a cluster and a node group become one SKE cluster

A small estate written for this guide, assessed by StackToIT on 4 November 2026. Left: the EKS cluster and its node group. Right: the stackit_ske_cluster block of the STACKIT Terraform the engine wrote, review comments left out.

Example inputmain.tf
resource "aws_eks_cluster" "platform" {
  name     = "platform"
  version  = "1.31"
  role_arn = aws_iam_role.cluster.arn

  vpc_config {
    subnet_ids = [aws_subnet.private_a.id, aws_subnet.private_b.id]
  }
}

resource "aws_eks_node_group" "workloads" {
  cluster_name    = aws_eks_cluster.platform.name
  node_group_name = "workloads"
  node_role_arn   = aws_iam_role.nodes.arn
  subnet_ids      = [aws_subnet.private_a.id, aws_subnet.private_b.id]
  instance_types  = ["m6i.xlarge"]

  scaling_config {
    desired_size = 3
    min_size     = 2
    max_size     = 6
  }
}
STACKIT Terraform by StackToITterraform/kubernetes.tf
resource "stackit_ske_cluster" "platform" {
  project_id = var.project_id
  name       = "platform"
  node_pools = [{
    name               = "workloads"
    machine_type       = var.pool_workloads_machine_type
    minimum            = 2
    maximum            = 6
    availability_zones = var.availability_zones
  }]
  kubernetes_version_min = "1.36"
}
  • Node groups become node pools

    The node group is not a separate resource on STACKIT: it is a node pool inside the cluster block. Minimum and maximum carry over; desired_size does not, because an SKE pool scales between its bounds and has no desired size.

  • The machine type is derived, not copied

    m6i.xlarge has 4 vCPU and 16 GiB. The draft points the pool at a variable whose default is the STACKIT machine type the run proposes for that size, and keeps the choice as an open decision for you to confirm or change.

  • The version moves up

    The source runs Kubernetes 1.31. The eu01 catalogue the run read starts at 1.35, but its lifecycle data marks 1.36 as the lowest supported version at or above the source, so the run sets kubernetes_version_min to 1.36 and warns that five minor versions of upgrade sit between the two: check removed APIs before the move.

  • Roles and subnets are dropped, by name

    The cluster IAM role, the node role and the control-plane subnets have no SKE counterpart. Each one is listed as not carried in the file, with the question it leaves: what the node credentials were used for, and which network the cluster joins.

GKE: protection, scaling and identity read differently

The same exercise for a Google Kubernetes Engine cluster and its node pool. Left: the input. Right: the SKE block.

Example inputmain.tf
resource "google_container_cluster" "platform" {
  name                     = "platform"
  location                 = "europe-west3"
  network                  = google_compute_network.platform.id
  subnetwork               = google_compute_subnetwork.gke.id
  min_master_version       = "1.32"
  remove_default_node_pool = true
  initial_node_count       = 1
  deletion_protection      = true

  release_channel {
    channel = "REGULAR"
  }

  workload_identity_config {
    workload_pool = "shop-platform-prod.svc.id.goog"
  }
}

resource "google_container_node_pool" "general" {
  name     = "general"
  cluster  = google_container_cluster.platform.id
  location = "europe-west3"

  autoscaling {
    min_node_count = 1
    max_node_count = 5
  }

  node_config {
    machine_type    = "e2-standard-8"
    disk_size_gb    = 100
    service_account = google_service_account.nodes.email
    oauth_scopes    = ["https://www.googleapis.com/auth/cloud-platform"]
  }
}
STACKIT Terraform by StackToITterraform/kubernetes.tf
resource "stackit_ske_cluster" "platform" {
  project_id = var.project_id
  name       = "platform"
  node_pools = [{
    name               = "general"
    machine_type       = var.general_machine_type
    minimum            = var.platform_general_minimum
    maximum            = var.platform_general_maximum
    availability_zones = var.availability_zones
  }]
  kubernetes_version_min = "1.36"
  lifecycle {
    prevent_destroy = true
  }
}
  • Deletion protection stays

    deletion_protection = true is carried as a Terraform guard, lifecycle prevent_destroy, so a destroy is refused as it was before.

  • Scaling counts change meaning

    GKE autoscaling limits count nodes per zone; SKE minimum and maximum count the whole pool. The run copies no value as an equivalent and leaves a note to set the pool totals.

  • Workload Identity does not carry

    The Google workload pool has no counterpart. Workloads federate through a STACKIT service-account identity provider that uses the cluster issuer, which the run flags as a finding and does not generate. Release channels are dropped too: SKE has no channels, and automatic version updates are a maintenance setting.

CCE, ACK and OKE: the cluster is assessed, the details are yours

For Huawei Cloud, Alibaba Cloud and Oracle Cloud sources this build writes no STACKIT resource blocks; it records the decision. These are the cluster units as assessment.json records them (id, class, confidence and target).

StackToIT assessmentassessment.json
{
  "id": "huaweicloud_cce_cluster.platform",
  "result": {
    "class": "REPLATFORM",
    "confidence": "MEDIUM",
    "target": {
      "service": "STACKIT Kubernetes Engine (SKE)",
      "resources": [
        "stackit_ske_cluster",
        "stackit_ske_kubeconfig"
      ]
    }
  }
}
{
  "id": "alicloud_cs_managed_kubernetes.platform",
  "result": {
    "class": "REPLATFORM",
    "confidence": "MEDIUM",
    "target": {
      "service": "STACKIT Kubernetes Engine (SKE)",
      "resources": [
        "stackit_ske_cluster",
        "stackit_ske_kubeconfig"
      ]
    }
  }
}
{
  "id": "oci_containerengine_cluster.platform",
  "result": {
    "class": "REPLATFORM",
    "confidence": "MEDIUM",
    "target": {
      "service": "STACKIT Kubernetes Engine (SKE)",
      "resources": [
        "stackit_ske_cluster",
        "stackit_ske_kubeconfig"
      ]
    }
  }
}
  • Same class, same target

    All three clusters are classed REPLATFORM with MEDIUM confidence and target STACKIT Kubernetes Engine. Workload manifests can stay; node pools, load balancer and storage annotations and identity are replaced, and so are add-ons (for OKE the run names images instead).

  • Node pools are uneven

    In these demo runs the OKE node pool is classed REPLATFORM, while the CCE and ACK node pools are MANUAL_REVIEW with LOW confidence: this build does not recognise their resource types, so nothing of them is assessed or drafted. They show up as work for an architect rather than as silent gaps.

What each source changes

Source clusterWhat the run found to changeOutput of the run
Amazon EKSNode groups become node pools; desired size and cluster roles are not carried; version raised to 1.36SKE cluster block in Terraform
Azure AKSSystem and user pools become two SKE pools; managed identity, DNS prefix and network plugin settings are not carried; the API server address changesSKE cluster block with two node pools
Google GKEPer-zone scaling limits become pool totals; Workload Identity and release channel are not carriedSKE cluster block with a destroy guard
Huawei CCECluster mapped; node pool held for an architectAssessment entry, no Terraform
Alibaba ACKCluster mapped; node pool held for an architectAssessment entry, no Terraform
Oracle OKECluster and node pool mapped; the shape becomes a STACKIT flavor; zone placement decided againAssessment entry, no Terraform

From the six demo runs of this guide set. The AKS cluster name is shortened because an SKE cluster name has 1 to 11 characters; the run chose aks-2a0320 and asks you to set the name you want.

The migration, in order

The steps below are general practice; the run supplies the first two and the lists that feed the rest.

  1. 1 · Assess the infrastructure code

    Run the engine on the Terraform or OpenTofu that defines the clusters. It names every cloud-specific setting, so the list of things to change exists before anyone writes a line.

  2. 2 · Decide networking and identity first

    Cluster placement, API access and how workloads authenticate are the questions the drafts leave open on every source. Settle them before node sizes.

  3. 3 · Scan manifests and charts

    Look for load balancer and ingress annotations, storage classes, service-account annotations for cloud identity and controllers that only exist on the source cloud. These are the parts that do not move with the manifests.

  4. 4 · Build the SKE cluster in a test project

    Apply the drafted cluster after the variables are filled in, then deploy the workloads stateless first.

  5. 5 · Move persistent volumes

    The run suggests a backup tool such as Velero for volume data; the data itself is never moved by the engine. Pick the method from size, change rate and tolerated downtime.

  6. 6 · Cut over by traffic

    Shift DNS or the load balancer in front one entry point at a time, keep the source cluster until checks pass, then retire it.

What the source clouds have in common

  • A managed control plane

    AKS, GKE and EKS all operate the control plane for you, and SKE does too, so the API server address and credentials change but the operating model stays familiar.

  • Automatic or standard modes

    EKS offers Auto Mode, AKS offers Automatic and Standard, GKE offers Autopilot and Standard. Auto-managed node features are provider behaviour; check whether workloads depend on them.

  • Cloud-bound add-ons

    Network plugins, storage drivers, ingress controllers and identity integrations come from the source cloud and are replaced by SKE equivalents.

  • Versions

    In these runs the SKE catalogue for eu01 starts at 1.35 and every draft asks for 1.36, so the 1.31 and 1.32 source clusters are upgraded on the way. Check removed Kubernetes APIs against your manifests first.

Questions platform teams ask

Do I need to rewrite my Kubernetes manifests?

Not for the Kubernetes objects themselves. The edits are in cloud-specific annotations, storage classes, ingress classes and identity configuration, which the run lists as items to review.

Does StackToIT move my workloads or volumes?

No. It reads infrastructure code and writes a plan, Terraform where supported, and manual steps. Moving data is done by you with your chosen tooling.

Why does the run not write Terraform for CCE, ACK or OKE?

On this build the Huawei, Alibaba and Oracle runs write assessments and decisions but no STACKIT resource blocks. The cluster mapping is still recorded, so the work can be planned.

Which STACKIT features does a cluster get?

The SKE documentation lists a highly available managed control plane, automatic Kubernetes and OS updates, pod and node autoscaling, and management through the portal, Terraform, the API or the CLI.

Sources

Your next move: STACKIT.

Tell us about your estate. We show you what StackToIT delivers for it: target architecture, Terraform artifacts and a structured migration plan.