- Coverage by target cloud
- How the targets compare
- On Google Cloud
- On Azure
- On OCI
- On Private Kubernetes
Coverage by target cloud
How the targets compare
Each row compares a capability of EC2 with its adaptation on each target. A dash means this row is not stated for that target.Max adaptation
Infrastructure-only adaptation
On Google Cloud
How it works
On AWS your workload runs on an EC2 instance. Tensor9 compiles the AWS Terraform into a Compute Engine VM using a compatible target image containing the application software. Your process runs directly on the VM. A Tensor9 metadata service runs inside the VM. It answers requests to169.254.169.254 for the instance ID, region, and IAM credentials your workload expects from EC2.
The workload runs on a native Compute Engine VM, with an in-guest metadata responder.
Machine Images
Tensor9 translates the image and VM size. A stock image is looked up: adata aws_ami lookup for a current Ubuntu LTS resolves to the equivalent Compute Engine image family (Ubuntu 22.04 on x86 → ubuntu-os-cloud/ubuntu-2204-lts), kept at the resolved version so a change to “latest” does not trigger a rebuild. A custom image is compiled into the target image format: your own built AMI becomes a native Compute Engine image containing your software, so both paths land a native image. The instance_type maps to the nearest Compute Engine machine type in the same hardware class, and the root EBS volume becomes a persistent disk. An input with no faithful target (an Arm origin where no matching image family exists, or an image that can’t be built) is caught at build rather than booted as the wrong machine.
- AMI → Compute Engine image: a
data aws_amistock lookup resolves to the equivalent image family at a fixed version; a custom AMI is compiled into a native Compute Engine image built from your software. Both produce an image for the target cloud. - instance_type → machine_type: general →
n2 / n4, compute →c2 / c3, memory →m3, storage →z3, GPU →a3 / a2 / g2. The Arm class has its analog inc4a(Axion), gated today on Arm image-family coverage, so an Arm origin is caught at build rather than landed on an x86 host. - The root disk: it boots the translated image, keeping its size and type; attached data volumes require target disks, guest mounts and a separate data transfer.
- Cloud-managed. Google operates the hypervisor, host, and availability; your workload runs unchanged in the guest.
IMDSv2
The responder implements Instance Metadata Service v2 (IMDSv2), the token-protected mode AWS defaults to:PUT /latest/api/token returns a short-lived session token, which the client sends back in the X-aws-ec2-metadata-token header on each GET /latest/meta-data/…. Token-less IMDSv1 reads work too, unless the origin instance set http_tokens=required.
The AWS SDK and most bootstrap scripts read this metadata from the fixed link-local address 169.254.169.254. Compute Engine uses that address for its own metadata API. The adapter serves the AWS metadata paths in the guest: the address is redirected to a loopback responder that returns an EC2-shaped identity, read-only, and never leaving the VM. A field it can’t resolve truthfully returns an error, so unresolved fields fail rather than returning a fabricated identity.
Native Google metadata uses /computeMetadata/v1/ paths and the required Metadata-Flavor: Google request header. The responder forwards those native requests to Compute Engine metadata, preserving the path, query and header; it returns the provider’s response. Only the AWS /latest/ paths use the EC2 responder and its IMDSv2 token handshake. The shared link-local address therefore does not turn a native Google metadata request into an AWS request.
the IMDSv2 handshake, unchanged, on the migrated GCE VM
The link-local metadata address is redirected to an in-guest responder that speaks IMDSv2 and returns an EC2-shaped identity.
Launch templates and Auto Scaling fleets
A launch template defines instance settings. An Auto Scaling group adds the member count, placement and scaling policy. The fleet mapping combines them into the target’s instance template and managed group. Review the Auto Scaling page for scaling-policy and orchestration limits. Launch templates. A launch template is a blueprint for an instance: the same fields anaws_instance sets (image, machine type, key, user-data, disks, IAM role), declared once for reuse. An instance that references one is read as a single effective configuration: the template supplies the base and the instance’s own inline arguments override it, field by field, exactly as AWS resolves them. That one effective machine is translated the same way a standalone instance is, so a launch-template-defined VM gets the same image, machine type, disks, network, identity, and in-guest metadata as any other.
Auto Scaling groups. An ASG is a fleet of identical instances behind one size-and-scaling policy, and Google’s native equivalent is a regional managed instance group driven by a google_compute_instance_template. desired_capacity becomes the group’s target size and min_size/max_size become the regional autoscaler’s bounds. The launch template’s effective configuration becomes the instance template every member boots from, so each replica is a full VM with the same disks, network, identity, and read-only metadata API as a standalone instance, spread across the region’s zones.
- Launch template → one effective machine: template base + the instance’s inline overrides resolve to a single configuration, translated like any standalone VM.
- ASG → regional managed instance group.
desired_capacity→ target size;min_size/max_size→ the regional autoscaler’s bounds. - Every replica is a full VM: the blueprint becomes the
google_compute_instance_templateeach member boots from, giving each member the same identity and metadata as a single instance.
When the instance ID changes
An EC2 instance-id (i-…) is stable for the life of the instance and changes only when the instance is replaced. The responder reproduces that by deriving the instance-id from the GCE VM’s own Google-assigned id (hashed together with the install id). While the VM exists the id is stable, including across reboots and across Tensor9 redeploys of the surrounding stack.
It changes when the VM is replaced. Tensor9 ties the VM’s replacement to the AWS attributes it models as requiring replacement (AMI, subnet, key pair, availability zone, CPU options, placement), so replacing any of them replaces the VM and rotates the id. Target replacement rules can differ from EC2; review image, shape and network changes before applying them.
- Stable across reboots and redeploys: the id is derived from the persistent GCE VM id, not from boot state.
- Rotates on a modeled force-new change: a change to a modeled attribute (AMI, subnet, key pair, AZ, CPU options, placement) replaces the VM and rotates the id.
- Never the raw VM id: the Google id is hashed into an EC2-shaped
i-…; it is not served or logged verbatim.
Limitations
The compute path is native and the metadata handshake matches EC2. Review these metadata, storage and network differences: Known limits- The metadata API is read-only: it serves identity and metadata, not a control plane: there is no EC2 create or terminate against it; the VM is managed as a Compute Engine resource.
- The signed instance-identity document isn’t served: its signature can’t be reproduced, so it is withheld; the plaintext identity document is served, with a reconciled account id and region. Workloads that verify the IMDS signature won’t run.
- Discovery uses the configured EC2 adapter endpoint. Describe operations return supported instances and related resources in the managed account, including the instance. Filters and pagination follow the supported API scope. The metadata endpoint inside the guest remains a separate service; unrelated real cloud accounts are outside this discovery scope.
- The IAM credentials from the metadata service are Tensor9-scoped placeholders. AWS calls still succeed (they travel the Tensor9 egress path, which substitutes the real caller credential), but the placeholder credentials don’t work against an AWS endpoint reached directly.
- The VM runs as the origin instance’s IAM role: that role is mapped to a Google service account and the VM runs as it (not GCP’s default Compute Engine service account), so the origin’s declared IAM intent is what the VM can actually do. A role with no literal name (a
name_prefixor computed name) can’t be resolved, so it is caught at compile. - The machine type is the nearest Compute Engine analog, not identical hardware: performance tracks Compute Engine rather than the specific EC2 instance, close on most shapes, with older Intel generations trailing on single-core. The performance tab has the published comparison.
- Security groups map to target network controls. Use the Compute Engine firewall rules for the VM’s translated rules. Preserve default-deny ingress and the declared egress permissions; do not rely on the network’s default reachability. Review target rule scope, protocol support and address ranges when validating connectivity.
- A per-instance public IP is caught at build: an instance that requests one (
associate_public_ip_address) is refused because this target does not create a per-instance public IP. - Explicit disk-performance settings fail during the build: an instance that sets
iopsorthroughputindependently (AWSgp3/io1/io2) asks for something a Compute Enginepd-*boot disk cannot honor independently, so the build stops rather than quietly giving the disk a different performance profile than the one you declared. - Disks use the target storage service. The root volume uses a Compute Engine persistent disk; attached data volumes need corresponding target disks and guest mounts. Match size, performance class, encryption and attachment limits to the workload. Provisioning a disk does not copy the data from an existing EBS volume.
- Launch templates and Auto Scaling groups use the fleet mapping. A launch template or launch configuration defines each member, and the group maps to a regional managed instance group. Review the Auto Scaling page for the target’s scaling, health-check and rolling-update limits; support for individual instances does not establish every fleet policy.
Other considerations
Plan for the following operating requirements.- Native execution: the workload runs directly on the Compute Engine VM; Tensor9 operates the separate in-guest metadata service.
- Google operates the machine: the hypervisor, host, and hardware availability are Google’s to run, as AWS does for EC2.
- Tensor9 operates the read-only metadata API: the in-guest responder answers EC2 identity and IAM credentials on 169.254.169.254, read-only, and accepts no create or terminate against the VM.
- The machine type is the nearest analog, not identical hardware: the workload lands on the closest Compute Engine machine type in its class, so plan for performance that tracks that type rather than the specific EC2 instance.
- The instance-id follows the VM’s lifecycle: it is stable across reboots and redeploys while the VM exists, and changes when the VM is replaced. Review target replacement rules before changing size or image.
Runtime lifecycle and instance metadata
Maximum adaptation separates the EC2 management API from the metadata endpoint inside each VM. Supported lifecycle requests record the requested instance state; a reconciler creates or changes the target VM and its associated resources. A successful request can return a pending state while the target is still creating the machine. Use the describe operations to check readiness. RunInstances, termination and tagging operate on resources managed by this adapter-managed account. Attribute updates and launch shapes remain bounded by the supported request and target settings. Describe requests can list managed instances; they do not grant access to unrelated cloud accounts. The in-guest metadata service supplies the workload’s identity and credentials independently of those lifecycle operations. Metadata and management responses must refer to the same managed instance.On Azure
How it works
On AWS your workload runs on an EC2 instance. Tensor9 compiles the AWS Terraform into an Azure Linux Virtual Machine using a compatible target image containing the application software. Your process runs directly on the VM. A Tensor9 metadata service runs inside the VM. It answers requests to169.254.169.254 for the instance ID, region, and IAM credentials your workload expects from EC2.
The workload runs on a native Azure Linux VM, with an in-guest metadata responder.
Machine Images
Tensor9 translates the VM size and image. Theinstance_type maps to the nearest Azure VM size in the same hardware family (general purpose → D-series, compute → F, memory → E, burstable → B), and the root EBS volume becomes an Azure managed disk.
The image. A stock image is looked up: a data aws_ami lookup for a current Ubuntu LTS resolves to the equivalent Canonical image in the Azure Marketplace (the Canonical publisher’s source_image_reference), kept at the resolved version so a change to “latest” does not trigger a rebuild. A custom image is compiled into the target image format: your own built AMI becomes a native Azure managed image containing your software, so both paths boot a native Azure image. An input with no faithful target (an Arm origin with no matching image, or an image that can’t be built) is caught at build rather than booted as the wrong machine.
- Stock image → Azure Marketplace: a
data aws_amiUbuntu-LTS lookup resolves to the matching Canonical Marketplace image, kept at the resolved version. - instance_type → VM size: general →
D, compute →F, memory →E, burstable →B, GPU →N-series, Arm →Dpds/Epsv. - The OS disk: it boots the resolved image, keeping its size and type; attached data volumes require target disks, guest mounts and a separate data transfer.
- Custom image → compiled Azure image: a non-Canonical AMI is compiled into a native Azure managed image built from your software; both stock and custom images use the target cloud’s format.
- Cloud-managed. Azure operates the hypervisor, host, and availability; your workload runs unchanged in the guest.
IMDSv2
The in-guest responder implements Instance Metadata Service v2 (IMDSv2), the token-protected mode AWS defaults to:PUT /latest/api/token returns a short-lived session token, which the client sends back in the X-aws-ec2-metadata-token header on each GET /latest/meta-data/…. Token-less IMDSv1 reads work too, unless the origin instance set http_tokens=required.
An Azure VM already answers on 169.254.169.254: that is Azure’s own Instance Metadata Service. Tensor9 does not take it over: the EC2 metadata paths (/latest/…) are answered in the guest by the EC2-shaped responder, while Azure’s own metadata paths (/metadata/…) are passed straight through to Azure untouched, so managed-identity and platform tooling that read Azure’s metadata keep working. A field the responder can’t resolve truthfully returns an error, so unresolved fields fail rather than returning a fabricated identity.
the IMDSv2 handshake, unchanged, on the migrated Azure VM
The link-local metadata address is shared by path: the EC2 metadata path gets an EC2-shaped answer in the guest; Azure’s own metadata path is passed straight through, untouched.
Launch templates and Auto Scaling fleets
A launch template defines instance settings. An Auto Scaling group adds the member count, placement and scaling policy. The fleet mapping combines them into the target’s instance template and managed group. Review the Auto Scaling page for scaling-policy and orchestration limits. Launch templates. A launch template is a blueprint for an instance: the same fields anaws_instance sets (image, size, key, user-data, disks, IAM role), declared once for reuse. An instance that references one is read as a single effective configuration: the template supplies the base and the instance’s own inline arguments override it, field by field, exactly as AWS resolves them. That one effective machine is then translated the same way a standalone instance is, so a launch-template-defined VM gets the same image, size, disks, network, identity, and in-guest metadata as any other.
Auto Scaling groups. An ASG is a fleet of identical instances behind one size-and-scaling policy, and Azure’s native equivalent is a Virtual Machine Scale Set. desired_capacity becomes the scale set’s desired size; running and ready capacity depend on allocation, startup and health checks. min_size/max_size become desired-capacity autoscale bounds. On Azure the scale set declares its machine blueprint inline (there is no separate template resource), so the launch template’s effective configuration becomes the scale set’s VM profile, and every replica is a full VM with the same disks, network, identity, and read-only metadata API as a standalone instance.
- Launch template → one effective machine: template base + the instance’s inline overrides resolve to a single configuration, translated like any standalone VM.
- ASG → Virtual Machine Scale Set.
desired_capacity→ desired size, with readiness following allocation and health;min_size/max_size→ autoscale bounds. - Every replica is a full VM: the blueprint becomes the scale set’s inline VM profile, so each replica gets the same identity and metadata as a single instance.
When the instance ID changes
An EC2 instance-id (i-…) is stable for the life of the instance and changes only when the instance is replaced. The responder reproduces that by deriving the instance-id from the Azure VM’s own vmId. While the VM exists the id is stable, including across reboots and across Tensor9 redeploys of the surrounding stack, and it is served consistently from first boot, not regenerated on a restart.
It changes when the VM is replaced. Tensor9 ties the VM’s replacement to the AWS attributes it models as requiring replacement (image, subnet, key pair, availability zone, CPU options, placement), so replacing any of them replaces the VM and rotates the id. Target replacement rules can differ from EC2; review image, shape and network changes before applying them.
- Stable across reboots and redeploys: the id is derived from the persistent Azure
vmId, and served consistently across a responder restart. - Rotates on a modeled force-new change: a change to a modeled attribute (image, subnet, key pair, zone, CPU options, placement) replaces the VM and rotates the id.
- Never the raw VM id: the Azure
vmIdis hashed into an EC2-shapedi-…; it is not served or logged verbatim.
Limitations
The compute path is native and the metadata handshake matches EC2. Review these metadata, storage and network differences: Known limits- The metadata API is read-only: it serves identity and metadata, not a control plane: there is no EC2 create or terminate against it; the VM is managed as an Azure resource.
- The signed instance-identity document isn’t served: its signature can’t be reproduced, so it is withheld; the plaintext identity document is served, with a reconciled account id and region. Workloads that verify the IMDS signature won’t run.
- Discovery uses the configured EC2 adapter endpoint. Describe operations return supported instances and related resources in the managed account, including the VM. Filters and pagination follow the supported API scope. The metadata endpoint inside the guest remains a separate service; unrelated real cloud accounts are outside this discovery scope.
- Security groups map to target network controls. Use the Azure network security group for the VM’s translated rules. Preserve default-deny ingress and the declared egress permissions; do not rely on Azure’s default intra-network allow. Review target rule scope, protocol support and address ranges when validating connectivity.
- A per-instance public IP is caught at build: an instance that requests one (
associate_public_ip_address) is refused because this target does not create a per-instance public IP. - Explicit disk-performance settings fail during the build: an instance that sets
iopsorthroughputindependently (AWSgp3/io1/io2) asks for something an Azure managed OS disk cannot honor (independent IOPS needs a different disk type entirely), so the build stops rather than quietly giving the disk a different performance profile than the one you declared. - Disks use the target storage service. The root volume uses an Azure managed disk; attached data volumes need corresponding target disks and guest mounts. Match size, performance class, encryption and attachment limits to the workload. Provisioning a disk does not copy the data from an existing EBS volume.
- Launch templates and Auto Scaling groups use the fleet mapping. A launch template or launch configuration defines each member, and the group maps to a Virtual Machine Scale Set. Review the Auto Scaling page for the target’s scaling, health-check and rolling-update limits; support for individual instances does not establish every fleet policy.
- The VM runs as the origin instance’s IAM role, mapped to an Azure managed identity: the origin’s declared IAM intent is what the VM can actually do; a role with no literal name (a
name_prefixor a pre-existing external profile that can’t be resolved) is caught at compile rather than binding a wrong or default identity. - The VM size is the nearest Azure analog, not identical hardware: performance tracks the Azure size rather than the specific EC2 instance. The performance tab has the published comparison.
- Burstable and Spot instances have limitations on Azure: a burstable T-instance maps to a B-series size; the AWS unlimited-burst mode has no B-series equivalent and is caught rather than silently throttled. Spot maps to an Azure Spot VM (stop → deallocate, terminate → delete); a hibernate-on-interruption policy is caught at compile.
Other considerations
Plan for the following operating requirements.- Native execution: the workload runs directly on the Azure Linux VM; Tensor9 operates the separate in-guest metadata service.
- Azure operates the machine: the hypervisor, host, and hardware availability are Azure’s to run, as AWS does for EC2.
- Tensor9 operates the read-only metadata API: the in-guest responder serves EC2 identity and IAM credentials but accepts no create or terminate against the VM, and Azure’s own instance metadata on the same address is passed through untouched.
- The VM size is the nearest analog, not identical hardware: the workload lands on the closest Azure size in its family (D/F/E/B), so plan for performance that tracks that size rather than the specific EC2 instance.
- The instance-id follows the VM’s lifecycle: it is stable across reboots and redeploys while the VM exists, and changes when the VM is replaced. Review target replacement rules before changing size or image.
Runtime management on Azure
The EC2 lifecycle and metadata model also applies to Azure VMs. Supported runtime requests reconcile onto Azure resources; acceptance precedes readiness. The Azure metadata endpoint remains separate from managed-account discovery. The operation rows above bound supported launch and attribute changes.On OCI
How it works
On AWS your workload runs on an EC2 instance. Tensor9 compiles the AWS Terraform into an OCI Compute instance (oci_core_instance) using a compatible target image containing the application software. Your process runs directly on the instance.
A Tensor9 metadata service runs inside the VM. It answers requests to 169.254.169.254 for the instance ID, region, and IAM credentials your workload expects from EC2.
The workload runs on a native OCI Compute instance, with an in-guest metadata responder.
Machine Images
Tensor9 translates the VM size and image. Theinstance_type maps to the nearest OCI shape, a VM.Standard flexible shape, where the origin’s vCPU count sets the shape’s OCPUs and its memory sizing; the root EBS volume becomes an OCI boot volume.
The image. A stock image is looked up: a data aws_ami lookup for a current Ubuntu LTS resolves to the equivalent Canonical Ubuntu image through a data oci_core_images find-latest lookup, kept at the resolved version so a change to “latest” does not trigger a rebuild. A custom image is compiled into the target image format: your own built AMI becomes a native OCI custom image containing your software, so both paths boot a native OCI image. An input with no faithful target (an Arm origin with no matching image, or an image that can’t be built) is caught at build rather than booted as the wrong machine.
- Stock image → Canonical Ubuntu: a
data aws_amiUbuntu-LTS lookup resolves throughdata oci_core_imagesto the matching Canonical image (x86 today; an Arm origin is caught at build rather than booted on the wrong architecture). - instance_type → OCI shape: mapped to the nearest
VM.Standardflexible shape; the vCPU count sets the shape’s OCPUs, andcpu_options.core_countmaps onto the shape’s OCPU config. - The boot volume: it runs the resolved image, keeping its size and type; attached data volumes use separately provisioned volumes and guest mounts.
- Custom image → compiled OCI image: a non-Canonical AMI is compiled into a native OCI custom image that contains your software; both stock and custom images use the target cloud’s format.
- Cloud-managed. OCI operates the hypervisor, host, and availability domain; your workload runs unchanged in the guest.
IMDSv2
The in-guest responder implements Instance Metadata Service v2 (IMDSv2), the token-protected mode AWS defaults to:PUT /latest/api/token returns a short-lived session token, which the client sends back in the X-aws-ec2-metadata-token header on each GET /latest/meta-data/…. Token-less IMDSv1 reads work too, unless the origin instance set http_tokens=required.
An OCI Compute instance already answers on 169.254.169.254: that is OCI’s own Instance Metadata Service, which serves under /opc/… paths. Tensor9 does not take it over: the EC2 metadata paths (/latest/…) are answered in the guest by the EC2-shaped responder, while OCI’s own metadata paths (/opc/…) are passed straight through to OCI untouched, so OCI instance-principal and platform tooling that read /opc keep working. A field the responder can’t resolve truthfully returns an error, so unresolved fields fail rather than returning a fabricated identity.
the IMDSv2 handshake, unchanged, on the migrated OCI Compute instance
The link-local metadata address is shared by path: the EC2 metadata path gets an EC2-shaped answer in the guest; OCI’s own /opc metadata path is passed straight through, untouched.
Launch templates and Auto Scaling fleets
A launch template defines instance settings. An Auto Scaling group adds the member count, placement and scaling policy. The fleet mapping combines them into the target’s instance template and managed group. Review the Auto Scaling page for scaling-policy and orchestration limits. Launch templates. A launch template is a blueprint for an instance: the same fields anaws_instance sets (image, size, key, user-data, disks, IAM role), declared once for reuse. An instance that references one is read as a single effective configuration: the template supplies the base and the instance’s own inline arguments override it, field by field, exactly as AWS resolves them. That one effective machine is then translated the same way a standalone instance is, so a launch-template-defined instance gets the same image, shape, disks, network, identity, and in-guest metadata as any other.
Auto Scaling groups. An ASG is a fleet of identical instances behind one size-and-scaling policy, and OCI’s native equivalent is an instance pool. Unlike Azure’s inline scale set, OCI keeps the machine blueprint in a separate oci_core_instance_configuration resource, which the pool references; desired_capacity becomes the pool’s desired size. Running and ready capacity depend on allocation, startup and health checks. min_size/max_size become its desired-capacity autoscale bounds. The launch template’s effective configuration becomes that configuration’s launch details, so every replica is a full instance with the same disks, network, scoped identity, and read-only metadata API as a standalone instance.
- Launch template → one effective machine: template base + the instance’s inline overrides resolve to a single configuration, translated like any standalone instance.
- ASG → instance pool + instance configuration.
desired_capacity→ desired size, with readiness following allocation and health;min_size/max_size→ autoscale bounds; the blueprint lives in a separateoci_core_instance_configuration, not inline. - Every replica is a full instance: the blueprint becomes the configuration’s launch details, so each pool member has the same scoped identity and metadata as a single instance.
When the instance ID changes
An EC2 instance-id (i-…) is stable for the life of the instance and changes only when the instance is replaced. The responder reproduces that by deriving the instance-id from the OCI instance’s own OCID. While the instance exists the id is stable, including across reboots and across Tensor9 redeploys of the surrounding stack, and it is served consistently from first boot, not regenerated on a restart.
It changes when the instance is replaced. Tensor9 ties the instance’s replacement to the AWS attributes it models as requiring replacement (image, subnet, SSH key pair, availability domain, CPU options, placement), so replacing any of them replaces the instance and rotates the id. Target replacement rules can differ from EC2.
- Stable across reboots and redeploys: the id is derived from the persistent OCI instance
OCID, and served consistently across a responder restart. - Rotates on a modeled force-new change: a change to a modeled attribute (image, subnet, SSH key, availability domain, CPU options, placement) replaces the instance and rotates the id.
- Never the raw OCID: the OCI
OCIDis hashed into an EC2-shapedi-…; it is not served or logged verbatim.
Limitations
The compute path is native and the metadata handshake matches EC2. Review these metadata, storage and network differences: Known limits- The metadata API is read-only: it serves identity and metadata, not a control plane: there is no EC2 create or terminate against it; the instance is managed as an OCI resource.
- The signed instance-identity document isn’t served: its signature can’t be reproduced, so it is withheld; the plaintext identity document is served, with a reconciled account id and region. Workloads that verify the IMDS signature won’t run.
- Discovery uses the configured EC2 adapter endpoint. Describe operations return supported instances and related resources in the managed account, including the instance. Filters and pagination follow the supported API scope. The metadata endpoint inside the guest remains a separate service; unrelated real cloud accounts are outside this discovery scope.
- Security groups map to target network controls. Use the OCI network security list for the instance’s translated rules. Preserve default-deny ingress and the declared egress permissions; do not rely on OCI’s more permissive default. Review target rule scope, protocol support and address ranges when validating connectivity.
- A per-instance public IP is caught at build: an instance that requests one (
associate_public_ip_address) is refused because this target does not create a per-instance public IP. - Launch templates and Auto Scaling groups use the fleet mapping. A launch template or launch configuration defines each member, and the group maps to an OCI instance pool. Review the Auto Scaling page for the target’s scaling, health-check and rolling-update limits; support for individual instances does not establish every fleet policy.
- The instance runs as the origin’s IAM role, mapped to an OCI dynamic group and instance principal, scoped to this one instance: every OCI instance is automatically an instance principal; the origin’s declared IAM intent becomes a dynamic group whose membership rule and policy use a per-install tag to match only this instance, so a grant never reaches sibling VMs. A role that can’t be resolved to a literal identity (a
name_prefix, or an external profile that can’t be resolved) is caught at compile, and an identity that can’t be scoped to the installed instance fails rather than granting access to other instances. - The OCI shape is the nearest analog, not identical hardware: performance tracks the OCI shape rather than the specific EC2 instance type. The performance tab has the published comparison.
- Disks use the target storage service. The root volume uses an OCI boot volume; attached data volumes need corresponding target disks and guest mounts. Match size, performance class, encryption and attachment limits to the workload. Provisioning a disk does not copy the data from an existing EBS volume.
- Boot-volume performance is one coupled knob, not two. AWS
gp3setsiopsandthroughputindependently; an OCI boot volume sets both together from a single per-GB performance setting. The volume class comes across (a general-purpose origin lands on the balanced setting), but explicitiopsorthroughputnumbers do not, so an instance that sets either is caught at build rather than having the two values silently coerced into one. - Availability-zone placement isn’t reproduced one-to-one: an AWS availability zone has no faithful OCI availability domain, so the instance is placed in the compartment’s availability domain rather than a mapped zone, which changes its placement.
- Burstable and Spot instances have limitations on OCI: a burstable T-instance maps to an OCI shape with a reduced baseline OCPU utilization; the AWS unlimited-burst mode has no OCI equivalent and is caught rather than silently throttled. Spot maps to an OCI preemptible instance (stop → the preemption action); a hibernate-on-interruption policy is caught at compile.
Other considerations
Plan for the following operating requirements.- Native execution: the workload runs directly on the OCI Compute instance; Tensor9 operates the separate in-guest metadata service.
- OCI operates the machine: the hypervisor, host, and availability domain are OCI’s to run, as AWS does for EC2.
- Tensor9 operates the read-only metadata API: the in-guest responder answers the EC2
/latestpaths on 169.254.169.254 while OCI’s own/opcmetadata is passed through, and it accepts no create or terminate against the instance. - The OCI shape is the nearest analog, not identical hardware: the workload lands on the closest
VM.Standardflexible shape, so plan for performance that tracks that shape rather than the specific EC2 instance type. - The instance-id follows the instance’s lifecycle: it is derived from the instance’s OCID, remains stable while the instance exists, and changes when the instance is replaced. Review target replacement rules before changing size or image.
Runtime management on OCI
OCI instances use the same bounded EC2 lifecycle and metadata model. Runtime changes finish asynchronously on OCI; describe operations expose observed readiness. In-guest discovery remains local, while the separate management API lists only the caller’s managed resources.On Private Kubernetes
How it works
On AWS your workload runs on an EC2 instance. Tensor9 compiles the AWS Terraform into a KubeVirt VirtualMachine using a compatible target image containing the application software, running under KVM on the Kubernetes cluster you operate. Your process runs directly inside the VM. A Tensor9 metadata service runs inside the VM. It answers requests to169.254.169.254 for the instance ID, region, and IAM credentials your workload expects from EC2.
The workload runs on a KubeVirt VirtualMachine under KVM on the target cluster, with an in-guest metadata responder.
Machine Images
Tensor9 translates the VM size and image. Theinstance_type becomes the VM’s guest resources (its domain CPU and memory) read straight from the instance’s vCPU and RAM rather than mapped through a fixed shape table. The VM boots the resolved image directly as its disk, sized by that image, so an origin that sets its own root-volume size is caught at build rather than booted smaller than it asked for.
The image. A stock image is looked up: a data aws_ami lookup for a current Ubuntu LTS resolves to the equivalent Canonical Ubuntu containerDisk (a bootable cloud image with cloud-init) that the VM boots directly. A custom image is compiled into a bootable volume: your own built AMI is compiled into a bootable persistent volume by the Containerized Data Importer, so the VM boots a native disk built from your software. That path, like the VM primitive itself, needs the KubeVirt operator and the Data Importer installed on the cluster, so a compile that references a custom image is caught at build with a clear message when they are absent, rather than booting the wrong image.
- Stock image → Canonical containerDisk: a
data aws_amiUbuntu-LTS lookup resolves to a Canonical Ubuntu containerDisk (a bootable cloud image with cloud-init) booted directly. - instance_type → domain CPU and memory: the guest’s vCPU and RAM are read straight from the instance shape, not mapped through a fixed size table.
- The boot disk: it is created from the resolved image and sized by it; additional capacity and data disks require appropriately sized persistent volumes and guest mounts.
- Custom image → compiled by the Data Importer: a non-Canonical AMI is compiled into a bootable persistent volume containing your software; the KubeVirt operator and Data Importer must be installed, and a compile that needs them when absent is caught at build rather than booted wrong.
- Self-managed: the VM runs under KVM on the nodes you operate: you run the hypervisor and the cluster, not a cloud provider; your workload runs unchanged in the guest.
IMDSv2
The in-guest responder implements Instance Metadata Service v2 (IMDSv2), the token-protected mode AWS defaults to:PUT /latest/api/token returns a short-lived session token, which the client sends back in the X-aws-ec2-metadata-token header on each GET /latest/meta-data/…. Token-less IMDSv1 reads work too, unless the origin instance set http_tokens=required.
The AWS SDK and most bootstrap scripts read this metadata from the fixed link-local address 169.254.169.254. A KubeVirt guest boots a real cloud image with cloud-init and, unlike a cloud VM, has no native metadata service sitting on that address to coexist with. So the in-guest responder owns 169.254.169.254 outright: it answers there directly, read-only, never leaving the VM, with nothing to pass through. A field it can’t resolve truthfully returns an error, so a wrong value never reaches the workload.
the IMDSv2 handshake, unchanged, on the migrated KubeVirt VM
The metadata address is owned outright in the guest (there is no native metadata service to share it with), and an in-guest responder speaks IMDSv2 and returns an EC2-shaped identity.
Launch templates and Auto Scaling fleets
A launch template defines instance settings. An Auto Scaling group adds the member count, placement and scaling policy. The fleet mapping combines them into the target’s instance template and managed group. Review the Auto Scaling page for scaling-policy and orchestration limits. Launch templates. A launch template is a blueprint for an instance: the same fields anaws_instance sets (image, size, key, user-data, disks, IAM role), declared once for reuse. An instance that references one is read as a single effective configuration: the template supplies the base and the instance’s own inline arguments override it, field by field, exactly as AWS resolves them. That one effective machine is then translated the same way a standalone instance is, so a launch-template-defined VM gets the same image, guest resources, disks, network, identity, and in-guest metadata as any other.
Auto Scaling groups. An ASG is a fleet of identical instances behind one size-and-scaling policy, and KubeVirt’s native equivalent is a VirtualMachinePool. The launch template’s effective configuration becomes the pool’s embedded virtualMachineTemplate, and desired_capacity becomes the pool’s replicas, every replica a full VM with the same disks, network, identity, and read-only metadata API as a standalone instance, scheduled onto your nodes. The pool exposes a standard scale subresource, so min_size/max_size become the bounds of a horizontal autoscaler you point at it; without one, the pool holds a fixed replica count.
- Launch template → one effective machine: template base + the instance’s inline overrides resolve to a single configuration, translated like any standalone VM.
- ASG → VirtualMachinePool.
desired_capacity→ the pool’sreplicas; the blueprint becomes the pool’s embeddedvirtualMachineTemplate. - Scaling → a horizontal autoscaler on the scale subresource.
min_size/max_sizebecome the bounds of a HorizontalPodAutoscaler you point at the pool; without one it holds a fixed count. - Every replica is a full VM: each replica has the same identity and metadata as a single instance, scheduled onto your own nodes.
When the instance ID changes
An EC2 instance-id (i-…) is stable for the life of the instance and changes only when the instance is replaced. The responder reproduces that by deriving the instance-id from the VM’s own firmware UUID, the SMBIOS identifier the VM presents to its guest, set when the VM is created. While the VM exists the id is stable, including across reboots and across Tensor9 redeploys of the surrounding stack, and it is served consistently from first boot, not regenerated on a restart.
It changes when the VM is replaced. Tensor9 ties the VM’s firmware UUID to the AWS attributes it models as requiring replacement (image, subnet, key pair, availability zone, CPU options, placement), so replacing any of them replaces the VM and rotates the id. Target replacement rules can differ from EC2; review image, shape and network changes before applying them. In a pool, each replica gets its own firmware UUID, so every replica gets a distinct EC2-shaped id.
- Stable across reboots and redeploys: the id is derived from the VM’s persistent firmware UUID, and served consistently across a responder restart.
- Rotates on a modeled force-new change: a change to a modeled attribute (image, subnet, key pair, zone, CPU options, placement) replaces the VM and rotates the id.
- Distinct per replica: each VM in a pool has its own firmware UUID, so each is served its own EC2-shaped id.
- Never the raw UUID: the firmware UUID is hashed into an EC2-shaped
i-…; it is not served or logged verbatim.
Limitations
The compute path is native and the metadata handshake matches EC2. Review these metadata, storage and network differences: Known limits- This is self-managed, not a cloud service: you operate the Kubernetes cluster and the KVM nodes the VM runs on, so availability, live-migration, and rescheduling on node drain are the target cluster’s (not a cloud provider’s single-instance SLA), and performance tracks the node the VM lands on.
- The metadata API is read-only: it serves identity and metadata, not a control plane: there is no EC2 create or terminate against it; the VM is managed as a Kubernetes resource on the target cluster.
- The VM runs as the origin instance’s IAM role, mapped to a Kubernetes ServiceAccount: the origin’s declared IAM role becomes the ServiceAccount the VM runs as (its
serviceAccountName), so the origin’s declared identity is what the VM can actually do; a named role with no projected ServiceAccount on the cluster is caught at compile rather than the VM silently running as the namespace default. - The signed instance-identity document isn’t served: its signature can’t be reproduced, so it is withheld; the plaintext identity document is served, with a reconciled account id and region. Workloads that verify the IMDS signature won’t run.
- Local discovery. The configured EC2 adapter endpoint describes only the calling VM and its attached resources. It does not enumerate a managed account or fleet. The in-guest metadata endpoint remains a separate read-only service.
- No per-VM public IP: a KubeVirt VM is single-homed on the target cluster network with no cloud-assigned public address; a request for a per-instance public IP is caught at compile, and an Elastic IP is reproduced as a LoadBalancer Service that fronts the VM rather than an address on the VM itself.
- Security groups map to target network controls. Use a default-deny Kubernetes NetworkPolicy with explicit allows for the VM’s translated rules. Preserve default-deny ingress and the declared egress permissions; do not rely on the cluster’s default pod-to-pod reachability. Review target rule scope, protocol support and address ranges when validating connectivity.
- Persistent storage needs explicit sizing. An image-backed boot disk and a persistent boot volume have different capacity and recovery behavior. Provision the required PersistentVolumes and guest mounts for root expansion or attached data disks; importing an image does not copy unrelated EBS volume contents.
- Launch templates and Auto Scaling groups use the fleet mapping. A launch template or launch configuration defines each member, and the group maps to a VirtualMachinePool. Review the Auto Scaling page for the target’s scaling, health-check and rolling-update limits; support for individual instances does not establish every fleet policy.
- Disk performance belongs to the target cluster, not the VM: a volume’s independent
iops/throughputsettings have no equivalent knob here (your StorageClass and CSI driver own disk performance), so an instance that sets either is caught at build rather than having the values silently ignored. - The KubeVirt operator and the Data Importer must be installed on the cluster: the VM primitive and the custom-image rebuild path depend on them; a compile that needs either is caught at build when they are absent, rather than emitting a manifest the cluster can’t run.
Other considerations
Plan for the following operating requirements.- Native execution: the workload runs directly in the KubeVirt VM’s guest; Tensor9 operates the separate in-guest metadata service.
- You operate the machine: unlike the cloud arms, the VM runs under KVM on the Kubernetes cluster and nodes you run, so availability, live-migration, and rescheduling on node drain are the target cluster’s, not a cloud provider’s.
- Tensor9 operates the read-only metadata API: the in-guest responder owns 169.254.169.254 outright and serves EC2 identity and IAM credentials, but accepts no create or terminate against the VM.
- Guest size is read directly, and performance tracks the node: the instance’s vCPU and RAM become the VM’s domain resources rather than a mapped shape, so performance tracks the node the VM is scheduled onto, not the specific EC2 instance.
- The instance-id follows the VM’s lifecycle: it is derived from the VM’s firmware UUID, remains stable while the VM exists, and changes when the VM is replaced. Review target replacement rules before changing size or image.