> ## Documentation Index
> Fetch the complete documentation index at: https://docs.tensor9.com/llms.txt
> Use this file to discover all available pages before exploring further.

# ECS

> ECS APIs with Cloud Adapter.

This page describes how ECS maps to services in the environment where the application runs, including backend choices, supported operations and service-specific behavior.

## Supported environments

* Akamai
* DigitalOcean
* Private Kubernetes
* Scaleway

Check the operation and capability tables for the behavior your application depends on. A supported environment does not imply that every operation of the origin service is available.

## How the backends compare

Each row compares a capability of ECS with its adaptation on each backend.
A dash means this profile does not state the capability for that backend.

### Cloud Adapter

| Capability | ECS | Akamai, DigitalOcean, Private Kubernetes, and Scaleway |
| - | - | - |
| Cluster · ECS cluster → k8s cluster / namespace | ECS cluster + capacity providers | the cluster or a namespace; capacity providers → the cluster's node pools / cluster-autoscaler (the target cluster owns the nodes) |
| Workload configuration · desired count → replicas | always-on ECS service | Deployment replicas = desiredCount, continuously running; the DAEMON strategy is not converted |
| Compute sizing · Fargate cpu/mem → requests/limits | Fargate \{0.25 … 16 vCPU} | Pod requests / limits: values within node capacity and quota, without Fargate fixed-size combinations |
| Autoscaling · Application Auto Scaling not converted | target-tracking on CPU / memory / custom | removed at build; add a HorizontalPodAutoscaler yourself |
| Service Connect mesh · namespace mesh + metrics | Yes - injected proxy, aliases, metrics | Partial - the Service named after the ECS service gives DNS discovery; a service mesh you add gives the proxy and metrics |
| DAEMON strategy · one copy per host | Yes - DAEMON scheduling strategy | No - not converted: the service becomes a Deployment |
| ECS Exec · shell into a task | Yes - SSM interactive shell | Yes - kubectl exec into the Pod |
| Load balancing · service LB block → Service + Ingress | ALB / NLB target group | not converted: a Service of type LoadBalancer on port 80 to the first container port, with no Ingress |
| Identity / secrets / logging · task role → ServiceAccount + RBAC | task role, secrets, awslogs | a Kubernetes ServiceAccount per service, with RBAC you own (no cloud identity binding); container secrets entries stop the build; output goes to the cluster's log stack |
| API coverage | full | partial |

## On Akamai, DigitalOcean, Private Kubernetes, and Scaleway

### Kubernetes Cluster

| Operation | Area | Support | Depth | Notes |
| - | - | - | - | - |
| Capacity providers / FARGATE\_SPOT | Cluster | Out of scope | Full surface | the cluster owns capacity via its node pools; FARGATE\_SPOT maps to the cluster's spot node pools |
| Identity: task role | Identity | Partial | Common | Each service gets a Kubernetes ServiceAccount. The task role is not bound to a cloud identity on a cluster you operate; AWS calls get credentials from the selected identity adapter. The execution role is not needed. |
| Secrets and environment | Identity | Partial | Common | Container environment variables are copied, including values that reference other resources. Container secrets entries are not supported: the build stops and names each one. |
| Load balancer: service LB block | Load balancer | Partial | Common | The service's load\_balancer block is not converted. Each service gets a Kubernetes Service of type LoadBalancer on port 80 that forwards to the first container's first port; no Ingress is created, and target-group rules and health checks are not carried. |
| Logging: awslogs | Logging | Supported | Common | awslogs → the target cluster's logging; a FireLens sidecar stays a logging sidecar |
| Networking: awsvpc (per-task IP + security group) | Networking | Partial | Common | Each Pod gets its own IP from the cluster network. Security groups are not converted to NetworkPolicy, so pods are not isolated from each other unless you add NetworkPolicy yourself. |
| Networking: service discovery / Service Connect | Networking | Partial | Most usage | Cloud Map registrations and Service Connect are not converted. The Kubernetes Service is named after the ECS service, so cluster DNS resolves that name; Service Connect's proxy and metrics need a service mesh you add (Istio, Linkerd). |
| ECS Exec | Runtime | Supported | Most usage | ECS Exec's interactive shell → kubectl exec into the Pod |
| Task-metadata endpoint (runtime) | Runtime | Out of scope | Common | Not served today. The compiled workload gets no ECS\_CONTAINER\_METADATA\_URI\_V4, and 169.254.170.2 is not answered, so code that reads ECS task metadata fails; read Pod details through the Kubernetes downward API instead. |
| Scheduling: DAEMON strategy | Service | Out of scope | Full surface | The DAEMON scheduling strategy is not read. The service becomes a Deployment with desiredCount replicas (one when unset), not one Pod per node; you must create a DaemonSet yourself. |
| Service: autoscaling | Service | Out of scope | Most usage | Application Auto Scaling targets and policies are removed, not converted. The Deployment runs desiredCount replicas; you must add a HorizontalPodAutoscaler yourself if the service must scale. |
| Service: deployment controller | Service | Partial | Most usage | The Deployment uses the Kubernetes default rolling update. ECS minimum healthy percent and maximum percent are not carried; weighted blue-green or canary release needs release tooling you add (Argo Rollouts, Flagger, a service mesh). |
| Service: desired count | Service | Supported | Common | desiredCount → Deployment desired replicas (one when unset); ready count depends on scheduling and health |
| Task definition: containers / sidecars | Task definition | Supported | Common | multi-container task → main container plus sidecars, native on every target cluster |
| Task definition: cpu / memory | Task definition | Partial | Common | Container cpu becomes a CPU request, with no CPU limit. Container memory becomes the memory limit, and memoryReservation the request. Task-level cpu and memory apply only to a single-container task; a value that is not a literal is left unset. |
| Task definition: image | Task definition | Supported | Common | Copies the container image to your registry during the build. |

#### How it works

Your container image does not change. On AWS, a task definition describes the image and its sizing, and an ECS service keeps a desired number of copies running on Fargate behind a load balancer. When Tensor9 builds your release, it translates the task definition and service into Kubernetes objects on a cluster you already operate: a **Deployment** (a **DaemonSet** for the DAEMON strategy) and a **Service**.

After deployment, clients reach your containers through the cluster's load balancer or cluster DNS. Tensor9 does not proxy application traffic.

![On AWS, your container image runs as an ECS service on Fargate behind an Application Load Balancer. After the move, the same image runs on a cluster you already operate as a Kubernetes Deployment or DaemonSet plus a Service, behind the cluster's load balancer. Tensor9 is not in the request path.](data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSI4MzYiIGhlaWdodD0iMjAwIiB2aWV3Qm94PSIwIDAgODM2IDIwMCIgcm9sZT0iaW1nIiBhcmlhLWxhYmVsPSJPbiBBV1MsIHlvdXIgY29udGFpbmVyIGltYWdlIHJ1bnMgYXMgYW4gRUNTIHNlcnZpY2Ugb24gRmFyZ2F0ZSBiZWhpbmQgYW4gQXBwbGljYXRpb24gTG9hZCBCYWxhbmNlci4gQWZ0ZXIgdGhlIG1vdmUsIHRoZSBzYW1lIGltYWdlIHJ1bnMgb24gYSBjbHVzdGVyIHlvdSBhbHJlYWR5IG9wZXJhdGUgYXMgYSBLdWJlcm5ldGVzIERlcGxveW1lbnQgb3IgRGFlbW9uU2V0IHBsdXMgYSBTZXJ2aWNlLCBiZWhpbmQgdGhlIGNsdXN0ZXIncyBsb2FkIGJhbGFuY2VyLiBUZW5zb3I5IGlzIG5vdCBpbiB0aGUgcmVxdWVzdCBwYXRoLiI+PHN0eWxlPnRleHR7Zm9udC1mYW1pbHk6SW50ZXIsLWFwcGxlLXN5c3RlbSxCbGlua01hY1N5c3RlbUZvbnQsJ1NlZ29lIFVJJyxSb2JvdG8sJ0hlbHZldGljYSBOZXVlJyxBcmlhbCxzYW5zLXNlcmlmO2ZpbGw6IzMzNDE1NX08L3N0eWxlPgo8ZGVmcz48bWFya2VyIGlkPSJlazhzLWh3IiB2aWV3Qm94PSIwIDAgMTAgMTAiIHJlZlg9IjgiIHJlZlk9IjUiIG1hcmtlcldpZHRoPSI3IiBtYXJrZXJIZWlnaHQ9IjciIG9yaWVudD0iYXV0by1zdGFydC1yZXZlcnNlIj48cGF0aCBkPSJNMCwwIEwxMCw1IEwwLDEwIHoiIHN0eWxlPSJmaWxsOiM5NGEzYjgiLz48L21hcmtlcj48L2RlZnM+CjxyZWN0IHg9IjE2IiB5PSI0NiIgd2lkdGg9IjM1OCIgaGVpZ2h0PSIxMzIiIHJ4PSIxNCIgc3Ryb2tlLXdpZHRoPSIxLjQiIHN0cm9rZS1kYXNoYXJyYXk9IjUgNSIgc3R5bGU9ImZpbGw6I2Y4ZmFmYztzdHJva2U6I2NiZDVlMSIvPgo8dGV4dCB4PSIzMCIgeT0iNjQiIHN0eWxlPSJmb250OiA3MDAgMTBweCBJbnRlciwgc2Fucy1zZXJpZjsgbGV0dGVyLXNwYWNpbmc6IDEuM3B4OyBmaWxsOiAjOTRhM2I4OyBmaWxsOiM2NDc0OGIiPk9OIEFXUyBUT0RBWTwvdGV4dD4KPHJlY3QgeD0iMzAiIHk9Ijg2IiB3aWR0aD0iODQiIGhlaWdodD0iNjAiIHJ4PSIxMSIgc3Ryb2tlLXdpZHRoPSIxLjUiIHN0eWxlPSJmaWxsOiNmZmZmZmY7c3Ryb2tlOiNjYmQ1ZTEiLz4KPHRleHQgeD0iNzIiIHk9IjExMCIgdGV4dC1hbmNob3I9Im1pZGRsZSIgc3R5bGU9ImZvbnQ6IDY1MCAxMy41cHggSW50ZXIsIHNhbnMtc2VyaWY7IGZpbGw6ICMwZjE3MmE7IGZvbnQtc2l6ZToxMS41cHgiPllvdXIgaW1hZ2U8L3RleHQ+Cjx0ZXh0IHg9IjcyIiB5PSIxMjgiIHRleHQtYW5jaG9yPSJtaWRkbGUiIHN0eWxlPSJmb250OiAxMXB4IEludGVyLCBzYW5zLXNlcmlmOyBmaWxsOiAjNjQ3NDhiIj5jb250YWluZXI8L3RleHQ+CjxsaW5lIHgxPSIxMTQiIHkxPSIxMTYiIHgyPSIxNDYiIHkyPSIxMTYiIHN0cm9rZS13aWR0aD0iMiIgbWFya2VyLWVuZD0idXJsKCNlazhzLWh3KSIgc3R5bGU9InN0cm9rZTojOTRhM2I4Ii8+CjxyZWN0IHg9IjE0OCIgeT0iODYiIHdpZHRoPSIxMTQiIGhlaWdodD0iNjAiIHJ4PSIxMSIgc3Ryb2tlLXdpZHRoPSIxLjUiIHN0eWxlPSJmaWxsOiNmZmZmZmY7c3Ryb2tlOiNjYmQ1ZTEiLz4KPHRleHQgeD0iMjA1IiB5PSIxMTAiIHRleHQtYW5jaG9yPSJtaWRkbGUiIHN0eWxlPSJmb250OiA2NTAgMTMuNXB4IEludGVyLCBzYW5zLXNlcmlmOyBmaWxsOiAjMGYxNzJhOyBmb250LXNpemU6MTEuNXB4Ij5FQ1Mgc2VydmljZTwvdGV4dD4KPHRleHQgeD0iMjA1IiB5PSIxMjgiIHRleHQtYW5jaG9yPSJtaWRkbGUiIHN0eWxlPSJmb250OiAxMXB4IEludGVyLCBzYW5zLXNlcmlmOyBmaWxsOiAjNjQ3NDhiIj5vbiBGYXJnYXRlPC90ZXh0Pgo8bGluZSB4MT0iMjYyIiB5MT0iMTE2IiB4Mj0iMjkwIiB5Mj0iMTE2IiBzdHJva2Utd2lkdGg9IjIiIG1hcmtlci1lbmQ9InVybCgjZWs4cy1odykiIHN0eWxlPSJzdHJva2U6Izk0YTNiOCIvPgo8cmVjdCB4PSIyOTIiIHk9Ijg2IiB3aWR0aD0iNzAiIGhlaWdodD0iNjAiIHJ4PSIxMSIgc3Ryb2tlLXdpZHRoPSIxLjUiIHN0eWxlPSJmaWxsOiNmZmZmZmY7c3Ryb2tlOiNjYmQ1ZTEiLz4KPHRleHQgeD0iMzI3IiB5PSIxMTAiIHRleHQtYW5jaG9yPSJtaWRkbGUiIHN0eWxlPSJmb250OiA2NTAgMTMuNXB4IEludGVyLCBzYW5zLXNlcmlmOyBmaWxsOiAjMGYxNzJhOyBmb250LXNpemU6MTFweCI+QUxCPC90ZXh0Pgo8dGV4dCB4PSIzMjciIHk9IjEyOCIgdGV4dC1hbmNob3I9Im1pZGRsZSIgc3R5bGU9ImZvbnQ6IDExcHggSW50ZXIsIHNhbnMtc2VyaWY7IGZpbGw6ICM2NDc0OGIiPnRyYWZmaWM8L3RleHQ+Cjx0ZXh0IHg9IjQxOCIgeT0iMzQiIHRleHQtYW5jaG9yPSJtaWRkbGUiIHN0eWxlPSJmb250OiAxMC41cHggSW50ZXIsIHNhbnMtc2VyaWY7IGZpbGw6ICMwNDc4NTc7IGZvbnQtd2VpZ2h0OjcwMCI+dHJhbnNsYXRlZCBhdCBkZXBsb3kgdGltZTwvdGV4dD4KPHJlY3QgeD0iNDYyIiB5PSI0NiIgd2lkdGg9IjM2MiIgaGVpZ2h0PSIxMzIiIHJ4PSIxNCIgc3Ryb2tlLXdpZHRoPSIxLjQiIHN0cm9rZS1kYXNoYXJyYXk9IjUgNSIgc3R5bGU9ImZpbGw6I2Y4ZmFmYztzdHJva2U6I2NiZDVlMSIvPgo8dGV4dCB4PSI0NzYiIHk9IjY0IiBzdHlsZT0iZm9udDogNzAwIDEwcHggSW50ZXIsIHNhbnMtc2VyaWY7IGxldHRlci1zcGFjaW5nOiAxLjNweDsgZmlsbDogIzk0YTNiODsgZmlsbDojMDQ3ODU3Ij5PTiBBIENMVVNURVIgWU9VIE9QRVJBVEU8L3RleHQ+CjxyZWN0IHg9IjQ3NiIgeT0iODAiIHdpZHRoPSI4MCIgaGVpZ2h0PSI1NiIgcng9IjExIiBzdHJva2Utd2lkdGg9IjEuNSIgc3R5bGU9ImZpbGw6I2ZmZmZmZjtzdHJva2U6I2NiZDVlMSIvPgo8dGV4dCB4PSI1MTYiIHk9IjEwNCIgdGV4dC1hbmNob3I9Im1pZGRsZSIgc3R5bGU9ImZvbnQ6IDY1MCAxMy41cHggSW50ZXIsIHNhbnMtc2VyaWY7IGZpbGw6ICMwZjE3MmE7IGZvbnQtc2l6ZToxMS41cHgiPlNhbWUgaW1hZ2U8L3RleHQ+Cjx0ZXh0IHg9IjUxNiIgeT0iMTIwIiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBzdHlsZT0iZm9udDogNjAwIDExcHggSW50ZXIsIHNhbnMtc2VyaWY7IGZpbGw6ICMwNDc4NTciPnVuY2hhbmdlZDwvdGV4dD4KPGxpbmUgeDE9IjU1NiIgeTE9IjEwOCIgeDI9IjU4NCIgeTI9IjEwOCIgc3Ryb2tlLXdpZHRoPSIyIiBtYXJrZXItZW5kPSJ1cmwoI2VrOHMtaHcpIiBzdHlsZT0ic3Ryb2tlOiM5NGEzYjgiLz4KPHJlY3QgeD0iNTg4IiB5PSI4MCIgd2lkdGg9IjE0OCIgaGVpZ2h0PSI1NiIgcng9IjExIiBzdHJva2Utd2lkdGg9IjEuNyIgc3R5bGU9ImZpbGw6I2VjZmRmNTtzdHJva2U6IzA0Nzg1NyIvPgo8dGV4dCB4PSI2NjIiIHk9IjEwNCIgdGV4dC1hbmNob3I9Im1pZGRsZSIgc3R5bGU9ImZvbnQ6IDcwMCAxMy41cHggSW50ZXIsIHNhbnMtc2VyaWY7IGZpbGw6ICMwNDc4NTc7IGZvbnQtc2l6ZToxMS41cHgiPkt1YmVybmV0ZXMgd29ya2xvYWQ8L3RleHQ+Cjx0ZXh0IHg9IjY2MiIgeT0iMTIwIiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBzdHlsZT0iZm9udDogMTAuNXB4IEludGVyLCBzYW5zLXNlcmlmOyBmaWxsOiAjMDQ3ODU3Ij5EZXBsb3ltZW50IG9yIERhZW1vblNldDwvdGV4dD4KPGxpbmUgeDE9IjczNiIgeTE9IjEwOCIgeDI9Ijc2MiIgeTI9IjEwOCIgc3Ryb2tlLXdpZHRoPSIyIiBtYXJrZXItZW5kPSJ1cmwoI2VrOHMtaHcpIiBzdHlsZT0ic3Ryb2tlOiM5NGEzYjgiLz4KPHJlY3QgeD0iNzY2IiB5PSI4MCIgd2lkdGg9IjUyIiBoZWlnaHQ9IjU2IiByeD0iMTEiIHN0cm9rZS13aWR0aD0iMS41IiBzdHlsZT0iZmlsbDojZmZmZmZmO3N0cm9rZTojY2JkNWUxIi8+Cjx0ZXh0IHg9Ijc5MiIgeT0iMTA0IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBzdHlsZT0iZm9udDogNjUwIDEzLjVweCBJbnRlciwgc2Fucy1zZXJpZjsgZmlsbDogIzBmMTcyYTsgZm9udC1zaXplOjEwcHgiPkNsdXN0ZXI8L3RleHQ+Cjx0ZXh0IHg9Ijc5MiIgeT0iMTIwIiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBzdHlsZT0iZm9udDogMTFweCBJbnRlciwgc2Fucy1zZXJpZjsgZmlsbDogIzY0NzQ4YiI+TEI8L3RleHQ+Cjx0ZXh0IHg9IjY0MyIgeT0iMTY0IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBzdHlsZT0iZm9udDogMTAuNXB4IEludGVyLCBzYW5zLXNlcmlmOyBmaWxsOiAjMDQ3ODU3OyBmb250LXdlaWdodDo3MDAiPlRlbnNvcjkgaXMgbm90IGluIHRoaXMgcGF0aDwvdGV4dD4KPC9zdmc+)

![On AWS, your container image runs as an ECS service on Fargate behind an Application Load Balancer. After the move, the same image runs on a cluster you already operate as a Kubernetes Deployment or DaemonSet plus a Service, behind the cluster's load balancer. Tensor9 is not in the request path.](data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSI4MzYiIGhlaWdodD0iMjAwIiB2aWV3Qm94PSIwIDAgODM2IDIwMCIgcm9sZT0iaW1nIiBhcmlhLWxhYmVsPSJPbiBBV1MsIHlvdXIgY29udGFpbmVyIGltYWdlIHJ1bnMgYXMgYW4gRUNTIHNlcnZpY2Ugb24gRmFyZ2F0ZSBiZWhpbmQgYW4gQXBwbGljYXRpb24gTG9hZCBCYWxhbmNlci4gQWZ0ZXIgdGhlIG1vdmUsIHRoZSBzYW1lIGltYWdlIHJ1bnMgb24gYSBjbHVzdGVyIHlvdSBhbHJlYWR5IG9wZXJhdGUgYXMgYSBLdWJlcm5ldGVzIERlcGxveW1lbnQgb3IgRGFlbW9uU2V0IHBsdXMgYSBTZXJ2aWNlLCBiZWhpbmQgdGhlIGNsdXN0ZXIncyBsb2FkIGJhbGFuY2VyLiBUZW5zb3I5IGlzIG5vdCBpbiB0aGUgcmVxdWVzdCBwYXRoLiI+PHN0eWxlPnRleHR7Zm9udC1mYW1pbHk6SW50ZXIsLWFwcGxlLXN5c3RlbSxCbGlua01hY1N5c3RlbUZvbnQsJ1NlZ29lIFVJJyxSb2JvdG8sJ0hlbHZldGljYSBOZXVlJyxBcmlhbCxzYW5zLXNlcmlmO2ZpbGw6I2NiZDVlMX08L3N0eWxlPgo8ZGVmcz48bWFya2VyIGlkPSJlazhzLWh3IiB2aWV3Qm94PSIwIDAgMTAgMTAiIHJlZlg9IjgiIHJlZlk9IjUiIG1hcmtlcldpZHRoPSI3IiBtYXJrZXJIZWlnaHQ9IjciIG9yaWVudD0iYXV0by1zdGFydC1yZXZlcnNlIj48cGF0aCBkPSJNMCwwIEwxMCw1IEwwLDEwIHoiIHN0eWxlPSJmaWxsOiM2NDc0OGIiLz48L21hcmtlcj48L2RlZnM+CjxyZWN0IHg9IjE2IiB5PSI0NiIgd2lkdGg9IjM1OCIgaGVpZ2h0PSIxMzIiIHJ4PSIxNCIgc3Ryb2tlLXdpZHRoPSIxLjQiIHN0cm9rZS1kYXNoYXJyYXk9IjUgNSIgc3R5bGU9ImZpbGw6IzBmMTcyYTtzdHJva2U6IzQ3NTU2OSIvPgo8dGV4dCB4PSIzMCIgeT0iNjQiIHN0eWxlPSJmb250OiA3MDAgMTBweCBJbnRlciwgc2Fucy1zZXJpZjsgbGV0dGVyLXNwYWNpbmc6IDEuM3B4OyBmaWxsOiAjNjQ3NDhiOyBmaWxsOiM5NGEzYjgiPk9OIEFXUyBUT0RBWTwvdGV4dD4KPHJlY3QgeD0iMzAiIHk9Ijg2IiB3aWR0aD0iODQiIGhlaWdodD0iNjAiIHJ4PSIxMSIgc3Ryb2tlLXdpZHRoPSIxLjUiIHN0eWxlPSJmaWxsOiMxZTI5M2I7c3Ryb2tlOiM0NzU1NjkiLz4KPHRleHQgeD0iNzIiIHk9IjExMCIgdGV4dC1hbmNob3I9Im1pZGRsZSIgc3R5bGU9ImZvbnQ6IDY1MCAxMy41cHggSW50ZXIsIHNhbnMtc2VyaWY7IGZpbGw6ICNmMWY1Zjk7IGZvbnQtc2l6ZToxMS41cHgiPllvdXIgaW1hZ2U8L3RleHQ+Cjx0ZXh0IHg9IjcyIiB5PSIxMjgiIHRleHQtYW5jaG9yPSJtaWRkbGUiIHN0eWxlPSJmb250OiAxMXB4IEludGVyLCBzYW5zLXNlcmlmOyBmaWxsOiAjOTRhM2I4Ij5jb250YWluZXI8L3RleHQ+CjxsaW5lIHgxPSIxMTQiIHkxPSIxMTYiIHgyPSIxNDYiIHkyPSIxMTYiIHN0cm9rZS13aWR0aD0iMiIgbWFya2VyLWVuZD0idXJsKCNlazhzLWh3KSIgc3R5bGU9InN0cm9rZTojNjQ3NDhiIi8+CjxyZWN0IHg9IjE0OCIgeT0iODYiIHdpZHRoPSIxMTQiIGhlaWdodD0iNjAiIHJ4PSIxMSIgc3Ryb2tlLXdpZHRoPSIxLjUiIHN0eWxlPSJmaWxsOiMxZTI5M2I7c3Ryb2tlOiM0NzU1NjkiLz4KPHRleHQgeD0iMjA1IiB5PSIxMTAiIHRleHQtYW5jaG9yPSJtaWRkbGUiIHN0eWxlPSJmb250OiA2NTAgMTMuNXB4IEludGVyLCBzYW5zLXNlcmlmOyBmaWxsOiAjZjFmNWY5OyBmb250LXNpemU6MTEuNXB4Ij5FQ1Mgc2VydmljZTwvdGV4dD4KPHRleHQgeD0iMjA1IiB5PSIxMjgiIHRleHQtYW5jaG9yPSJtaWRkbGUiIHN0eWxlPSJmb250OiAxMXB4IEludGVyLCBzYW5zLXNlcmlmOyBmaWxsOiAjOTRhM2I4Ij5vbiBGYXJnYXRlPC90ZXh0Pgo8bGluZSB4MT0iMjYyIiB5MT0iMTE2IiB4Mj0iMjkwIiB5Mj0iMTE2IiBzdHJva2Utd2lkdGg9IjIiIG1hcmtlci1lbmQ9InVybCgjZWs4cy1odykiIHN0eWxlPSJzdHJva2U6IzY0NzQ4YiIvPgo8cmVjdCB4PSIyOTIiIHk9Ijg2IiB3aWR0aD0iNzAiIGhlaWdodD0iNjAiIHJ4PSIxMSIgc3Ryb2tlLXdpZHRoPSIxLjUiIHN0eWxlPSJmaWxsOiMxZTI5M2I7c3Ryb2tlOiM0NzU1NjkiLz4KPHRleHQgeD0iMzI3IiB5PSIxMTAiIHRleHQtYW5jaG9yPSJtaWRkbGUiIHN0eWxlPSJmb250OiA2NTAgMTMuNXB4IEludGVyLCBzYW5zLXNlcmlmOyBmaWxsOiAjZjFmNWY5OyBmb250LXNpemU6MTFweCI+QUxCPC90ZXh0Pgo8dGV4dCB4PSIzMjciIHk9IjEyOCIgdGV4dC1hbmNob3I9Im1pZGRsZSIgc3R5bGU9ImZvbnQ6IDExcHggSW50ZXIsIHNhbnMtc2VyaWY7IGZpbGw6ICM5NGEzYjgiPnRyYWZmaWM8L3RleHQ+Cjx0ZXh0IHg9IjQxOCIgeT0iMzQiIHRleHQtYW5jaG9yPSJtaWRkbGUiIHN0eWxlPSJmb250OiAxMC41cHggSW50ZXIsIHNhbnMtc2VyaWY7IGZpbGw6ICM2ZWU3Yjc7IGZvbnQtd2VpZ2h0OjcwMCI+dHJhbnNsYXRlZCBhdCBkZXBsb3kgdGltZTwvdGV4dD4KPHJlY3QgeD0iNDYyIiB5PSI0NiIgd2lkdGg9IjM2MiIgaGVpZ2h0PSIxMzIiIHJ4PSIxNCIgc3Ryb2tlLXdpZHRoPSIxLjQiIHN0cm9rZS1kYXNoYXJyYXk9IjUgNSIgc3R5bGU9ImZpbGw6IzBmMTcyYTtzdHJva2U6IzQ3NTU2OSIvPgo8dGV4dCB4PSI0NzYiIHk9IjY0IiBzdHlsZT0iZm9udDogNzAwIDEwcHggSW50ZXIsIHNhbnMtc2VyaWY7IGxldHRlci1zcGFjaW5nOiAxLjNweDsgZmlsbDogIzY0NzQ4YjsgZmlsbDojNmVlN2I3Ij5PTiBBIENMVVNURVIgWU9VIE9QRVJBVEU8L3RleHQ+CjxyZWN0IHg9IjQ3NiIgeT0iODAiIHdpZHRoPSI4MCIgaGVpZ2h0PSI1NiIgcng9IjExIiBzdHJva2Utd2lkdGg9IjEuNSIgc3R5bGU9ImZpbGw6IzFlMjkzYjtzdHJva2U6IzQ3NTU2OSIvPgo8dGV4dCB4PSI1MTYiIHk9IjEwNCIgdGV4dC1hbmNob3I9Im1pZGRsZSIgc3R5bGU9ImZvbnQ6IDY1MCAxMy41cHggSW50ZXIsIHNhbnMtc2VyaWY7IGZpbGw6ICNmMWY1Zjk7IGZvbnQtc2l6ZToxMS41cHgiPlNhbWUgaW1hZ2U8L3RleHQ+Cjx0ZXh0IHg9IjUxNiIgeT0iMTIwIiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBzdHlsZT0iZm9udDogNjAwIDExcHggSW50ZXIsIHNhbnMtc2VyaWY7IGZpbGw6ICM2ZWU3YjciPnVuY2hhbmdlZDwvdGV4dD4KPGxpbmUgeDE9IjU1NiIgeTE9IjEwOCIgeDI9IjU4NCIgeTI9IjEwOCIgc3Ryb2tlLXdpZHRoPSIyIiBtYXJrZXItZW5kPSJ1cmwoI2VrOHMtaHcpIiBzdHlsZT0ic3Ryb2tlOiM2NDc0OGIiLz4KPHJlY3QgeD0iNTg4IiB5PSI4MCIgd2lkdGg9IjE0OCIgaGVpZ2h0PSI1NiIgcng9IjExIiBzdHJva2Utd2lkdGg9IjEuNyIgc3R5bGU9ImZpbGw6IzA2NGUzYjtzdHJva2U6IzZlZTdiNyIvPgo8dGV4dCB4PSI2NjIiIHk9IjEwNCIgdGV4dC1hbmNob3I9Im1pZGRsZSIgc3R5bGU9ImZvbnQ6IDcwMCAxMy41cHggSW50ZXIsIHNhbnMtc2VyaWY7IGZpbGw6ICM2ZWU3Yjc7IGZvbnQtc2l6ZToxMS41cHgiPkt1YmVybmV0ZXMgd29ya2xvYWQ8L3RleHQ+Cjx0ZXh0IHg9IjY2MiIgeT0iMTIwIiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBzdHlsZT0iZm9udDogMTAuNXB4IEludGVyLCBzYW5zLXNlcmlmOyBmaWxsOiAjNmVlN2I3Ij5EZXBsb3ltZW50IG9yIERhZW1vblNldDwvdGV4dD4KPGxpbmUgeDE9IjczNiIgeTE9IjEwOCIgeDI9Ijc2MiIgeTI9IjEwOCIgc3Ryb2tlLXdpZHRoPSIyIiBtYXJrZXItZW5kPSJ1cmwoI2VrOHMtaHcpIiBzdHlsZT0ic3Ryb2tlOiM2NDc0OGIiLz4KPHJlY3QgeD0iNzY2IiB5PSI4MCIgd2lkdGg9IjUyIiBoZWlnaHQ9IjU2IiByeD0iMTEiIHN0cm9rZS13aWR0aD0iMS41IiBzdHlsZT0iZmlsbDojMWUyOTNiO3N0cm9rZTojNDc1NTY5Ii8+Cjx0ZXh0IHg9Ijc5MiIgeT0iMTA0IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBzdHlsZT0iZm9udDogNjUwIDEzLjVweCBJbnRlciwgc2Fucy1zZXJpZjsgZmlsbDogI2YxZjVmOTsgZm9udC1zaXplOjEwcHgiPkNsdXN0ZXI8L3RleHQ+Cjx0ZXh0IHg9Ijc5MiIgeT0iMTIwIiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBzdHlsZT0iZm9udDogMTFweCBJbnRlciwgc2Fucy1zZXJpZjsgZmlsbDogIzk0YTNiOCI+TEI8L3RleHQ+Cjx0ZXh0IHg9IjY0MyIgeT0iMTY0IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBzdHlsZT0iZm9udDogMTAuNXB4IEludGVyLCBzYW5zLXNlcmlmOyBmaWxsOiAjNmVlN2I3OyBmb250LXdlaWdodDo3MDAiPlRlbnNvcjkgaXMgbm90IGluIHRoaXMgcGF0aDwvdGV4dD4KPC9zdmc+)

Tensor9 translates your task definition and service before deployment; afterwards the cluster's load balancer carries every request.

#### The task definition and service

Every container in the task definition becomes a container in one Kubernetes **Pod**, so a main container and its helper containers stay together. Tensor9 copies each image to your registry during the build. Fargate sizes a task from fixed CPU and memory combinations (0.25 to 16 vCPU); on the target cluster those values become Pod `requests` and `limits`, without the fixed combinations. The requested resources must fit node capacity, scheduling rules and quota.

The service's desired count becomes the Deployment's `replicas`: the number of Pods Kubernetes keeps running, not a promise that they are all ready. Scale-to-zero is off unless you add it with KEDA or Knative. **Application Auto Scaling** becomes a **HorizontalPodAutoscaler** on CPU, memory or a custom metric. A rolling update uses the Deployment's `RollingUpdate` settings, `maxSurge` and `maxUnavailable`. The **DAEMON** strategy becomes a **DaemonSet** (one Pod per node), and **ECS Exec** becomes `kubectl exec` into the Pod.

![A task definition's containers, image and CPU and memory sizing become a Kubernetes Pod spec, and an ECS service's desired count becomes a Deployment's replica count. CPU and memory become Pod requests and limits. The DAEMON strategy becomes a DaemonSet, and ECS Exec becomes kubectl exec.](data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSI4MzYiIGhlaWdodD0iMjMyIiB2aWV3Qm94PSIwIDAgODM2IDIzMiIgcm9sZT0iaW1nIiBhcmlhLWxhYmVsPSJBIHRhc2sgZGVmaW5pdGlvbidzIGNvbnRhaW5lcnMsIGltYWdlIGFuZCBDUFUgYW5kIG1lbW9yeSBzaXppbmcgYmVjb21lIGEgS3ViZXJuZXRlcyBQb2Qgc3BlYywgYW5kIGFuIEVDUyBzZXJ2aWNlJ3MgZGVzaXJlZCBjb3VudCBiZWNvbWVzIGEgRGVwbG95bWVudCdzIHJlcGxpY2EgY291bnQuIENQVSBhbmQgbWVtb3J5IGJlY29tZSBQb2QgcmVxdWVzdHMgYW5kIGxpbWl0cy4gVGhlIERBRU1PTiBzdHJhdGVneSBiZWNvbWVzIGEgRGFlbW9uU2V0LCBhbmQgRUNTIEV4ZWMgYmVjb21lcyBrdWJlY3RsIGV4ZWMuIj48c3R5bGU+dGV4dHtmb250LWZhbWlseTpJbnRlciwtYXBwbGUtc3lzdGVtLEJsaW5rTWFjU3lzdGVtRm9udCwnU2Vnb2UgVUknLFJvYm90bywnSGVsdmV0aWNhIE5ldWUnLEFyaWFsLHNhbnMtc2VyaWY7ZmlsbDojMzM0MTU1fTwvc3R5bGU+CjxkZWZzPjxtYXJrZXIgaWQ9ImVrOHMtdGQiIHZpZXdCb3g9IjAgMCAxMCAxMCIgcmVmWD0iOCIgcmVmWT0iNSIgbWFya2VyV2lkdGg9IjciIG1hcmtlckhlaWdodD0iNyIgb3JpZW50PSJhdXRvLXN0YXJ0LXJldmVyc2UiPjxwYXRoIGQ9Ik0wLDAgTDEwLDUgTDAsMTAgeiIgc3R5bGU9ImZpbGw6IzA0Nzg1NyIvPjwvbWFya2VyPjwvZGVmcz4KPHJlY3QgeD0iMjQiIHk9IjMwIiB3aWR0aD0iMjg2IiBoZWlnaHQ9IjEyMCIgcng9IjEyIiBzdHJva2Utd2lkdGg9IjEuNSIgc3R5bGU9ImZpbGw6I2ZmZmZmZjtzdHJva2U6I2NiZDVlMSIvPgo8dGV4dCB4PSIxNjciIHk9IjUyIiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBzdHlsZT0iZm9udDogNjUwIDEzLjVweCBJbnRlciwgc2Fucy1zZXJpZjsgZmlsbDogIzBmMTcyYTsgZm9udC1zaXplOjExLjVweCI+VGFzayBkZWZpbml0aW9uICsgc2VydmljZTwvdGV4dD4KPHRleHQgeD0iNDIiIHk9Ijc4IiBzdHlsZT0iZm9udDogMTFweCAnU0YgTW9ubycsIHVpLW1vbm9zcGFjZSwgJ0pldEJyYWlucyBNb25vJywgTWVubG8sIG1vbm9zcGFjZTsgZmlsbDogIzMzNDE1NSI+Y29udGFpbmVycyDCtyBpbWFnZTwvdGV4dD4KPHRleHQgeD0iNDIiIHk9IjEwMCIgc3R5bGU9ImZvbnQ6IDExcHggJ1NGIE1vbm8nLCB1aS1tb25vc3BhY2UsICdKZXRCcmFpbnMgTW9ubycsIE1lbmxvLCBtb25vc3BhY2U7IGZpbGw6ICMzMzQxNTUiPmNwdTogMTAyNCDCtyBtZW1vcnk6IDIwNDg8L3RleHQ+Cjx0ZXh0IHg9IjQyIiB5PSIxMjIiIHN0eWxlPSJmb250OiAxMXB4ICdTRiBNb25vJywgdWktbW9ub3NwYWNlLCAnSmV0QnJhaW5zIE1vbm8nLCBNZW5sbywgbW9ub3NwYWNlOyBmaWxsOiAjMzM0MTU1Ij5kZXNpcmVkQ291bnQ6IDMgwrcgYXV0b3NjYWxpbmc8L3RleHQ+Cjx0ZXh0IHg9IjE2NyIgeT0iMTQyIiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBzdHlsZT0iZm9udDogMTFweCBJbnRlciwgc2Fucy1zZXJpZjsgZmlsbDogIzY0NzQ4YiI+d2hhdCB5b3UgZGVjbGFyZSBvbiBBV1M8L3RleHQ+CjxsaW5lIHgxPSIzMTAiIHkxPSI5MCIgeDI9IjM3MiIgeTI9IjkwIiBzdHJva2Utd2lkdGg9IjIiIG1hcmtlci1lbmQ9InVybCgjZWs4cy10ZCkiIHN0eWxlPSJzdHJva2U6IzA0Nzg1NyIvPgo8dGV4dCB4PSIzNDEiIHk9IjgyIiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBzdHlsZT0iZm9udDogMTAuNXB4IEludGVyLCBzYW5zLXNlcmlmOyBmaWxsOiAjMDQ3ODU3OyBmb250LXNpemU6OXB4Ij5hdCBkZXBsb3k8L3RleHQ+CjxyZWN0IHg9IjM3NiIgeT0iMzAiIHdpZHRoPSI0MzYiIGhlaWdodD0iMTIwIiByeD0iMTIiIHN0cm9rZS13aWR0aD0iMS42IiBzdHlsZT0iZmlsbDojZWNmZGY1O3N0cm9rZTojMDQ3ODU3Ii8+Cjx0ZXh0IHg9IjU5NCIgeT0iNTIiIHRleHQtYW5jaG9yPSJtaWRkbGUiIHN0eWxlPSJmb250OiA3MDAgMTMuNXB4IEludGVyLCBzYW5zLXNlcmlmOyBmaWxsOiAjMDQ3ODU3OyBmb250LXNpemU6MTEuNXB4Ij5EZXBsb3ltZW50ICsgU2VydmljZSBvbiB0aGUgdGFyZ2V0IGNsdXN0ZXI8L3RleHQ+Cjx0ZXh0IHg9IjM5NCIgeT0iNzgiIHN0eWxlPSJmb250OiAxMC41cHggSW50ZXIsIHNhbnMtc2VyaWY7IGZpbGw6ICMwNDc4NTciPlBvZCBzcGVjIMK3IGFsbCBjb250YWluZXJzIGluIG9uZSBQb2Q8L3RleHQ+Cjx0ZXh0IHg9IjM5NCIgeT0iMTAwIiBzdHlsZT0iZm9udDogMTAuNXB4IEludGVyLCBzYW5zLXNlcmlmOyBmaWxsOiAjMDQ3ODU3Ij5jcHUgwrcgbWVtb3J5IOKGkiBQb2QgcmVxdWVzdHMgYW5kIGxpbWl0czwvdGV4dD4KPHRleHQgeD0iMzk0IiB5PSIxMjIiIHN0eWxlPSJmb250OiAxMC41cHggSW50ZXIsIHNhbnMtc2VyaWY7IGZpbGw6ICMwNDc4NTciPmRlc2lyZWRDb3VudCDihpIgcmVwbGljYXM6IDMgwrcgYXV0b3NjYWxpbmcg4oaSIEhQQTwvdGV4dD4KPHJlY3QgeD0iMjQiIHk9IjE2NiIgd2lkdGg9IjM4NiIgaGVpZ2h0PSI0NiIgcng9IjEwIiBzdHJva2Utd2lkdGg9IjEuMyIgc3R5bGU9ImZpbGw6I2Y4ZmFmYztzdHJva2U6I2NiZDVlMSIvPgo8dGV4dCB4PSIyMTciIHk9IjE4NSIgdGV4dC1hbmNob3I9Im1pZGRsZSIgc3R5bGU9ImZvbnQ6IDY1MCAxMy41cHggSW50ZXIsIHNhbnMtc2VyaWY7IGZpbGw6ICMwZjE3MmE7IGZvbnQtc2l6ZToxMXB4Ij5EQUVNT04gc3RyYXRlZ3kg4oaSIERhZW1vblNldDwvdGV4dD4KPHRleHQgeD0iMjE3IiB5PSIyMDIiIHRleHQtYW5jaG9yPSJtaWRkbGUiIHN0eWxlPSJmb250OiAxMXB4IEludGVyLCBzYW5zLXNlcmlmOyBmaWxsOiAjNjQ3NDhiIj5vbmUgUG9kIHBlciBub2RlPC90ZXh0Pgo8cmVjdCB4PSI0MjYiIHk9IjE2NiIgd2lkdGg9IjM4NiIgaGVpZ2h0PSI0NiIgcng9IjEwIiBzdHJva2Utd2lkdGg9IjEuMyIgc3R5bGU9ImZpbGw6I2Y4ZmFmYztzdHJva2U6I2NiZDVlMSIvPgo8dGV4dCB4PSI2MTkiIHk9IjE4NSIgdGV4dC1hbmNob3I9Im1pZGRsZSIgc3R5bGU9ImZvbnQ6IDY1MCAxMy41cHggSW50ZXIsIHNhbnMtc2VyaWY7IGZpbGw6ICMwZjE3MmE7IGZvbnQtc2l6ZToxMXB4Ij5FQ1MgRXhlYyDihpIga3ViZWN0bCBleGVjPC90ZXh0Pgo8dGV4dCB4PSI2MTkiIHk9IjIwMiIgdGV4dC1hbmNob3I9Im1pZGRsZSIgc3R5bGU9ImZvbnQ6IDExcHggSW50ZXIsIHNhbnMtc2VyaWY7IGZpbGw6ICM2NDc0OGIiPmEgc2hlbGwgaW4gdGhlIHJ1bm5pbmcgUG9kPC90ZXh0Pgo8L3N2Zz4=)

![A task definition's containers, image and CPU and memory sizing become a Kubernetes Pod spec, and an ECS service's desired count becomes a Deployment's replica count. CPU and memory become Pod requests and limits. The DAEMON strategy becomes a DaemonSet, and ECS Exec becomes kubectl exec.](data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSI4MzYiIGhlaWdodD0iMjMyIiB2aWV3Qm94PSIwIDAgODM2IDIzMiIgcm9sZT0iaW1nIiBhcmlhLWxhYmVsPSJBIHRhc2sgZGVmaW5pdGlvbidzIGNvbnRhaW5lcnMsIGltYWdlIGFuZCBDUFUgYW5kIG1lbW9yeSBzaXppbmcgYmVjb21lIGEgS3ViZXJuZXRlcyBQb2Qgc3BlYywgYW5kIGFuIEVDUyBzZXJ2aWNlJ3MgZGVzaXJlZCBjb3VudCBiZWNvbWVzIGEgRGVwbG95bWVudCdzIHJlcGxpY2EgY291bnQuIENQVSBhbmQgbWVtb3J5IGJlY29tZSBQb2QgcmVxdWVzdHMgYW5kIGxpbWl0cy4gVGhlIERBRU1PTiBzdHJhdGVneSBiZWNvbWVzIGEgRGFlbW9uU2V0LCBhbmQgRUNTIEV4ZWMgYmVjb21lcyBrdWJlY3RsIGV4ZWMuIj48c3R5bGU+dGV4dHtmb250LWZhbWlseTpJbnRlciwtYXBwbGUtc3lzdGVtLEJsaW5rTWFjU3lzdGVtRm9udCwnU2Vnb2UgVUknLFJvYm90bywnSGVsdmV0aWNhIE5ldWUnLEFyaWFsLHNhbnMtc2VyaWY7ZmlsbDojY2JkNWUxfTwvc3R5bGU+CjxkZWZzPjxtYXJrZXIgaWQ9ImVrOHMtdGQiIHZpZXdCb3g9IjAgMCAxMCAxMCIgcmVmWD0iOCIgcmVmWT0iNSIgbWFya2VyV2lkdGg9IjciIG1hcmtlckhlaWdodD0iNyIgb3JpZW50PSJhdXRvLXN0YXJ0LXJldmVyc2UiPjxwYXRoIGQ9Ik0wLDAgTDEwLDUgTDAsMTAgeiIgc3R5bGU9ImZpbGw6IzZlZTdiNyIvPjwvbWFya2VyPjwvZGVmcz4KPHJlY3QgeD0iMjQiIHk9IjMwIiB3aWR0aD0iMjg2IiBoZWlnaHQ9IjEyMCIgcng9IjEyIiBzdHJva2Utd2lkdGg9IjEuNSIgc3R5bGU9ImZpbGw6IzFlMjkzYjtzdHJva2U6IzQ3NTU2OSIvPgo8dGV4dCB4PSIxNjciIHk9IjUyIiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBzdHlsZT0iZm9udDogNjUwIDEzLjVweCBJbnRlciwgc2Fucy1zZXJpZjsgZmlsbDogI2YxZjVmOTsgZm9udC1zaXplOjExLjVweCI+VGFzayBkZWZpbml0aW9uICsgc2VydmljZTwvdGV4dD4KPHRleHQgeD0iNDIiIHk9Ijc4IiBzdHlsZT0iZm9udDogMTFweCAnU0YgTW9ubycsIHVpLW1vbm9zcGFjZSwgJ0pldEJyYWlucyBNb25vJywgTWVubG8sIG1vbm9zcGFjZTsgZmlsbDogI2NiZDVlMSI+Y29udGFpbmVycyDCtyBpbWFnZTwvdGV4dD4KPHRleHQgeD0iNDIiIHk9IjEwMCIgc3R5bGU9ImZvbnQ6IDExcHggJ1NGIE1vbm8nLCB1aS1tb25vc3BhY2UsICdKZXRCcmFpbnMgTW9ubycsIE1lbmxvLCBtb25vc3BhY2U7IGZpbGw6ICNjYmQ1ZTEiPmNwdTogMTAyNCDCtyBtZW1vcnk6IDIwNDg8L3RleHQ+Cjx0ZXh0IHg9IjQyIiB5PSIxMjIiIHN0eWxlPSJmb250OiAxMXB4ICdTRiBNb25vJywgdWktbW9ub3NwYWNlLCAnSmV0QnJhaW5zIE1vbm8nLCBNZW5sbywgbW9ub3NwYWNlOyBmaWxsOiAjY2JkNWUxIj5kZXNpcmVkQ291bnQ6IDMgwrcgYXV0b3NjYWxpbmc8L3RleHQ+Cjx0ZXh0IHg9IjE2NyIgeT0iMTQyIiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBzdHlsZT0iZm9udDogMTFweCBJbnRlciwgc2Fucy1zZXJpZjsgZmlsbDogIzk0YTNiOCI+d2hhdCB5b3UgZGVjbGFyZSBvbiBBV1M8L3RleHQ+CjxsaW5lIHgxPSIzMTAiIHkxPSI5MCIgeDI9IjM3MiIgeTI9IjkwIiBzdHJva2Utd2lkdGg9IjIiIG1hcmtlci1lbmQ9InVybCgjZWs4cy10ZCkiIHN0eWxlPSJzdHJva2U6IzZlZTdiNyIvPgo8dGV4dCB4PSIzNDEiIHk9IjgyIiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBzdHlsZT0iZm9udDogMTAuNXB4IEludGVyLCBzYW5zLXNlcmlmOyBmaWxsOiAjNmVlN2I3OyBmb250LXNpemU6OXB4Ij5hdCBkZXBsb3k8L3RleHQ+CjxyZWN0IHg9IjM3NiIgeT0iMzAiIHdpZHRoPSI0MzYiIGhlaWdodD0iMTIwIiByeD0iMTIiIHN0cm9rZS13aWR0aD0iMS42IiBzdHlsZT0iZmlsbDojMDY0ZTNiO3N0cm9rZTojNmVlN2I3Ii8+Cjx0ZXh0IHg9IjU5NCIgeT0iNTIiIHRleHQtYW5jaG9yPSJtaWRkbGUiIHN0eWxlPSJmb250OiA3MDAgMTMuNXB4IEludGVyLCBzYW5zLXNlcmlmOyBmaWxsOiAjNmVlN2I3OyBmb250LXNpemU6MTEuNXB4Ij5EZXBsb3ltZW50ICsgU2VydmljZSBvbiB0aGUgdGFyZ2V0IGNsdXN0ZXI8L3RleHQ+Cjx0ZXh0IHg9IjM5NCIgeT0iNzgiIHN0eWxlPSJmb250OiAxMC41cHggSW50ZXIsIHNhbnMtc2VyaWY7IGZpbGw6ICM2ZWU3YjciPlBvZCBzcGVjIMK3IGFsbCBjb250YWluZXJzIGluIG9uZSBQb2Q8L3RleHQ+Cjx0ZXh0IHg9IjM5NCIgeT0iMTAwIiBzdHlsZT0iZm9udDogMTAuNXB4IEludGVyLCBzYW5zLXNlcmlmOyBmaWxsOiAjNmVlN2I3Ij5jcHUgwrcgbWVtb3J5IOKGkiBQb2QgcmVxdWVzdHMgYW5kIGxpbWl0czwvdGV4dD4KPHRleHQgeD0iMzk0IiB5PSIxMjIiIHN0eWxlPSJmb250OiAxMC41cHggSW50ZXIsIHNhbnMtc2VyaWY7IGZpbGw6ICM2ZWU3YjciPmRlc2lyZWRDb3VudCDihpIgcmVwbGljYXM6IDMgwrcgYXV0b3NjYWxpbmcg4oaSIEhQQTwvdGV4dD4KPHJlY3QgeD0iMjQiIHk9IjE2NiIgd2lkdGg9IjM4NiIgaGVpZ2h0PSI0NiIgcng9IjEwIiBzdHJva2Utd2lkdGg9IjEuMyIgc3R5bGU9ImZpbGw6IzBmMTcyYTtzdHJva2U6IzQ3NTU2OSIvPgo8dGV4dCB4PSIyMTciIHk9IjE4NSIgdGV4dC1hbmNob3I9Im1pZGRsZSIgc3R5bGU9ImZvbnQ6IDY1MCAxMy41cHggSW50ZXIsIHNhbnMtc2VyaWY7IGZpbGw6ICNmMWY1Zjk7IGZvbnQtc2l6ZToxMXB4Ij5EQUVNT04gc3RyYXRlZ3kg4oaSIERhZW1vblNldDwvdGV4dD4KPHRleHQgeD0iMjE3IiB5PSIyMDIiIHRleHQtYW5jaG9yPSJtaWRkbGUiIHN0eWxlPSJmb250OiAxMXB4IEludGVyLCBzYW5zLXNlcmlmOyBmaWxsOiAjOTRhM2I4Ij5vbmUgUG9kIHBlciBub2RlPC90ZXh0Pgo8cmVjdCB4PSI0MjYiIHk9IjE2NiIgd2lkdGg9IjM4NiIgaGVpZ2h0PSI0NiIgcng9IjEwIiBzdHJva2Utd2lkdGg9IjEuMyIgc3R5bGU9ImZpbGw6IzBmMTcyYTtzdHJva2U6IzQ3NTU2OSIvPgo8dGV4dCB4PSI2MTkiIHk9IjE4NSIgdGV4dC1hbmNob3I9Im1pZGRsZSIgc3R5bGU9ImZvbnQ6IDY1MCAxMy41cHggSW50ZXIsIHNhbnMtc2VyaWY7IGZpbGw6ICNmMWY1Zjk7IGZvbnQtc2l6ZToxMXB4Ij5FQ1MgRXhlYyDihpIga3ViZWN0bCBleGVjPC90ZXh0Pgo8dGV4dCB4PSI2MTkiIHk9IjIwMiIgdGV4dC1hbmNob3I9Im1pZGRsZSIgc3R5bGU9ImZvbnQ6IDExcHggSW50ZXIsIHNhbnMtc2VyaWY7IGZpbGw6ICM5NGEzYjgiPmEgc2hlbGwgaW4gdGhlIHJ1bm5pbmcgUG9kPC90ZXh0Pgo8L3N2Zz4=)

The task definition becomes a Pod spec and the service becomes a Deployment with the same desired count.

#### Networking, discovery, and load balancing

In ECS `awsvpc` mode, each task has its own IP address and security group. On the target cluster, your CNI gives each Pod its own IP address, so Pods are individually addressable in the same way. A task's security group becomes a **NetworkPolicy** that keeps the same isolation between workloads. Service discovery by name, through Cloud Map or DNS, becomes a Kubernetes **Service** with cluster DNS, the same name-based model.

The service's `loadBalancer` block (the ALB or NLB target group its tasks register with) becomes a Kubernetes **Service** of type LoadBalancer or ClusterIP, plus an **Ingress** for host and path routing. The target group's health check becomes the Pod's readiness probe. For supported routing rules, weights and certificates, see the [Application Load Balancer](https://docs.tensor9.com/cloud-adapter-early-access/service-catalog/aws/networking-traffic/lb.md) and [Network Load Balancer](https://docs.tensor9.com/cloud-adapter-early-access/service-catalog/aws/networking-traffic/nlb.md) articles.

#### The cluster you operate

The Deployment and Service run on a cluster **you already operate**: kubeadm, k3s or kops, or a managed cluster you bring. This works on any target the Cloud Adapter deployment supports, including fully disconnected environments. For a self-operated cluster, you maintain the **control plane and nodes**, including the API server, etcd, upgrades and availability. For a managed cluster you bring, its provider keeps those responsibilities. An ECS capacity provider maps to your own node pools and cluster autoscaler, and a `FARGATE_SPOT` preference maps to your Spot node pools.

The service needs an ingress controller for the Service and Ingress, a cluster autoscaler, a metrics or Prometheus stack, and the service mesh that replaces Service Connect's proxy. On a self-operated cluster you install and run these; on a managed cluster, use the provider's supported services. Confirm which components you operate and which your provider supplies.

![The service runs on an existing cluster, self-operated or managed. Confirm who operates its control plane and nodes, and its ingress controller, cluster autoscaler, metrics stack and Gateway API or service mesh. In a disconnected environment, these must be available locally.](data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSI4MzYiIGhlaWdodD0iMjQ0IiB2aWV3Qm94PSIwIDAgODM2IDI0NCIgcm9sZT0iaW1nIiBhcmlhLWxhYmVsPSJUaGUgc2VydmljZSBydW5zIG9uIGFuIGV4aXN0aW5nIGNsdXN0ZXIsIHNlbGYtb3BlcmF0ZWQgb3IgbWFuYWdlZC4gQ29uZmlybSB3aG8gb3BlcmF0ZXMgaXRzIGNvbnRyb2wgcGxhbmUgYW5kIG5vZGVzLCBhbmQgaXRzIGluZ3Jlc3MgY29udHJvbGxlciwgY2x1c3RlciBhdXRvc2NhbGVyLCBtZXRyaWNzIHN0YWNrIGFuZCBHYXRld2F5IEFQSSBvciBzZXJ2aWNlIG1lc2guIEluIGEgZGlzY29ubmVjdGVkIGVudmlyb25tZW50LCB0aGVzZSBtdXN0IGJlIGF2YWlsYWJsZSBsb2NhbGx5LiI+PHN0eWxlPnRleHR7Zm9udC1mYW1pbHk6SW50ZXIsLWFwcGxlLXN5c3RlbSxCbGlua01hY1N5c3RlbUZvbnQsJ1NlZ29lIFVJJyxSb2JvdG8sJ0hlbHZldGljYSBOZXVlJyxBcmlhbCxzYW5zLXNlcmlmO2ZpbGw6IzMzNDE1NX08L3N0eWxlPgo8cmVjdCB4PSIxNiIgeT0iMjgiIHdpZHRoPSI4MDQiIGhlaWdodD0iNzIiIHJ4PSIxMyIgc3Ryb2tlLXdpZHRoPSIxLjUiIHN0eWxlPSJmaWxsOiNlY2ZkZjU7c3Ryb2tlOiMwNDc4NTciLz4KPHRleHQgeD0iMzAiIHk9IjQ4IiBzdHlsZT0iZm9udDogNzAwIDEwcHggSW50ZXIsIHNhbnMtc2VyaWY7IGxldHRlci1zcGFjaW5nOiAxLjNweDsgZmlsbDogIzk0YTNiODsgZmlsbDojMDQ3ODU3Ij5BTiBFWElTVElORyBDTFVTVEVSIMK3IFNFTEYtT1BFUkFURUQgT1IgTUFOQUdFRDwvdGV4dD4KPHJlY3QgeD0iMzAiIHk9IjU4IiB3aWR0aD0iMzY2IiBoZWlnaHQ9IjMyIiByeD0iOCIgc3Ryb2tlLXdpZHRoPSIxLjMiIHN0eWxlPSJmaWxsOiNmZmZmZmY7c3Ryb2tlOiNhN2YzZDAiLz4KPHRleHQgeD0iMjEzIiB5PSI3OCIgdGV4dC1hbmNob3I9Im1pZGRsZSIgc3R5bGU9ImZvbnQ6IDEwLjVweCBJbnRlciwgc2Fucy1zZXJpZjsgZmlsbDogIzA0Nzg1NzsgZm9udC1zaXplOjExcHgiPmNvbnRyb2wgcGxhbmUgwrcgeW91IG9yIHlvdXIgcHJvdmlkZXI8L3RleHQ+CjxyZWN0IHg9IjQwOCIgeT0iNTgiIHdpZHRoPSIzOTgiIGhlaWdodD0iMzIiIHJ4PSI4IiBzdHJva2Utd2lkdGg9IjEuMyIgc3R5bGU9ImZpbGw6I2ZmZmZmZjtzdHJva2U6I2E3ZjNkMCIvPgo8dGV4dCB4PSI2MDciIHk9Ijc4IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBzdHlsZT0iZm9udDogMTAuNXB4IEludGVyLCBzYW5zLXNlcmlmOyBmaWxsOiAjMDQ3ODU3OyBmb250LXNpemU6MTFweCI+Y29uZmlybSB3aG8gcnVucyBub2RlcyBhbmQgdXBncmFkZXM8L3RleHQ+Cjx0ZXh0IHg9IjI4IiB5PSIxMjQiIHN0eWxlPSJmb250OiA3MDAgMTBweCBJbnRlciwgc2Fucy1zZXJpZjsgbGV0dGVyLXNwYWNpbmc6IDEuM3B4OyBmaWxsOiAjOTRhM2I4OyBmaWxsOiM2NDc0OGIiPlJFUVVJUkVEIEFERC1PTlMgwrcgWU9VUlMgT1IgWU9VUiBQUk9WSURFUidTPC90ZXh0Pgo8cmVjdCB4PSIyMCIgeT0iMTM0IiB3aWR0aD0iMTkyIiBoZWlnaHQ9IjM4IiByeD0iOSIgc3Ryb2tlLXdpZHRoPSIxLjIiIHN0eWxlPSJmaWxsOiNmOGZhZmM7c3Ryb2tlOiNjYmQ1ZTEiLz4KPHRleHQgeD0iMTE2IiB5PSIxNTciIHRleHQtYW5jaG9yPSJtaWRkbGUiIHN0eWxlPSJmb250OiA2NTAgMTMuNXB4IEludGVyLCBzYW5zLXNlcmlmOyBmaWxsOiAjMGYxNzJhOyBmb250LXNpemU6MTAuNXB4Ij5pbmdyZXNzIGNvbnRyb2xsZXI8L3RleHQ+CjxyZWN0IHg9IjIyNCIgeT0iMTM0IiB3aWR0aD0iMTkyIiBoZWlnaHQ9IjM4IiByeD0iOSIgc3Ryb2tlLXdpZHRoPSIxLjIiIHN0eWxlPSJmaWxsOiNmOGZhZmM7c3Ryb2tlOiNjYmQ1ZTEiLz4KPHRleHQgeD0iMzIwIiB5PSIxNTciIHRleHQtYW5jaG9yPSJtaWRkbGUiIHN0eWxlPSJmb250OiA2NTAgMTMuNXB4IEludGVyLCBzYW5zLXNlcmlmOyBmaWxsOiAjMGYxNzJhOyBmb250LXNpemU6MTAuNXB4Ij5jbHVzdGVyIGF1dG9zY2FsZXI8L3RleHQ+CjxyZWN0IHg9IjQyOCIgeT0iMTM0IiB3aWR0aD0iMTkyIiBoZWlnaHQ9IjM4IiByeD0iOSIgc3Ryb2tlLXdpZHRoPSIxLjIiIHN0eWxlPSJmaWxsOiNmOGZhZmM7c3Ryb2tlOiNjYmQ1ZTEiLz4KPHRleHQgeD0iNTI0IiB5PSIxNTciIHRleHQtYW5jaG9yPSJtaWRkbGUiIHN0eWxlPSJmb250OiA2NTAgMTMuNXB4IEludGVyLCBzYW5zLXNlcmlmOyBmaWxsOiAjMGYxNzJhOyBmb250LXNpemU6MTAuNXB4Ij5tZXRyaWNzIC8gUHJvbWV0aGV1czwvdGV4dD4KPHJlY3QgeD0iNjMyIiB5PSIxMzQiIHdpZHRoPSIxODAiIGhlaWdodD0iMzgiIHJ4PSI5IiBzdHJva2Utd2lkdGg9IjEuMiIgc3R5bGU9ImZpbGw6I2Y4ZmFmYztzdHJva2U6I2NiZDVlMSIvPgo8dGV4dCB4PSI3MjIiIHk9IjE1NyIgdGV4dC1hbmNob3I9Im1pZGRsZSIgc3R5bGU9ImZvbnQ6IDY1MCAxMy41cHggSW50ZXIsIHNhbnMtc2VyaWY7IGZpbGw6ICMwZjE3MmE7IGZvbnQtc2l6ZToxMC41cHgiPkdhdGV3YXkgLyBtZXNoPC90ZXh0Pgo8cmVjdCB4PSIyMCIgeT0iMTgyIiB3aWR0aD0iNzkyIiBoZWlnaHQ9IjM2IiByeD0iOSIgc3Ryb2tlLXdpZHRoPSIxLjIiIHN0eWxlPSJmaWxsOiNmZmZmZmY7c3Ryb2tlOiNjYmQ1ZTEiLz4KPHRleHQgeD0iNDE2IiB5PSIyMDQiIHRleHQtYW5jaG9yPSJtaWRkbGUiIHN0eWxlPSJmb250OiAxMXB4IEludGVyLCBzYW5zLXNlcmlmOyBmaWxsOiAjNjQ3NDhiIj5SdW4gdGhlc2UgY29tcG9uZW50cyB5b3Vyc2VsZiBvciB1c2UgdGhlIG9uZXMgeW91ciBjbHVzdGVyIHByb3ZpZGVyIHN1cHBsaWVzLjwvdGV4dD4KPHRleHQgeD0iMjgiIHk9IjIzOCIgc3R5bGU9ImZvbnQ6IDExcHggSW50ZXIsIHNhbnMtc2VyaWY7IGZpbGw6ICM2NDc0OGI7IGZpbGw6IzY0NzQ4YiI+Q2FwYWNpdHkgcHJvdmlkZXJzIOKGkiB5b3VyIG5vZGUgcG9vbHMgYW5kIGNsdXN0ZXIgYXV0b3NjYWxlciDCtyBGQVJHQVRFX1NQT1Qg4oaSIHlvdXIgU3BvdCBub2RlIHBvb2xzPC90ZXh0Pgo8L3N2Zz4=)

![The service runs on an existing cluster, self-operated or managed. Confirm who operates its control plane and nodes, and its ingress controller, cluster autoscaler, metrics stack and Gateway API or service mesh. In a disconnected environment, these must be available locally.](data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSI4MzYiIGhlaWdodD0iMjQ0IiB2aWV3Qm94PSIwIDAgODM2IDI0NCIgcm9sZT0iaW1nIiBhcmlhLWxhYmVsPSJUaGUgc2VydmljZSBydW5zIG9uIGFuIGV4aXN0aW5nIGNsdXN0ZXIsIHNlbGYtb3BlcmF0ZWQgb3IgbWFuYWdlZC4gQ29uZmlybSB3aG8gb3BlcmF0ZXMgaXRzIGNvbnRyb2wgcGxhbmUgYW5kIG5vZGVzLCBhbmQgaXRzIGluZ3Jlc3MgY29udHJvbGxlciwgY2x1c3RlciBhdXRvc2NhbGVyLCBtZXRyaWNzIHN0YWNrIGFuZCBHYXRld2F5IEFQSSBvciBzZXJ2aWNlIG1lc2guIEluIGEgZGlzY29ubmVjdGVkIGVudmlyb25tZW50LCB0aGVzZSBtdXN0IGJlIGF2YWlsYWJsZSBsb2NhbGx5LiI+PHN0eWxlPnRleHR7Zm9udC1mYW1pbHk6SW50ZXIsLWFwcGxlLXN5c3RlbSxCbGlua01hY1N5c3RlbUZvbnQsJ1NlZ29lIFVJJyxSb2JvdG8sJ0hlbHZldGljYSBOZXVlJyxBcmlhbCxzYW5zLXNlcmlmO2ZpbGw6I2NiZDVlMX08L3N0eWxlPgo8cmVjdCB4PSIxNiIgeT0iMjgiIHdpZHRoPSI4MDQiIGhlaWdodD0iNzIiIHJ4PSIxMyIgc3Ryb2tlLXdpZHRoPSIxLjUiIHN0eWxlPSJmaWxsOiMwNjRlM2I7c3Ryb2tlOiM2ZWU3YjciLz4KPHRleHQgeD0iMzAiIHk9IjQ4IiBzdHlsZT0iZm9udDogNzAwIDEwcHggSW50ZXIsIHNhbnMtc2VyaWY7IGxldHRlci1zcGFjaW5nOiAxLjNweDsgZmlsbDogIzY0NzQ4YjsgZmlsbDojNmVlN2I3Ij5BTiBFWElTVElORyBDTFVTVEVSIMK3IFNFTEYtT1BFUkFURUQgT1IgTUFOQUdFRDwvdGV4dD4KPHJlY3QgeD0iMzAiIHk9IjU4IiB3aWR0aD0iMzY2IiBoZWlnaHQ9IjMyIiByeD0iOCIgc3Ryb2tlLXdpZHRoPSIxLjMiIHN0eWxlPSJmaWxsOiMxZTI5M2I7c3Ryb2tlOiMwNDc4NTciLz4KPHRleHQgeD0iMjEzIiB5PSI3OCIgdGV4dC1hbmNob3I9Im1pZGRsZSIgc3R5bGU9ImZvbnQ6IDEwLjVweCBJbnRlciwgc2Fucy1zZXJpZjsgZmlsbDogIzZlZTdiNzsgZm9udC1zaXplOjExcHgiPmNvbnRyb2wgcGxhbmUgwrcgeW91IG9yIHlvdXIgcHJvdmlkZXI8L3RleHQ+CjxyZWN0IHg9IjQwOCIgeT0iNTgiIHdpZHRoPSIzOTgiIGhlaWdodD0iMzIiIHJ4PSI4IiBzdHJva2Utd2lkdGg9IjEuMyIgc3R5bGU9ImZpbGw6IzFlMjkzYjtzdHJva2U6IzA0Nzg1NyIvPgo8dGV4dCB4PSI2MDciIHk9Ijc4IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBzdHlsZT0iZm9udDogMTAuNXB4IEludGVyLCBzYW5zLXNlcmlmOyBmaWxsOiAjNmVlN2I3OyBmb250LXNpemU6MTFweCI+Y29uZmlybSB3aG8gcnVucyBub2RlcyBhbmQgdXBncmFkZXM8L3RleHQ+Cjx0ZXh0IHg9IjI4IiB5PSIxMjQiIHN0eWxlPSJmb250OiA3MDAgMTBweCBJbnRlciwgc2Fucy1zZXJpZjsgbGV0dGVyLXNwYWNpbmc6IDEuM3B4OyBmaWxsOiAjNjQ3NDhiOyBmaWxsOiM5NGEzYjgiPlJFUVVJUkVEIEFERC1PTlMgwrcgWU9VUlMgT1IgWU9VUiBQUk9WSURFUidTPC90ZXh0Pgo8cmVjdCB4PSIyMCIgeT0iMTM0IiB3aWR0aD0iMTkyIiBoZWlnaHQ9IjM4IiByeD0iOSIgc3Ryb2tlLXdpZHRoPSIxLjIiIHN0eWxlPSJmaWxsOiMwZjE3MmE7c3Ryb2tlOiM0NzU1NjkiLz4KPHRleHQgeD0iMTE2IiB5PSIxNTciIHRleHQtYW5jaG9yPSJtaWRkbGUiIHN0eWxlPSJmb250OiA2NTAgMTMuNXB4IEludGVyLCBzYW5zLXNlcmlmOyBmaWxsOiAjZjFmNWY5OyBmb250LXNpemU6MTAuNXB4Ij5pbmdyZXNzIGNvbnRyb2xsZXI8L3RleHQ+CjxyZWN0IHg9IjIyNCIgeT0iMTM0IiB3aWR0aD0iMTkyIiBoZWlnaHQ9IjM4IiByeD0iOSIgc3Ryb2tlLXdpZHRoPSIxLjIiIHN0eWxlPSJmaWxsOiMwZjE3MmE7c3Ryb2tlOiM0NzU1NjkiLz4KPHRleHQgeD0iMzIwIiB5PSIxNTciIHRleHQtYW5jaG9yPSJtaWRkbGUiIHN0eWxlPSJmb250OiA2NTAgMTMuNXB4IEludGVyLCBzYW5zLXNlcmlmOyBmaWxsOiAjZjFmNWY5OyBmb250LXNpemU6MTAuNXB4Ij5jbHVzdGVyIGF1dG9zY2FsZXI8L3RleHQ+CjxyZWN0IHg9IjQyOCIgeT0iMTM0IiB3aWR0aD0iMTkyIiBoZWlnaHQ9IjM4IiByeD0iOSIgc3Ryb2tlLXdpZHRoPSIxLjIiIHN0eWxlPSJmaWxsOiMwZjE3MmE7c3Ryb2tlOiM0NzU1NjkiLz4KPHRleHQgeD0iNTI0IiB5PSIxNTciIHRleHQtYW5jaG9yPSJtaWRkbGUiIHN0eWxlPSJmb250OiA2NTAgMTMuNXB4IEludGVyLCBzYW5zLXNlcmlmOyBmaWxsOiAjZjFmNWY5OyBmb250LXNpemU6MTAuNXB4Ij5tZXRyaWNzIC8gUHJvbWV0aGV1czwvdGV4dD4KPHJlY3QgeD0iNjMyIiB5PSIxMzQiIHdpZHRoPSIxODAiIGhlaWdodD0iMzgiIHJ4PSI5IiBzdHJva2Utd2lkdGg9IjEuMiIgc3R5bGU9ImZpbGw6IzBmMTcyYTtzdHJva2U6IzQ3NTU2OSIvPgo8dGV4dCB4PSI3MjIiIHk9IjE1NyIgdGV4dC1hbmNob3I9Im1pZGRsZSIgc3R5bGU9ImZvbnQ6IDY1MCAxMy41cHggSW50ZXIsIHNhbnMtc2VyaWY7IGZpbGw6ICNmMWY1Zjk7IGZvbnQtc2l6ZToxMC41cHgiPkdhdGV3YXkgLyBtZXNoPC90ZXh0Pgo8cmVjdCB4PSIyMCIgeT0iMTgyIiB3aWR0aD0iNzkyIiBoZWlnaHQ9IjM2IiByeD0iOSIgc3Ryb2tlLXdpZHRoPSIxLjIiIHN0eWxlPSJmaWxsOiMxZTI5M2I7c3Ryb2tlOiM0NzU1NjkiLz4KPHRleHQgeD0iNDE2IiB5PSIyMDQiIHRleHQtYW5jaG9yPSJtaWRkbGUiIHN0eWxlPSJmb250OiAxMXB4IEludGVyLCBzYW5zLXNlcmlmOyBmaWxsOiAjOTRhM2I4Ij5SdW4gdGhlc2UgY29tcG9uZW50cyB5b3Vyc2VsZiBvciB1c2UgdGhlIG9uZXMgeW91ciBjbHVzdGVyIHByb3ZpZGVyIHN1cHBsaWVzLjwvdGV4dD4KPHRleHQgeD0iMjgiIHk9IjIzOCIgc3R5bGU9ImZvbnQ6IDExcHggSW50ZXIsIHNhbnMtc2VyaWY7IGZpbGw6ICM5NGEzYjg7IGZpbGw6Izk0YTNiOCI+Q2FwYWNpdHkgcHJvdmlkZXJzIOKGkiB5b3VyIG5vZGUgcG9vbHMgYW5kIGNsdXN0ZXIgYXV0b3NjYWxlciDCtyBGQVJHQVRFX1NQT1Qg4oaSIHlvdXIgU3BvdCBub2RlIHBvb2xzPC90ZXh0Pgo8L3N2Zz4=)

The service runs on your existing cluster; confirm who operates its control plane, nodes and add-ons.

#### Pod identity: the task role

An ECS task role is the identity your application code uses; EKS does the same with IRSA. On managed Kubernetes services it maps to the cloud's workload identity; an existing cluster uses whatever identity integrations it already has. Inside the cluster, identity is a native **Kubernetes ServiceAccount** with **RBAC**, which you own: the ServiceAccount identifies the workload, and RBAC decides what it may do through the Kubernetes API.

AWS calls handled by Tensor9 use the configured credential adapter and the task-role policy. The Cloud Adapter deployment answers as the task role, taken from the Pod's identity, so `aws sts get-caller-identity` and `iam:GetRole` return the task's own role. Calls to real external cloud services need credentials that cloud authorizes, through the cluster's federation or secret configuration. The **execution role**, which ECS used to pull the image, fetch secrets and write logs, is not needed, because the cluster pulls images and delivers logs.

![The ECS task role maps to a native Kubernetes ServiceAccount, with RBAC governing access to the cluster. AWS calls use the task role. Access to an external cloud uses credentials or federation you configure separately.](data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSI4MzYiIGhlaWdodD0iMTk2IiB2aWV3Qm94PSIwIDAgODM2IDE5NiIgcm9sZT0iaW1nIiBhcmlhLWxhYmVsPSJUaGUgRUNTIHRhc2sgcm9sZSBtYXBzIHRvIGEgbmF0aXZlIEt1YmVybmV0ZXMgU2VydmljZUFjY291bnQsIHdpdGggUkJBQyBnb3Zlcm5pbmcgYWNjZXNzIHRvIHRoZSBjbHVzdGVyLiBBV1MgY2FsbHMgdXNlIHRoZSB0YXNrIHJvbGUuIEFjY2VzcyB0byBhbiBleHRlcm5hbCBjbG91ZCB1c2VzIGNyZWRlbnRpYWxzIG9yIGZlZGVyYXRpb24geW91IGNvbmZpZ3VyZSBzZXBhcmF0ZWx5LiI+PHN0eWxlPnRleHR7Zm9udC1mYW1pbHk6SW50ZXIsLWFwcGxlLXN5c3RlbSxCbGlua01hY1N5c3RlbUZvbnQsJ1NlZ29lIFVJJyxSb2JvdG8sJ0hlbHZldGljYSBOZXVlJyxBcmlhbCxzYW5zLXNlcmlmO2ZpbGw6IzMzNDE1NX08L3N0eWxlPgo8ZGVmcz48bWFya2VyIGlkPSJlazhzLWlkIiB2aWV3Qm94PSIwIDAgMTAgMTAiIHJlZlg9IjgiIHJlZlk9IjUiIG1hcmtlcldpZHRoPSI3IiBtYXJrZXJIZWlnaHQ9IjciIG9yaWVudD0iYXV0by1zdGFydC1yZXZlcnNlIj48cGF0aCBkPSJNMCwwIEwxMCw1IEwwLDEwIHoiIHN0eWxlPSJmaWxsOiMwNDc4NTciLz48L21hcmtlcj48L2RlZnM+CjxyZWN0IHg9IjIwIiB5PSI0NCIgd2lkdGg9IjE4OCIgaGVpZ2h0PSI2NiIgcng9IjEyIiBzdHJva2Utd2lkdGg9IjEuNSIgc3R5bGU9ImZpbGw6I2ZmZmZmZjtzdHJva2U6I2NiZDVlMSIvPgo8dGV4dCB4PSIxMTQiIHk9IjcwIiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBzdHlsZT0iZm9udDogNjUwIDEzLjVweCBJbnRlciwgc2Fucy1zZXJpZjsgZmlsbDogIzBmMTcyYTsgZm9udC1zaXplOjExcHgiPkVDUyB0YXNrIHJvbGU8L3RleHQ+Cjx0ZXh0IHg9IjExNCIgeT0iOTAiIHRleHQtYW5jaG9yPSJtaWRkbGUiIHN0eWxlPSJmb250OiAxMXB4ICdTRiBNb25vJywgdWktbW9ub3NwYWNlLCAnSmV0QnJhaW5zIE1vbm8nLCBNZW5sbywgbW9ub3NwYWNlOyBmaWxsOiAjMzM0MTU1OyBmb250LXNpemU6MTBweDtmaWxsOiMzMzQxNTUiPnRhc2tSb2xlQXJuPC90ZXh0Pgo8dGV4dCB4PSIxMTQiIHk9IjEyMyIgdGV4dC1hbmNob3I9Im1pZGRsZSIgc3R5bGU9ImZvbnQ6IDExcHggSW50ZXIsIHNhbnMtc2VyaWY7IGZpbGw6ICM2NDc0OGIiPnRoZSBhcHAncyBvd24gaWRlbnRpdHk8L3RleHQ+CjxsaW5lIHgxPSIyMDgiIHkxPSI3NyIgeDI9IjI1MCIgeTI9Ijc3IiBzdHJva2Utd2lkdGg9IjIiIG1hcmtlci1lbmQ9InVybCgjZWs4cy1pZCkiIHN0eWxlPSJzdHJva2U6IzA0Nzg1NyIvPgo8cmVjdCB4PSIyNTQiIHk9IjQwIiB3aWR0aD0iMzAyIiBoZWlnaHQ9Ijc0IiByeD0iMTIiIHN0cm9rZS13aWR0aD0iMS43IiBzdHlsZT0iZmlsbDojZWNmZGY1O3N0cm9rZTojMDQ3ODU3Ii8+Cjx0ZXh0IHg9IjQwNSIgeT0iNjYiIHRleHQtYW5jaG9yPSJtaWRkbGUiIHN0eWxlPSJmb250OiA3MDAgMTMuNXB4IEludGVyLCBzYW5zLXNlcmlmOyBmaWxsOiAjMDQ3ODU3OyBmb250LXNpemU6MTEuNXB4Ij5TZXJ2aWNlQWNjb3VudCArIFJCQUM8L3RleHQ+Cjx0ZXh0IHg9IjQwNSIgeT0iODYiIHRleHQtYW5jaG9yPSJtaWRkbGUiIHN0eWxlPSJmb250OiAxMC41cHggSW50ZXIsIHNhbnMtc2VyaWY7IGZpbGw6ICMwNDc4NTciPmNsdXN0ZXIgYWNjZXNzPC90ZXh0Pgo8dGV4dCB4PSI0MDUiIHk9IjEwMyIgdGV4dC1hbmNob3I9Im1pZGRsZSIgc3R5bGU9ImZvbnQ6IDEwLjVweCBJbnRlciwgc2Fucy1zZXJpZjsgZmlsbDogIzA0Nzg1NyI+QVdTIGNhbGxzIHVzZSB0aGUgdGFzayByb2xlPC90ZXh0Pgo8bGluZSB4MT0iNTU2IiB5MT0iNzciIHgyPSI1OTgiIHkyPSI3NyIgc3Ryb2tlLXdpZHRoPSIyIiBtYXJrZXItZW5kPSJ1cmwoI2VrOHMtaWQpIiBzdHlsZT0ic3Ryb2tlOiM5NGEzYjgiLz4KPHJlY3QgeD0iNjAyIiB5PSI0NCIgd2lkdGg9IjIxNCIgaGVpZ2h0PSI2NiIgcng9IjEyIiBzdHJva2Utd2lkdGg9IjEuNCIgc3Ryb2tlLWRhc2hhcnJheT0iNSA1IiBzdHlsZT0iZmlsbDojZjhmYWZjO3N0cm9rZTojY2JkNWUxIi8+Cjx0ZXh0IHg9IjcwOSIgeT0iNzAiIHRleHQtYW5jaG9yPSJtaWRkbGUiIHN0eWxlPSJmb250OiA2NTAgMTMuNXB4IEludGVyLCBzYW5zLXNlcmlmOyBmaWxsOiAjMGYxNzJhOyBmb250LXNpemU6MTAuNXB4O2ZpbGw6IzY0NzQ4YiI+RXh0ZXJuYWwgY2xvdWQgYWNjZXNzPC90ZXh0Pgo8dGV4dCB4PSI3MDkiIHk9IjkwIiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBzdHlsZT0iZm9udDogMTFweCBJbnRlciwgc2Fucy1zZXJpZjsgZmlsbDogIzY0NzQ4YiI+Y3JlZGVudGlhbHMgb3IgZmVkZXJhdGlvbjwvdGV4dD4KPHRleHQgeD0iNzA5IiB5PSIxMDYiIHRleHQtYW5jaG9yPSJtaWRkbGUiIHN0eWxlPSJmb250OiAxMXB4IEludGVyLCBzYW5zLXNlcmlmOyBmaWxsOiAjNjQ3NDhiIj55b3UgY29uZmlndXJlPC90ZXh0Pgo8dGV4dCB4PSI0MTgiIHk9IjE1MCIgdGV4dC1hbmNob3I9Im1pZGRsZSIgc3R5bGU9ImZvbnQ6IDExcHggSW50ZXIsIHNhbnMtc2VyaWY7IGZpbGw6ICM2NDc0OGIiPkFXUyBjYWxscyBhcmUgYXV0aG9yaXplZCB3aXRoIHRoZSB0YXNrIHJvbGU7IGV4dGVybmFsIGNsb3VkIGFjY2VzcyBpcyBjb25maWd1cmVkIHNlcGFyYXRlbHkuPC90ZXh0Pgo8dGV4dCB4PSI0MTgiIHk9IjE3MCIgdGV4dC1hbmNob3I9Im1pZGRsZSIgc3R5bGU9ImZvbnQ6IDExcHggSW50ZXIsIHNhbnMtc2VyaWY7IGZpbGw6ICM2NDc0OGIiPkNsdXN0ZXIgaWRlbnRpdHkgaXMgYSBuYXRpdmUgU2VydmljZUFjY291bnQgd2l0aCBSQkFDLCB3aGljaCB5b3Ugb3duLjwvdGV4dD4KPC9zdmc+)

![The ECS task role maps to a native Kubernetes ServiceAccount, with RBAC governing access to the cluster. AWS calls use the task role. Access to an external cloud uses credentials or federation you configure separately.](data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSI4MzYiIGhlaWdodD0iMTk2IiB2aWV3Qm94PSIwIDAgODM2IDE5NiIgcm9sZT0iaW1nIiBhcmlhLWxhYmVsPSJUaGUgRUNTIHRhc2sgcm9sZSBtYXBzIHRvIGEgbmF0aXZlIEt1YmVybmV0ZXMgU2VydmljZUFjY291bnQsIHdpdGggUkJBQyBnb3Zlcm5pbmcgYWNjZXNzIHRvIHRoZSBjbHVzdGVyLiBBV1MgY2FsbHMgdXNlIHRoZSB0YXNrIHJvbGUuIEFjY2VzcyB0byBhbiBleHRlcm5hbCBjbG91ZCB1c2VzIGNyZWRlbnRpYWxzIG9yIGZlZGVyYXRpb24geW91IGNvbmZpZ3VyZSBzZXBhcmF0ZWx5LiI+PHN0eWxlPnRleHR7Zm9udC1mYW1pbHk6SW50ZXIsLWFwcGxlLXN5c3RlbSxCbGlua01hY1N5c3RlbUZvbnQsJ1NlZ29lIFVJJyxSb2JvdG8sJ0hlbHZldGljYSBOZXVlJyxBcmlhbCxzYW5zLXNlcmlmO2ZpbGw6I2NiZDVlMX08L3N0eWxlPgo8ZGVmcz48bWFya2VyIGlkPSJlazhzLWlkIiB2aWV3Qm94PSIwIDAgMTAgMTAiIHJlZlg9IjgiIHJlZlk9IjUiIG1hcmtlcldpZHRoPSI3IiBtYXJrZXJIZWlnaHQ9IjciIG9yaWVudD0iYXV0by1zdGFydC1yZXZlcnNlIj48cGF0aCBkPSJNMCwwIEwxMCw1IEwwLDEwIHoiIHN0eWxlPSJmaWxsOiM2ZWU3YjciLz48L21hcmtlcj48L2RlZnM+CjxyZWN0IHg9IjIwIiB5PSI0NCIgd2lkdGg9IjE4OCIgaGVpZ2h0PSI2NiIgcng9IjEyIiBzdHJva2Utd2lkdGg9IjEuNSIgc3R5bGU9ImZpbGw6IzFlMjkzYjtzdHJva2U6IzQ3NTU2OSIvPgo8dGV4dCB4PSIxMTQiIHk9IjcwIiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBzdHlsZT0iZm9udDogNjUwIDEzLjVweCBJbnRlciwgc2Fucy1zZXJpZjsgZmlsbDogI2YxZjVmOTsgZm9udC1zaXplOjExcHgiPkVDUyB0YXNrIHJvbGU8L3RleHQ+Cjx0ZXh0IHg9IjExNCIgeT0iOTAiIHRleHQtYW5jaG9yPSJtaWRkbGUiIHN0eWxlPSJmb250OiAxMXB4ICdTRiBNb25vJywgdWktbW9ub3NwYWNlLCAnSmV0QnJhaW5zIE1vbm8nLCBNZW5sbywgbW9ub3NwYWNlOyBmaWxsOiAjY2JkNWUxOyBmb250LXNpemU6MTBweDtmaWxsOiNjYmQ1ZTEiPnRhc2tSb2xlQXJuPC90ZXh0Pgo8dGV4dCB4PSIxMTQiIHk9IjEyMyIgdGV4dC1hbmNob3I9Im1pZGRsZSIgc3R5bGU9ImZvbnQ6IDExcHggSW50ZXIsIHNhbnMtc2VyaWY7IGZpbGw6ICM5NGEzYjgiPnRoZSBhcHAncyBvd24gaWRlbnRpdHk8L3RleHQ+CjxsaW5lIHgxPSIyMDgiIHkxPSI3NyIgeDI9IjI1MCIgeTI9Ijc3IiBzdHJva2Utd2lkdGg9IjIiIG1hcmtlci1lbmQ9InVybCgjZWs4cy1pZCkiIHN0eWxlPSJzdHJva2U6IzZlZTdiNyIvPgo8cmVjdCB4PSIyNTQiIHk9IjQwIiB3aWR0aD0iMzAyIiBoZWlnaHQ9Ijc0IiByeD0iMTIiIHN0cm9rZS13aWR0aD0iMS43IiBzdHlsZT0iZmlsbDojMDY0ZTNiO3N0cm9rZTojNmVlN2I3Ii8+Cjx0ZXh0IHg9IjQwNSIgeT0iNjYiIHRleHQtYW5jaG9yPSJtaWRkbGUiIHN0eWxlPSJmb250OiA3MDAgMTMuNXB4IEludGVyLCBzYW5zLXNlcmlmOyBmaWxsOiAjNmVlN2I3OyBmb250LXNpemU6MTEuNXB4Ij5TZXJ2aWNlQWNjb3VudCArIFJCQUM8L3RleHQ+Cjx0ZXh0IHg9IjQwNSIgeT0iODYiIHRleHQtYW5jaG9yPSJtaWRkbGUiIHN0eWxlPSJmb250OiAxMC41cHggSW50ZXIsIHNhbnMtc2VyaWY7IGZpbGw6ICM2ZWU3YjciPmNsdXN0ZXIgYWNjZXNzPC90ZXh0Pgo8dGV4dCB4PSI0MDUiIHk9IjEwMyIgdGV4dC1hbmNob3I9Im1pZGRsZSIgc3R5bGU9ImZvbnQ6IDEwLjVweCBJbnRlciwgc2Fucy1zZXJpZjsgZmlsbDogIzZlZTdiNyI+QVdTIGNhbGxzIHVzZSB0aGUgdGFzayByb2xlPC90ZXh0Pgo8bGluZSB4MT0iNTU2IiB5MT0iNzciIHgyPSI1OTgiIHkyPSI3NyIgc3Ryb2tlLXdpZHRoPSIyIiBtYXJrZXItZW5kPSJ1cmwoI2VrOHMtaWQpIiBzdHlsZT0ic3Ryb2tlOiM2NDc0OGIiLz4KPHJlY3QgeD0iNjAyIiB5PSI0NCIgd2lkdGg9IjIxNCIgaGVpZ2h0PSI2NiIgcng9IjEyIiBzdHJva2Utd2lkdGg9IjEuNCIgc3Ryb2tlLWRhc2hhcnJheT0iNSA1IiBzdHlsZT0iZmlsbDojMGYxNzJhO3N0cm9rZTojNDc1NTY5Ii8+Cjx0ZXh0IHg9IjcwOSIgeT0iNzAiIHRleHQtYW5jaG9yPSJtaWRkbGUiIHN0eWxlPSJmb250OiA2NTAgMTMuNXB4IEludGVyLCBzYW5zLXNlcmlmOyBmaWxsOiAjZjFmNWY5OyBmb250LXNpemU6MTAuNXB4O2ZpbGw6Izk0YTNiOCI+RXh0ZXJuYWwgY2xvdWQgYWNjZXNzPC90ZXh0Pgo8dGV4dCB4PSI3MDkiIHk9IjkwIiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBzdHlsZT0iZm9udDogMTFweCBJbnRlciwgc2Fucy1zZXJpZjsgZmlsbDogIzk0YTNiOCI+Y3JlZGVudGlhbHMgb3IgZmVkZXJhdGlvbjwvdGV4dD4KPHRleHQgeD0iNzA5IiB5PSIxMDYiIHRleHQtYW5jaG9yPSJtaWRkbGUiIHN0eWxlPSJmb250OiAxMXB4IEludGVyLCBzYW5zLXNlcmlmOyBmaWxsOiAjOTRhM2I4Ij55b3UgY29uZmlndXJlPC90ZXh0Pgo8dGV4dCB4PSI0MTgiIHk9IjE1MCIgdGV4dC1hbmNob3I9Im1pZGRsZSIgc3R5bGU9ImZvbnQ6IDExcHggSW50ZXIsIHNhbnMtc2VyaWY7IGZpbGw6ICM5NGEzYjgiPkFXUyBjYWxscyBhcmUgYXV0aG9yaXplZCB3aXRoIHRoZSB0YXNrIHJvbGU7IGV4dGVybmFsIGNsb3VkIGFjY2VzcyBpcyBjb25maWd1cmVkIHNlcGFyYXRlbHkuPC90ZXh0Pgo8dGV4dCB4PSI0MTgiIHk9IjE3MCIgdGV4dC1hbmNob3I9Im1pZGRsZSIgc3R5bGU9ImZvbnQ6IDExcHggSW50ZXIsIHNhbnMtc2VyaWY7IGZpbGw6ICM5NGEzYjgiPkNsdXN0ZXIgaWRlbnRpdHkgaXMgYSBuYXRpdmUgU2VydmljZUFjY291bnQgd2l0aCBSQkFDLCB3aGljaCB5b3Ugb3duLjwvdGV4dD4KPC9zdmc+)

Cluster permissions, AWS calls and external-cloud credentials are configured separately.

#### AWS request authorization

For supported AWS API calls, Tensor9 checks the task role's IAM policy against the verified caller, action and resource; a denial overrides an allowance. Tensor9 prepares the policy rules during the build, including supported action and resource wildcards, and policy updates reach the Cloud Adapter deployment with an integrity check. See [AWS request authorization](https://docs.tensor9.com/cloud-adapter-early-access/service-catalog/aws/compute-containers/ecs-cluster.md#aws-request-authorization) for details.

Native permissions for external cloud services are granted separately, with credentials or federation that provider authorizes. Kubernetes RBAC governs the cluster API on its own, and the AWS policy check runs inside the Cloud Adapter deployment without a cloud IAM service.

#### Secrets and logging

Container `environment` variables are set as they are. Container `secrets` entries are not supported: if a container passes secrets through `valueFrom`, deployment stops with an error that names the service and each variable, rather than starting the container without them. On this target, Parameter Store values live in **Kubernetes Secrets**, often managed through the External Secrets Operator.

The `awslogs` log driver becomes **the cluster's own log stack**, which collects stdout and stderr automatically. A custom FireLens log router can still run as a helper container; configure its destination and credentials for your environment's logging service.

#### Limitations

* **Container secrets are not supported.** A container `secrets` entry (`valueFrom`) stops the deployment with an error naming the service and the variable, rather than starting the container without it.
* **ECS Service Connect is only partly supported.** A Kubernetes Service provides name-based discovery, but Service Connect's injected proxy and its built-in metrics need a service mesh you add, such as Istio or Linkerd. You run that mesh.
* **You must add tooling for weighted blue-green or canary releases.** A plain rolling update works natively; a weighted traffic split uses Gateway API, Argo Rollouts or Flagger.
* **Capacity providers and Fargate Spot behave differently: your node pools provide capacity.** A capacity-provider strategy maps to your node pools, and a Spot preference maps to your Spot node pools.
* **You must configure each credential path.** Kubernetes RBAC governs cluster access. AWS adapters use the task role; real external services need credentials or federation their provider authorizes.
* **The task metadata endpoint is read-only.** Your code reaches the ECS task metadata API through `ECS_CONTAINER_METADATA_URI_V4`, as on ECS. Other AWS calls go to the matching Tensor9 adapters.

#### Other considerations

* **Moving from AWS.** A task definition and service hold no data, and each image is copied to your registry during the build, so moving is a redeploy. Volumes a task mounts (EFS, EBS) move under their own service mappings.
* **Confirm who operates what.** On a self-operated cluster you maintain the control plane, nodes and add-ons. A managed cluster you bring keeps its provider's control-plane and add-on services.
* **Cost.** `desiredCount` becomes always-on replicas on nodes you provision, sized by your node pools rather than billed per Fargate task.
* **What to monitor.** Logs flow through the node's log stack and Parameter Store values live in Kubernetes Secrets, so there is no CloudWatch or Secrets Manager in the path; observability is whatever the cluster runs.

#### Runtime task execution

The runtime ECS API is not available today. Calls your application makes through the AWS SDK, such as RegisterTaskDefinition, RunTask, DescribeTasks, ListTasks and StopTask, are not answered: the Cloud Adapter deployment does not start the ECS adapter until task-role delivery and placement are qualified. The ECS services you declare in Terraform are compiled to Kubernetes workloads at deployment, as described above, and their containers run on the target cluster.

Check readiness and container exit information through Kubernetes, not through the ECS API. Service deployment, scaling and workload credentials are separate concerns. The target cluster schedules and runs the containers. A Kubernetes ServiceAccount does not by itself supply AWS credentials, so containers that call AWS need a separate identity setup. Check task and service features against their own rows, including network policy, Service Connect, storage and execution settings.

#### Example monthly charges

This Tensor9 Cloud Adapter scenario estimates service charges for the named origin and target services. Adapter hosting and commercial Tensor9 fees need separate allocations. [How Tensor9 estimates costs](https://docs.tensor9.com/cloud-adapter-early-access/costs/overview.md) explains the method and what the estimates include.

##### ECS task execution on Kubernetes · Allocated task CPU-seconds per month

Feature: ECS task execution on Kubernetes.

Estimated monthly service charges by Allocated task CPU-seconds per month. Adapter hosting and Tensor9 fees are excluded. Source: us-east-1; target: us-central1; currency: USD.

![ECS task execution on Kubernetes · Allocated task CPU-seconds per month: monthly service charges by Allocated task CPU-seconds per month. Exact values are in the following table.](https://docs.tensor9.com/images/cloud-adapter-early-access/diagrams/service-cost/72e858c190e034ee6587a2fb1bc3874acf796803172a3981a46e0ba1a7892788-light.svg)

![ECS task execution on Kubernetes · Allocated task CPU-seconds per month: monthly service charges by Allocated task CPU-seconds per month. Exact values are in the following table.](https://docs.tensor9.com/images/cloud-adapter-early-access/diagrams/service-cost/e33a5dd8ae26ce22938da162b8a8ffe22b5718f4d820f4fe512f7a1da4c5c39f-dark.svg)

Comparison pills describe all sampled scale points; amounts beside each service are for the named workload. Costs The Same means within 20% at every point. Costs Depend includes mixed results and unpriced samples.

Sampled monthly charges in USD, rounded to cents. Difference means target minus origin; a positive difference means the target costs more.

| Allocated task CPU-seconds per month (vCPU-second/month) | ECS Cluster | Target scenario | Kubernetes Cluster | Difference |
| -: | -: | - | -: | -: |
| 0 | 6.49 | Kubernetes Cluster (one copy) | 80.90 | 74.41 |
| 0 | 6.49 | Kubernetes Cluster (two copies) | 161.79 | 155.30 |
| 262,800 | 9.44 | Kubernetes Cluster (one copy) | 80.90 | 71.45 |
| 262,800 | 9.44 | Kubernetes Cluster (two copies) | 161.79 | 152.35 |
| 2,628,000 | 36.04 | Kubernetes Cluster (one copy) | 151.79 | 115.75 |
| 2,628,000 | 36.04 | Kubernetes Cluster (two copies) | 303.58 | 267.54 |
| 26,280,000 | 301.99 | Kubernetes Cluster (one copy) | 1,144.34 | 842.35 |
| 26,280,000 | 301.99 | Kubernetes Cluster (two copies) | 2,288.68 | 1,986.68 |
| 262,800,000 | 2,961.52 | Kubernetes Cluster (one copy) | 10,299.04 | 7,337.53 |
| 262,800,000 | 2,961.52 | Kubernetes Cluster (two copies) | 20,598.09 | 17,636.57 |

Estimated allocation, not benchmark calibrated: sized from 2 vCPU, 8 GiB memory and 100 GiB SSD at 0 vCPU-second/month to 9 nodes of 32 vCPU, 128 GiB memory and 100 GiB SSD each at 262,800,000 vCPU-second/month.

**Curve assumptions**

| Target scenario | Assumption | Value | Unit |
| - | - | -: | - |
| Kubernetes Cluster (one copy) | Origin list price · Task CPU allocation | 0.0000112444 | USD/vCPU-second |
| Kubernetes Cluster (one copy) | Origin list price · Task memory allocation | 0.0000012347 | USD/GiB-second |
| Kubernetes Cluster (one copy) | Origin list price · Task starts | 0 | USD/Requests |
| Kubernetes Cluster (one copy) | Target worker packing utilization | 0.7 | fraction |
| Kubernetes Cluster (one copy) | Peak / average allocated task resources | 2 | multiplier |
| Kubernetes Cluster (one copy) | Target price guess · read | 0 | USD/read |
| Kubernetes Cluster (one copy) | Target price guess · write | 0 | USD/write |
| Kubernetes Cluster (one copy) | Target price guess · provider operation | 0 | USD/provider operation |
| Kubernetes Cluster (one copy) | Target list price · GiB-month | 0.1 | USD/GiB-month |
| Kubernetes Cluster (one copy) | Target price guess · published GiB | 0 | USD/published GiB |
| Kubernetes Cluster (one copy) | Target price guess · delivered GiB | 0 | USD/delivered GiB |
| Kubernetes Cluster (one copy) | Target list price · network GiB | 0.12 | USD/network GiB |
| Kubernetes Cluster (one copy) | Target price guess · replica GiB-month | 0 | USD/replica GiB-month |
| Kubernetes Cluster (one copy) | Target list price · vCPU-hour | 0.031611 | USD/vCPU-hour |
| Kubernetes Cluster (one copy) | Target list price · GiB-hour | 0.004237 | USD/GiB-hour |
| Kubernetes Cluster (one copy) | Target price guess · resource-hour | 0 | USD/resource-hour |
| Kubernetes Cluster (one copy) | Target price guess · resource-month | 0 | USD/resource-month |
| Kubernetes Cluster (one copy) | Target price guess · input token | 0 | USD/input token |
| Kubernetes Cluster (one copy) | Target price guess · output token | 0 | USD/output token |
| Kubernetes Cluster (one copy) | Target monthly base charge | 0 | USD/month |
| Kubernetes Cluster (one copy) | Approximate target service minimum | 0 | USD/month |
| Kubernetes Cluster (one copy) | Minimum primary CPU | 2 | vCPU |
| Kubernetes Cluster (one copy) | Minimum primary RAM | 8 | GiB |
| Kubernetes Cluster (one copy) | Minimum primary disk | 100 | GiB |
| Kubernetes Cluster (one copy) | Additional full-price standby copy | 0 | 0 or 1 |
| Kubernetes Cluster (one copy) | Allocated share of provisioned cost | 1 | fraction |
| Kubernetes Cluster (one copy) | Read/write work per vCPU-second | 1,500 | operations/vCPU-second |
| Kubernetes Cluster (one copy) | Planning peak / mean work | 2 | multiplier |
| Kubernetes Cluster (one copy) | Planning primary CPU utilization | 0.7 | fraction |
| Kubernetes Cluster (one copy) | Resident state reserved in RAM | 0.1 | fraction |
| Kubernetes Cluster (one copy) | Planning disk utilization | 0.8 | fraction |
| Kubernetes Cluster (one copy) | Maintenance and log disk reserve | 20 | GiB |
| Kubernetes Cluster (one copy) | Staging database CPU unit-price guess | 0.0413 | USD/vCPU-hour |
| Kubernetes Cluster (one copy) | Staging database RAM unit-price guess | 0.007 | USD/GiB-hour |
| Kubernetes Cluster (one copy) | Staging database disk unit-price guess | 0.17 | USD/GiB-month |
| Kubernetes Cluster (one copy) | Dependent object sink storage price guess | 0.023 | USD/GiB-month |
| Kubernetes Cluster (one copy) | Dependent object sink write price guess | 0.000005 | USD/write |
| Kubernetes Cluster (two copies) | Origin list price · Task CPU allocation | 0.0000112444 | USD/vCPU-second |
| Kubernetes Cluster (two copies) | Origin list price · Task memory allocation | 0.0000012347 | USD/GiB-second |
| Kubernetes Cluster (two copies) | Origin list price · Task starts | 0 | USD/Requests |
| Kubernetes Cluster (two copies) | Target worker packing utilization | 0.7 | fraction |
| Kubernetes Cluster (two copies) | Peak / average allocated task resources | 2 | multiplier |
| Kubernetes Cluster (two copies) | Target price guess · read | 0 | USD/read |
| Kubernetes Cluster (two copies) | Target price guess · write | 0 | USD/write |
| Kubernetes Cluster (two copies) | Target price guess · provider operation | 0 | USD/provider operation |
| Kubernetes Cluster (two copies) | Target list price · GiB-month | 0.1 | USD/GiB-month |
| Kubernetes Cluster (two copies) | Target price guess · published GiB | 0 | USD/published GiB |
| Kubernetes Cluster (two copies) | Target price guess · delivered GiB | 0 | USD/delivered GiB |
| Kubernetes Cluster (two copies) | Target list price · network GiB | 0.12 | USD/network GiB |
| Kubernetes Cluster (two copies) | Target price guess · replica GiB-month | 0 | USD/replica GiB-month |
| Kubernetes Cluster (two copies) | Target list price · vCPU-hour | 0.031611 | USD/vCPU-hour |
| Kubernetes Cluster (two copies) | Target list price · GiB-hour | 0.004237 | USD/GiB-hour |
| Kubernetes Cluster (two copies) | Target price guess · resource-hour | 0 | USD/resource-hour |
| Kubernetes Cluster (two copies) | Target price guess · resource-month | 0 | USD/resource-month |
| Kubernetes Cluster (two copies) | Target price guess · input token | 0 | USD/input token |
| Kubernetes Cluster (two copies) | Target price guess · output token | 0 | USD/output token |
| Kubernetes Cluster (two copies) | Target monthly base charge | 0 | USD/month |
| Kubernetes Cluster (two copies) | Approximate target service minimum | 0 | USD/month |
| Kubernetes Cluster (two copies) | Minimum primary CPU | 2 | vCPU |
| Kubernetes Cluster (two copies) | Minimum primary RAM | 8 | GiB |
| Kubernetes Cluster (two copies) | Minimum primary disk | 100 | GiB |
| Kubernetes Cluster (two copies) | Additional full-price standby copy | 1 | 0 or 1 |
| Kubernetes Cluster (two copies) | Allocated share of provisioned cost | 1 | fraction |
| Kubernetes Cluster (two copies) | Read/write work per vCPU-second | 1,500 | operations/vCPU-second |
| Kubernetes Cluster (two copies) | Planning peak / mean work | 2 | multiplier |
| Kubernetes Cluster (two copies) | Planning primary CPU utilization | 0.7 | fraction |
| Kubernetes Cluster (two copies) | Resident state reserved in RAM | 0.1 | fraction |
| Kubernetes Cluster (two copies) | Planning disk utilization | 0.8 | fraction |
| Kubernetes Cluster (two copies) | Maintenance and log disk reserve | 20 | GiB |
| Kubernetes Cluster (two copies) | Staging database CPU unit-price guess | 0.0413 | USD/vCPU-hour |
| Kubernetes Cluster (two copies) | Staging database RAM unit-price guess | 0.007 | USD/GiB-hour |
| Kubernetes Cluster (two copies) | Staging database disk unit-price guess | 0.17 | USD/GiB-month |
| Kubernetes Cluster (two copies) | Dependent object sink storage price guess | 0.023 | USD/GiB-month |
| Kubernetes Cluster (two copies) | Dependent object sink write price guess | 0.000005 | USD/write |

* Only this native meter varies; all other source usage and translation assumptions retain the displayed defaults. Other native meters and workload assumptions retain their explicitly displayed default quantities. Workload translation and capacity assumptions are not benchmark measurements.
* Native monthly usage priced at the cited provider list prices; listed target allowances apply where present, excluding invoice credits, taxes and negotiated discounts. Rates as of 2026-10-22: us-east-1 → us-central1, USD/month.
* Source prices are reference charges, not an invoice. Target lines cover selected service usage/configuration only; adapter hosting and Tensor9 fees are excluded.
* Samples of explicit prices are not performance measurements or capacity qualification. No interpolation or break-even guarantee is implied.
* Variant assumptions show the first axis sample; any axis-dependent configuration is described by this curve's workload note.
* Rates are cited provider list prices, editable for discounts, commitments or another region. Workload translation and capacity coefficients remain editable planning assumptions, not benchmark measurements or a commercial quote.
* Default-zero rates are explicit assumptions, not evidence that the deployed service or resource is free.
* Provisioned-unit minimums use an editable approximate allocation floor. Modeled target service cost is max(usage/allocation, minimum), with billable network, durable staging and dependent sinks added separately; actual RU/TU sizing, scaling increments and throughput remain unqualified.
* Durable staging is priced once: provisioned targets include adapter state in their selected allocation; native targets add a separate staging allocation when required. Adapter hosting is a separate allocation and must exclude resources already priced as staging, workers or target capacity.
* A declared adapter mapping and cost model do not establish implementation availability or service equivalence.
* This is a declared directed mapping; a planning estimate does not establish deployment or request-serving support.
* Origin unit prices are cited provider list prices; capacity coefficients and translation assumptions are editable authored planning guesses, not measured capacity or a provider quote.
* Management requests do not reveal resource allocation or workload traffic. Provisioned resources and traffic are independent inputs.
* Task CPU and memory independently grow worker resource-hours; task-start counts are not a capacity estimate.
* The runtime ECS management endpoint and catalog compile-time container targets have different serving availability.
* Self-hosted target: Kubernetes (Apache-2.0, [https://github.com/kubernetes/kubernetes/blob/master/LICENSE](https://github.com/kubernetes/kubernetes/blob/master/LICENSE)); the host cloud's managed control plane is a separate per-cluster-hour allocation. Selected CPU, RAM and physical disk allocation grow with workload; no per-operation price is assumed. No vendor charge: the target runs on the customer's Kubernetes nodes, so CPU, RAM and disk bill at the Kubernetes node reference rates, Compute Engine N2 in us-central1 (USD 0.031611/vCPU-hour, 0.004237/GiB-hour) with pd-balanced disk (0.10/GiB-month) and Premium Tier egress. The cost-optimized E2 series lists 0.02181159/vCPU-hour and 0.00292353/GiB-hour; AWS m6i/r6i and Azure D2s v5/E2s v5 both decompose to 0.033/vCPU-hour and 0.00375/GiB-hour. Requested CPU and RAM are billed; node bin-packing waste, system reservations and the cluster control-plane fee are not.
* Row-store throughput (capacityOpsPerVcpuSecond, default 1500) is measured-by-tensor9 as a lower bound: the DynamoDB adapter on Cloud SQL db-custom-2-7680 (2 vCPU, PostgreSQL 16, us-west1) served 2,974 ops/s of YCSB-A at 16 threads without recorded saturation (src/main/kotlin/t9/prime/equiv/generated/eval/CloudsqlPostgresqlYcsbAT16GoYcsbV1\_0\_0.kt). Published CPU-bound pgbench reaches 3,101 read-write transactions and 20,289 point reads per vCPU-second (AWS z1d.2xlarge, PostgreSQL 14.5), so actual capacity is likely higher. Reads and writes share one coefficient: at the same adapter version, read-only YCSB-C was not faster than 50%-update YCSB-A.
* Log-broker throughput (capacityStreamMiBPerVcpuSecond 20 at 0.5 utilization, 4 GiB RAM per vCPU) is provider-documented by Google Managed Service for Apache Kafka sizing ([https://docs.cloud.google.com/managed-service-for-apache-kafka/docs/plan-cluster-size](https://docs.cloud.google.com/managed-service-for-apache-kafka/docs/plan-cluster-size)): write-equivalent bytes are replicated writes plus a quarter of reads. Producer batches below 10 KB lower per-CPU throughput; that penalty is not modeled.
* Disk utilization 0.8 is provider-documented headroom below Cloud SQL automatic storage increase, which triggers near 91-95% full ([https://docs.cloud.google.com/sql/docs/postgres/instance-settings](https://docs.cloud.google.com/sql/docs/postgres/instance-settings)). The 20 GiB reserve exceeds PostgreSQL's 1 GB default max\_wal\_size; the remainder of that reserve is unmeasured.
* CPU tiers double from 2 vCPUs to the target's largest node at 4 GiB per vCPU; each target's documented largest node bounds CPU, RAM, RAM per vCPU and disk, and the durable staging database uses Cloud SQL Enterprise (96 vCPU, 6.5 GiB per vCPU, 624 GiB, 64 TiB). Targets billed per capacity unit or throughput unit are sized by their backend instead.
* No public evidence: peak/mean work (2) and the RAM working-set fraction (0.1). Proposed measurements: the p99 one-minute rate over the monthly mean from customer CloudWatch metrics; the buffer hit ratio while stepping RAM under a fixed YCSB-B load.
* Node bounds: Planning worker node of 32 vCPUs and 128 GiB, not a provider maximum; the cluster adds nodes up to a 1,000-node planning bound. Requested CPU and RAM bill linearly, so the node size changes only rounding.
* Stored GiB already includes the origin family's physical footprint assumptions; no second storage amplification is applied.
* The workload family already selected resource-hours; the throughput coefficient is not applied again.
* Copies and allocation fractions change cost only; they do not increase modeled primary capacity.
* AWS Price List API, AmazonECS offer: [https://pricing.us-east-1.amazonaws.com/offers/v1.0/aws/AmazonECS/current/us-east-1/index.json](https://pricing.us-east-1.amazonaws.com/offers/v1.0/aws/AmazonECS/current/us-east-1/index.json)
* Amazon ECS pricing: [https://aws.amazon.com/ecs/pricing/](https://aws.amazon.com/ecs/pricing/)
* Compute Engine general-purpose machine pricing: [https://cloud.google.com/products/compute/pricing/general-purpose](https://cloud.google.com/products/compute/pricing/general-purpose)
* Disk and image pricing: [https://cloud.google.com/compute/disks-image-pricing](https://cloud.google.com/compute/disks-image-pricing)
* Network pricing: [https://cloud.google.com/vpc/network-pricing](https://cloud.google.com/vpc/network-pricing)

Cost scope: Modeled target native service and explicitly modeled state allocation; hosting and Tensor9 fees only when supplied.

Excluded costs and workload features:

* Cluster control plane, worker idle floor, image pulls, persistent storage, GPU tasks, networking and ECS service lifecycle.
* Taxes, discounts, credits and free-tier allowances not explicitly listed by this model.
* Unmodeled dependent services, task execution and operations outside the selected workload family.

List prices read: 2026-10-22. Model: `plan-351fa675b0206b0661fb0e787b5c1d6d303c1fd4` / `2026-10-22.planning.2`. Curve: `workload-1`.

Sources: [AWS Price List API, AmazonECS offer](https://pricing.us-east-1.amazonaws.com/offers/v1.0/aws/AmazonECS/current/us-east-1/index.json), [Amazon ECS pricing](https://aws.amazon.com/ecs/pricing/), [Compute Engine general-purpose machine pricing](https://cloud.google.com/products/compute/pricing/general-purpose), [Disk and image pricing](https://cloud.google.com/compute/disks-image-pricing), [Network pricing](https://cloud.google.com/vpc/network-pricing).

**ECS task execution on Kubernetes → Kubernetes Cluster: Authored native-usage planning example.** Native monthly usage priced at the cited provider list prices; listed target allowances apply where present, excluding invoice credits, taxes and negotiated discounts.

Scenario source region: us-east-1. Scenario target region: us-central1. Currency: USD.

| Monthly component | USD |
| - | -: |
| Origin: Task CPU allocation | 29.55 |
| Origin: Task memory allocation | 6.49 |
| Origin: Task starts | 0.00 |
| Target: Provisioned primary CPU | 92.30 |
| Target: Provisioned primary RAM | 49.49 |
| Target: Provisioned primary disk | 10.00 |
| Target: Selected billable network | 0.00 |
| Target: Independent provisioned resources | 0.00 |
| Target: Independent managed resources | 0.00 |
| **Origin service subtotal** | **36.04** |
| **Target service subtotal** | **151.79** |

Estimated allocation, not benchmark calibrated: sized at 4 vCPU, 16 GiB memory and 100 GiB SSD for this scenario.

Unestimated components: Adapter hosting, Tensor9 fees. A modeled adapted total and savings require these costs.

Cost scope: Modeled target native service and explicitly modeled state allocation; hosting and Tensor9 fees only when supplied.

Excluded costs and workload features:

* Cluster control plane, worker idle floor, image pulls, persistent storage, GPU tasks, networking and ECS service lifecycle.
* Taxes, discounts, credits and free-tier allowances not explicitly listed by this model.
* Unmodeled dependent services, task execution and operations outside the selected workload family.

**Scenario assumptions**

| Input | Value | Unit |
| - | -: | - |
| Origin list price · Task CPU allocation | 0.0000112444 | USD/vCPU-second |
| Origin list price · Task memory allocation | 0.0000012347 | USD/GiB-second |
| Origin list price · Task starts | 0 | USD/Requests |
| Target worker packing utilization | 0.7 | fraction |
| Peak / average allocated task resources | 2 | multiplier |
| Target price guess · read | 0 | USD/read |
| Target price guess · write | 0 | USD/write |
| Target price guess · provider operation | 0 | USD/provider operation |
| Target list price · GiB-month | 0.1 | USD/GiB-month |
| Target price guess · published GiB | 0 | USD/published GiB |
| Target price guess · delivered GiB | 0 | USD/delivered GiB |
| Target list price · network GiB | 0.12 | USD/network GiB |
| Target price guess · replica GiB-month | 0 | USD/replica GiB-month |
| Target list price · vCPU-hour | 0.031611 | USD/vCPU-hour |
| Target list price · GiB-hour | 0.004237 | USD/GiB-hour |
| Target price guess · resource-hour | 0 | USD/resource-hour |
| Target price guess · resource-month | 0 | USD/resource-month |
| Target price guess · input token | 0 | USD/input token |
| Target price guess · output token | 0 | USD/output token |
| Target monthly base charge | 0 | USD/month |
| Approximate target service minimum | 0 | USD/month |
| Minimum primary CPU | 2 | vCPU |
| Minimum primary RAM | 8 | GiB |
| Minimum primary disk | 100 | GiB |
| Additional full-price standby copy | 0 | 0 or 1 |
| Allocated share of provisioned cost | 1 | fraction |
| Read/write work per vCPU-second | 1,500 | operations/vCPU-second |
| Planning peak / mean work | 2 | multiplier |
| Planning primary CPU utilization | 0.7 | fraction |
| Resident state reserved in RAM | 0.1 | fraction |
| Planning disk utilization | 0.8 | fraction |
| Maintenance and log disk reserve | 20 | GiB |
| Staging database CPU unit-price guess | 0.0413 | USD/vCPU-hour |
| Staging database RAM unit-price guess | 0.007 | USD/GiB-hour |
| Staging database disk unit-price guess | 0.17 | USD/GiB-month |
| Dependent object sink storage price guess | 0.023 | USD/GiB-month |
| Dependent object sink write price guess | 0.000005 | USD/write |
| Task CPU allocation | 2,628,000 | vCPU-second |
| Task memory allocation | 5,256,000 | GiB-second |
| Task starts | 43,800 | Requests |

* Translated reads: 0 operations.

* Translated writes: 0 operations.

* Translated resident physical data: 0 GiB-month.

* Native provider operations: 43,800 operations.

* Published payload: 0 GiB.

* Delivered payload: 0 GiB.

* Allocated execution CPU: 2,086 vCPU-hour.

* Allocated execution RAM: 4,171 GiB-hour.

* Independent resource allocation: 0 resource-hour.

* Independent inventory: 0 resource-month.

* Input tokens: 0 tokens.

* Output tokens: 0 tokens.

* Billable network: 0 GiB.

* Dependent object sink retained data: 0 GiB-month.

* Dependent object sink writes: 0 writes.

* Rates are cited provider list prices, editable for discounts, commitments or another region. Workload translation and capacity coefficients remain editable planning assumptions, not benchmark measurements or a commercial quote.

* Default-zero rates are explicit assumptions, not evidence that the deployed service or resource is free.

* Provisioned-unit minimums use an editable approximate allocation floor. Modeled target service cost is max(usage/allocation, minimum), with billable network, durable staging and dependent sinks added separately; actual RU/TU sizing, scaling increments and throughput remain unqualified.

* Durable staging is priced once: provisioned targets include adapter state in their selected allocation; native targets add a separate staging allocation when required. Adapter hosting is a separate allocation and must exclude resources already priced as staging, workers or target capacity.

* A declared adapter mapping and cost model do not establish implementation availability or service equivalence.

* This is a declared directed mapping; a planning estimate does not establish deployment or request-serving support.

* Origin unit prices are cited provider list prices; capacity coefficients and translation assumptions are editable authored planning guesses, not measured capacity or a provider quote.

* Management requests do not reveal resource allocation or workload traffic. Provisioned resources and traffic are independent inputs.

* Task CPU and memory independently grow worker resource-hours; task-start counts are not a capacity estimate.

* The runtime ECS management endpoint and catalog compile-time container targets have different serving availability.

* Self-hosted target: Kubernetes (Apache-2.0, [https://github.com/kubernetes/kubernetes/blob/master/LICENSE](https://github.com/kubernetes/kubernetes/blob/master/LICENSE)); the host cloud's managed control plane is a separate per-cluster-hour allocation. Selected CPU, RAM and physical disk allocation grow with workload; no per-operation price is assumed. No vendor charge: the target runs on the customer's Kubernetes nodes, so CPU, RAM and disk bill at the Kubernetes node reference rates, Compute Engine N2 in us-central1 (USD 0.031611/vCPU-hour, 0.004237/GiB-hour) with pd-balanced disk (0.10/GiB-month) and Premium Tier egress. The cost-optimized E2 series lists 0.02181159/vCPU-hour and 0.00292353/GiB-hour; AWS m6i/r6i and Azure D2s v5/E2s v5 both decompose to 0.033/vCPU-hour and 0.00375/GiB-hour. Requested CPU and RAM are billed; node bin-packing waste, system reservations and the cluster control-plane fee are not.

* Row-store throughput (capacityOpsPerVcpuSecond, default 1500) is measured-by-tensor9 as a lower bound: the DynamoDB adapter on Cloud SQL db-custom-2-7680 (2 vCPU, PostgreSQL 16, us-west1) served 2,974 ops/s of YCSB-A at 16 threads without recorded saturation (src/main/kotlin/t9/prime/equiv/generated/eval/CloudsqlPostgresqlYcsbAT16GoYcsbV1\_0\_0.kt). Published CPU-bound pgbench reaches 3,101 read-write transactions and 20,289 point reads per vCPU-second (AWS z1d.2xlarge, PostgreSQL 14.5), so actual capacity is likely higher. Reads and writes share one coefficient: at the same adapter version, read-only YCSB-C was not faster than 50%-update YCSB-A.

* Log-broker throughput (capacityStreamMiBPerVcpuSecond 20 at 0.5 utilization, 4 GiB RAM per vCPU) is provider-documented by Google Managed Service for Apache Kafka sizing ([https://docs.cloud.google.com/managed-service-for-apache-kafka/docs/plan-cluster-size](https://docs.cloud.google.com/managed-service-for-apache-kafka/docs/plan-cluster-size)): write-equivalent bytes are replicated writes plus a quarter of reads. Producer batches below 10 KB lower per-CPU throughput; that penalty is not modeled.

* Disk utilization 0.8 is provider-documented headroom below Cloud SQL automatic storage increase, which triggers near 91-95% full ([https://docs.cloud.google.com/sql/docs/postgres/instance-settings](https://docs.cloud.google.com/sql/docs/postgres/instance-settings)). The 20 GiB reserve exceeds PostgreSQL's 1 GB default max\_wal\_size; the remainder of that reserve is unmeasured.

* CPU tiers double from 2 vCPUs to the target's largest node at 4 GiB per vCPU; each target's documented largest node bounds CPU, RAM, RAM per vCPU and disk, and the durable staging database uses Cloud SQL Enterprise (96 vCPU, 6.5 GiB per vCPU, 624 GiB, 64 TiB). Targets billed per capacity unit or throughput unit are sized by their backend instead.

* No public evidence: peak/mean work (2) and the RAM working-set fraction (0.1). Proposed measurements: the p99 one-minute rate over the monthly mean from customer CloudWatch metrics; the buffer hit ratio while stepping RAM under a fixed YCSB-B load.

* Node bounds: Planning worker node of 32 vCPUs and 128 GiB, not a provider maximum; the cluster adds nodes up to a 1,000-node planning bound. Requested CPU and RAM bill linearly, so the node size changes only rounding.

* Stored GiB already includes the origin family's physical footprint assumptions; no second storage amplification is applied.

* The workload family already selected resource-hours; the throughput coefficient is not applied again.

* Copies and allocation fractions change cost only; they do not increase modeled primary capacity.

List prices read: 2026-10-22. Model: `plan-351fa675b0206b0661fb0e787b5c1d6d303c1fd4` / `2026-10-22.planning.2`. Scenario: `planning-example`.

Sources: [AWS Price List API, AmazonECS offer](https://pricing.us-east-1.amazonaws.com/offers/v1.0/aws/AmazonECS/current/us-east-1/index.json), [Amazon ECS pricing](https://aws.amazon.com/ecs/pricing/), [Compute Engine general-purpose machine pricing](https://cloud.google.com/products/compute/pricing/general-purpose), [Disk and image pricing](https://cloud.google.com/compute/disks-image-pricing), [Network pricing](https://cloud.google.com/vpc/network-pricing).

## Costs

Estimated monthly service charges for each backend with a published cost model, at one sampled workload from that model's cost curve. Adapter hosting and Tensor9 fees are excluded. [How Tensor9 estimates costs](https://docs.tensor9.com/cloud-adapter-early-access/costs/overview.md) explains the method, what the estimates include and how to read their qualifications.

| Backend | Sampled workload | Price basis | Origin USD/month | Backend USD/month | Difference | Mapping |
| - | - | - | -: | -: | -: | - |
| Kubernetes Cluster | Allocated task CPU-seconds per month: 2,628,000 vCPU-second/month; one copy | Cited list prices, 2026-10-22 | 36.04 | 151.79 | +115.75 | Service adapter |

Difference means backend minus origin; a positive difference means the backend costs more. Workloads and target configurations differ by model, so compare each row's difference at its stated workload rather than charges across rows.
Cost curves across workload sizes, with every assumption and exclusion: [ECS Cluster costs](https://docs.tensor9.com/cloud-adapter-early-access/costs/additional-services/aws-ecs-cluster).

## Service level agreements

> [!WARNING]
>
> These tables show Tensor9's standard service levels and adapters whose standard terms are still being defined. Your signed agreement determines the SLAs, covered adapters and operations, limits, remedies and support terms that apply to your deployment.

Listed terms cover requests sent through this service adapter. They do not cover direct connections to the target service or replace the cloud provider's own SLA. Each origin-to-target pair has its own terms or an explicit pending status.

See the [SLA tables](https://docs.tensor9.com/cloud-adapter-early-access/support/service-adapter-slas.md), [measurement rules](https://docs.tensor9.com/cloud-adapter-early-access/support/service-levels.md), and [scaling conditions](https://docs.tensor9.com/cloud-adapter-early-access/support/scaling-and-limits.md).

### ECS Cluster to Kubernetes Cluster

| SLA | Service level | What is covered | Conditions |
| - | - | - | - |
| Cluster and workload desired-state admission adapter-added latency | +20 ms monthly p99 | `aws::1.0.0::ecs`: `CreateService`, `RegisterTaskDefinition`, `UpdateService` | One cluster/service/task definition; at most 20 containers and at most 100 environment/secret/network entries; readiness separate. |
| Documented adapter behavior | Preserve the supported behavior documented for this adapter | `aws::1.0.0::ecs`: `CreateService`, `RegisterTaskDefinition`, `UpdateService` | Accepted desired state is durable and generation ordered. Workload identity binds only the intended service account/role, secrets are not emitted into public fields, and observed status never claims readiness before the target reports it. Unsupported scheduling or networking modes fail before partial creation. |
| Endpoint reachability | 99.9% per calendar month | Adapter endpoint reachability | The agreed production deployment has healthy target connectivity and receives a valid adapter health probe. This measures the adapter endpoint, not the target provider's service. |
| Adapter autoscaling and limits | Automatic scaling within the workload and deployment limits in your agreement | Adapter behavior across requests | Your agreement states the maximum request rate, burst size, request and response sizes, concurrency, and target calls per request. Tensor9 maintains adapter capacity inside that envelope. Target-service quotas and capacity are separate. |

**Adapter-added latency.** A + prefix marks time added by the adapter, not the total time your application waits. Total request time includes adapter processing, backend service time and network time. The backend provider's SLA applies independently. Only separately measured target-service wait may be subtracted, and only when your agreement permits it; internal metadata, coordination and retry processing still count. For one request, 12 ms of adapter processing plus 90 ms waiting for the backend means at least 102 ms total. This example does not add monthly p99 values.

**What Tensor9 covers.** These service levels cover the adapter between the origin API and target API. They do not replace the target provider's SLA.

**How latency is counted.** Adapter work, including metadata and coordination, counts. Only separately measured permitted target waits are excluded.

**Which terms apply.** Your signed agreement names the covered operations, workload limits, remedies, and final service levels for your deployment.

#### What this adapter does

Cluster, workload and identity calls validate AWS-shaped intent, record the desired resource and reconcile native objects on kubernetes::1.0.0::cluster. In-cluster Kubernetes traffic and application packet flow are not proxied by this control-plane estimate. Provider provisioning and image pull time are readiness phases; adapter validation, durable admission and status conversion remain covered.

#### How the latency targets were chosen

**Cluster and workload desired-state admission: +20 ms monthly p99 (adapter-added).** `CreateService`, `RegisterTaskDefinition`, `UpdateService`. Validation, durable generation commit and reconciliation scheduling.

Your signed agreement sets the terms for your deployment. A target does not add an operation or option that the compatibility tables mark unavailable.

#### What counts toward latency

For a request-response row, measure from the agreed ingress boundary to dispatch of the complete response. A row that explicitly names a first response chunk ends at that chunk; its number does not cover the rest of the stream. A long-poll row names the intentional wait and when adapter delay starts. Include parsing, authorization, admission, translation, serialization, adapter-owned storage and coordination, retries and response handling. Subtract only separately measured target-workload waits and external network segments allowed by the measurement rules. The adapter's own response handling and dispatch remain covered. A database used for adapter metadata is still adapter work, even if a cloud provider hosts it.

For concurrent calls, exclude the union of permitted wait intervals, not the sum of overlapping spans. Calculate each request's adapter duration first, then the monthly p99. Do not subtract one service's p99 from another's. Known adapter timeouts are over-budget samples; failed or incomplete requests cannot disappear to improve the percentile. Missing measurements do not become zero latency. An SDK call span alone does not prove how much of its duration can be excluded.

#### Endpoint reachability and request failures

The endpoint-reachability target measures adapter health checks. Correctly forwarding a target quota or permission error is different from producing that error because the adapter sent the wrong request. Adapter-caused failures remain Tensor9's responsibility even when the target is healthy.

Correctness and data-integrity requirements apply to every supported request. Endpoint reachability does not measure request correctness or grant an allowance for incorrect results.

#### Scaling and target-service capacity

Independent clusters, services, tasks and identity associations reconcile concurrently. Mutations for one object serialize by generation, list calls are bounded pages, and status polling must not starve writes. Qualification fixes object count, manifest size, container count, tag count and concurrent reconcilers.

Tell Tensor9 the expected steady rate, bursts, concurrency, payload sizes and operation mix. Tensor9 sizes and scales the adapter for the agreed load; you choose and monitor the target service's capacity with Tensor9's help. A latency budget is not a requests-per-second rating. Larger requests and higher rates need explicit terms, not silent inheritance of a small-request SLA.

#### Data and behavior guarantees

Accepted desired state is durable and generation ordered. Workload identity binds only the intended service account/role, secrets are not emitted into public fields, and observed status never claims readiness before the target reports it. Unsupported scheduling or networking modes fail before partial creation.

#### Example and diagnosis

CreateCluster records a bounded cluster specification and returns its stable identity. Native provisioning may continue after the adapter response. DescribeCluster is a bounded read of desired plus observed state and must not report ACTIVE until the target control plane is actually ready.

Use `tensor9 explain` and the documented explain headers to understand the selected adapter and its behavior. Correlate available request diagnostics with the target provider's latency, throttling and capacity metrics. An explain report helps diagnose a request; it is not by itself a qualified SLA timing measurement. Share the operation, request shape, timestamps and request identifiers with support, with credentials and customer payloads removed.

## Install and run

The documentation and SLAs are public. Downloading and running the Cloud Adapter binary requires an entitled customer account. Set `T9_API_KEY` as described in [Install and Authenticate](https://docs.tensor9.com/cloud-adapter-early-access/getting-started/install-and-authenticate.md), then list the adapters your account may use with this origin:

```sh theme={null}
tensor9 adapt svc list \
  -origin aws::1.0.0::ecs::cluster
```

The result is limited to directed mappings for this origin that your account is entitled to use. Use a returned backend identifier when configuring the adapter or investigating a request.

Request binary access from [hello@tensor9.com](mailto:hello@tensor9.com) if your account does not yet include this direction.

## Existing data and credentials

Selecting a backend does not copy existing data, credentials or access policies. Plan and verify migration separately before changing an application's endpoint. Do not assume an identifier, credential or encrypted value from the origin service works unchanged on the target.

## Configure, tune and debug

Start with [setup](https://docs.tensor9.com/cloud-adapter-early-access/getting-started/overview.md) and [configuration](https://docs.tensor9.com/cloud-adapter-early-access/configuration/overview.md). Use [tuning](https://docs.tensor9.com/cloud-adapter-early-access/tuning/overview.md) to understand supported request tags, [debugging](https://docs.tensor9.com/cloud-adapter-early-access/debugging/overview.md) to investigate a request, and [High Fidelity Cloud Emulators](https://docs.tensor9.com/cloud-adapter-early-access/local-testing/overview.md) to validate a bounded reproduction.

For requests that go through an entitled service adapter, use [tensor9 explain](https://docs.tensor9.com/cloud-adapter-early-access/debugging/explain.md) and [x-t9-explain](https://docs.tensor9.com/cloud-adapter-early-access/debugging/response-headers.md) to inspect the selected mapping.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.