Migrating from a public cloud to Managed Service for Kubernetes
This guide explains how to migrate Kubernetes workloads from a managed service of another cloud provider to Managed Service for Kubernetes.
The key strategy is to migrate step by step while keeping both the source and target clusters running in parallel. This minimizes the impact on production services and ensures a safe rollback path.
To migrate workloads to Managed Service for Kubernetes:
- Develop a migration plan.
- Set up your Yandex Cloud infrastructure.
- Migrate container images.
- Migrate stateful workloads.
- Migrate stateless workloads.
- Configure the load balancers and update your DNS records.
- Complete your migration.
Required paid resources
- Managed Service for Kubernetes master (see Managed Service for Kubernetes pricing).
- Managed Service for Kubernetes cluster nodes: use of computing resources and storage (see Yandex Compute Cloud pricing).
- Public IP addresses for the Managed Service for Kubernetes cluster's master and nodes with public access enabled (see Yandex Virtual Private Cloud pricing).
- Each active L7 load balancer, if using the Gwin controller: use of computing resources (see Application Load Balancer pricing).
- Each network load balancer, if using the
LoadBalancerservice type: incoming and outgoing traffic processed by the load balancer (see Yandex Network Load Balancer pricing). - Container Registry: storage of migrated Docker images (see Container Registry pricing).
- Object Storage bucket: use of storage, data operations (see Yandex Object Storage pricing).
- Data Transfer transfers, if migrating managed databases (see Yandex Data Transfer pricing).
Getting started
Sign up for Yandex Cloud and create a billing account:
- Navigate to the management console
and log in to Yandex Cloud or create a new account. - On the Yandex Cloud Billing
page, make sure you have a billing account linked and it has theACTIVEorTRIAL_ACTIVEstatus. If you do not have a billing account, create one and link a cloud to it.
If you have an active billing account, you can create or select a folder for your infrastructure on the cloud page
Learn more about clouds and folders here.
Develop a migration plan
Before the migration, make sure to inventory your workloads and assess the compatibility between the source and target clusters. This helps you estimate migration complexity, map out the order in which to migrate your services, and develop a rollback plan in case of critical issues.
Inventory your workloads
Get a list of source cluster resources for all namespaces: applications, versions, dependencies, and network rules. Review the full migration plan in advance to understand in what order you need to move your resources.
Make sure that all stateful workloads, including managed databases and StatefulSets with PersistentVolumes, have up-to-date backups.
Run this command to get a full list of your source cluster resources:
for ns in $(kubectl get ns --no-headers -o custom-columns=':metadata.name'); do
echo "=== Namespace: $ns ==="
kubectl get deploy,sts,ds,job,cronjob,svc,ingress,pvc,cm,secret,hpa,pdb -n $ns
done
Inventory checklist:
|
Resource |
Details to collect |
|
Deployments, StatefulSets, DaemonSets, Jobs, CronJobs |
Quantity, namespace, images |
|
PersistentVolumeClaim |
Size, StorageClass, access mode (RWO/RWX) |
|
LoadBalancer-type services |
External IPs, DNS names |
|
Ingress / HTTPRoute |
Hosts, TLS, IngressClass, or GatewayClass |
|
ConfigMap and Secret |
List |
|
CustomResourceDefinitions and Operators |
List of installed CRDs and operators |
Assess compatibility
To make sure your cluster components work correctly after the migration, assess their compatibility with the target cluster in advance. Create a list of changes you need to make to the manifests and plan how to replace incompatible source cluster components with their Yandex Cloud alternatives.
The scope of changes depends on the version gap between the source and target Kubernetes clusters. The wider the gap, the more changes you need to make, as both vendor-specific CRDs and standard Kubernetes API groups may differ. For supported versions, see Support for Kubernetes versions.
Tip
Run the kubectl api-resources command on both the source and target clusters to compare API resources, or use the kube-no-trouble (kubent)
Key considerations to keep in mind:
- Check for vendor-specific CRDs in the source cluster that may not be available in Yandex Cloud. Replace the components with Yandex Cloud services or solutions from Yandex Cloud Marketplace.
- Note that PodSecurityPolicy is removed in Kubernetes versions 1.25 and up. If using PodSecurityPolicy in the source cluster, migrate to PodSecurity Admission
. - Replace the storage classes (
storageClassName) in your manifests with those supported in Managed Service for Kubernetes. - We recommend using the Gwin controller for L7 load balancing.
Develop the service migration plan
Decide on the order for migrating your services: start with the least critical ones and finish with production workloads. To redirect traffic, use a zero-downtime blue-green deployment
Key considerations to keep in mind:
- Perform an end-to-end migration in a staging environment before migrating production workloads.
- Develop a rollback plan for critical issues and align it with your team in advance.
- Work closely with development and support teams at all stages.
- Choose off-peak hours to perform the migration.
- Monitor metrics before, during, and after the migration using Yandex Monitoring.
Set up your Yandex Cloud infrastructure
Prepare the target environment in Yandex Cloud for your workloads.
Configure access and permissions
Create service accounts to manage cluster resources and worker nodes, and assign roles to them.
Roles you may need
To manage the cluster:
k8s.clusters.agent.k8s.tunnelClusters.agentinstead ofk8s.clusters.agent, if creating the cluster in tunneling mode.
Learn more about roles in Managed Service for Kubernetes.
To manage network resources:
vpc.publicAdmin.vpc.privateAdmin.vpc.user.vpc.bridgeAdminif the VPC resides in a different folder.
Learn more about roles in VPC.
To work with images:
container-registry.images.puller.cloud-registry.artifacts.pullerif using Cloud Registry as an alternative to Container Registry.
Learn more about roles in Container Registry and Cloud Registry roles.
If using secret encryption:
kms.keys.encrypterDecrypter
Learn more about roles in KMS.
If using Object Storage for backups:
storage.editor
Learn more about roles in Object Storage.
Set up the network infrastructure
Set up a network infrastructure for the cluster: an isolated network with security rules for all types of cluster traffic:
- Create a VPC and subnets in three zones to ensure high availability.
- Create security groups to isolate cluster traffic, node traffic, and inbound connections. You must create five groups in total.
Create a Managed Service for Kubernetes cluster
- Create a Managed Service for Kubernetes cluster. Use the same Kubernetes version as in your source cluster or higher.
- Create a node group in each availability zone.
Migrate container images
Move container images to Yandex Container Registry one by one, keeping their tags and metadata.
You can also use Yandex Cloud Registry as an alternative storage for images. Unlike Yandex Container Registry, Cloud Registry supports not only Docker images but other artifact types as well.
Migrate stateful workloads
Migrating stateful workloads, such as managed databases and StatefulSets with PersistentVolumes, is the most complex step of the migration. They store data and cannot be recreated with zero data loss.
Warning
Make sure that all stateful workloads, including managed databases and StatefulSets with PersistentVolumes, have up-to-date backups.
Migrate managed databases
Use Yandex Data Transfer to migrate managed databases. Yandex Data Transfer allows you to migrate data while keeping your source online and minimizing the downtime of applications using the source.
Use the transfer matrix to check that the Snapshot and increment transfer type is supported for your source and target, then refer to your database guide to complete the migration.
Note
Make sure that Data Transfer has network access to the source database. For the current Data Transfer IP address ranges, see the relevant guide.
If Data Transfer does not support your source or you need more control, refer to your target database guides.
Migrate StatefulSets with PersistentVolumes
To migrate StatefulSets with PersistentVolumes, use Veleronode-agent (formerly kopia). This method works with any PVCs regardless of your CSI provider.
Tip
If you have less than 50 GB of data or cannot use Velero, you can migrate data manually via rsync. This requires direct network connectivity between your clusters.
Proceed as follows:
-
Create a bucket in Yandex Object Storage to store backups.
-
Create a file named
credentials-velerocontaining the static access key data for the service account that has access to the bucket:[default] aws_access_key_id = <key_ID> aws_secret_access_key = <secret_key> -
Install the Velero CLI
on the machine you will use to perform the migration. It must havekubectlaccess to the source and target clusters.Tip
The
velero-plugin-for-awsplugin version in the commands below may be outdated. For the latest version, refer to this Velero article . -
Install Velero in the source cluster:
-
Make sure the source cluster context is active:
kubectl config current-context -
Create a namespace for Velero:
kubectl create namespace velero -
Install Velero:
velero install \ --provider aws \ --plugins velero/velero-plugin-for-aws:v1.14.0 \ --bucket <bucket_name> \ --secret-file ./credentials-velero \ --backup-location-config \ region=ru-central1,s3ForcePathStyle=true,s3Url=https://storage.yandexcloud.net \ --use-volume-snapshots=false \ --use-node-agent \ --uploader-type=kopiaWhere:
--provider aws: Uses an AWS plugin compatible with Object Storage.--use-node-agent: Enables DaemonSet to perform file system backups.--uploader-type=kopia: Recommended uploader, works faster than restic.--use-volume-snapshots=false: Disables CSI snapshots to transfer data via kopia.
-
Check component status:
kubectl get pods -n velero kubectl get backupstoragelocation -n velero velero backup-location getBackupStorageLocationmust switch toAvailable.
-
-
Create a backup of the required namespaces:
velero backup create migration-backup \ --include-namespaces <namespace> \ --default-volumes-to-fs-backup \ --waitYou can check the status and logs using the following commands:
velero backup describe migration-backup --details velero backup logs migration-backup -
Install Velero in the target Managed Service for Kubernetes cluster:
-
Switch to the target cluster context:
kubectl config use-context <target_cluster_context> -
Create a namespace for Velero:
kubectl create namespace velero -
Install Velero with the same parameters as in the source cluster, specifying the same bucket:
velero install \ --provider aws \ --plugins velero/velero-plugin-for-aws:v1.14.0 \ --bucket <bucket_name> \ --secret-file ./credentials-velero \ --backup-location-config \ region=ru-central1,s3ForcePathStyle=true,s3Url=https://storage.yandexcloud.net \ --use-volume-snapshots=false \ --use-node-agent \ --uploader-type=kopia -
Confirm that the backup from the source cluster is visible in the target cluster:
kubectl get pods -n velero velero backup-location get velero backup getBackupStorageLocationmust switch toAvailable, and themigration-backup, toCompleted.
-
-
Restore data from the backup:
velero restore create \ --from-backup migration-backup \ --waitYou can check the status and logs using the following commands:
velero restore describe migration-backup --details velero restore logs migration-backupTip
If the StorageClass names in the source cluster and Managed Service for Kubernetes cluster do not match, create a ConfigMap with the StorageClass mapping before initiating recovery:
apiVersion: v1 kind: ConfigMap metadata: name: change-storage-class-config namespace: velero labels: velero.io/plugin-config: "" velero.io/change-storage-class: RestoreItemAction data: <source_storage_class>: yc-network-ssd
Migrate stateless workloads
To migrate stateless workloads, export your source cluster manifests, update them for Yandex Cloud, and apply to the target cluster.
Checklist for updating manifests:
- Replace vendor-specific CRDs with Yandex Cloud services or solutions from Yandex Cloud Marketplace.
- For any deprecated
apiVersion, update the version to make it compatible with the target Kubernetes version. - Use the Gwin controller (
gwin-default) iningressClassNameandgatewayClassName. - Replace resource annotations used for configuring the load balancer with Yandex Cloud annotations.
- Make sure image links lead to Yandex Container Registry (
cr.yandex/<id>/...).
You can use kubectl-neat
Configure the load balancers and update your DNS records
Reroute traffic to the new cluster.
Managed Service for Kubernetes supports two load balancing methods:
- Gwin.
- Network Load Balancer: Created automatically for a service of the
LoadBalancertype.
Steps to switch traffic:
- Deploy Gateway or Ingress resources in the Managed Service for Kubernetes cluster.
- Get the external IP addresses of the new load balancers.
- Test your services using temporary DNS records.
- Reduce the TTL of production DNS records in advance, then update them incrementally.
- Monitor DNS propagation and TLS certificate updates.
Tip
If you face critical issues after updating DNS records, go back to using the old IP addresses. The source cluster must remain operational until all TTLs expire and you confirm a successful migration.
Complete your migration
Take final steps and optimize your configuration:
- Make sure all services work correctly in Managed Service for Kubernetes.
- Check metrics and performance in Yandex Monitoring.
- Disable your source cloud resources after confirming stable operation.
- Optimize the cluster configuration to match your actual workload.
- Delete temporary resources: the Velero bucket, Data Transfer pipelines, VPN tunnels, and temporary login credentials.