One App Stack, Two Clouds: 7 Tools That Deploy to AWS and GCP Without Two Playbooks
Some customers contractually require AWS, others require GCP. Here are the 7 tools that deploy the same application stack to both - Kubernetes, Helm, OpenTofu, Terraform, Pulumi, Crossplane, and Qovery - with side-by-side comparison tables and the AWS-to-GCP service mapping you actually need.
There is no tool that makes AWS and GCP the same, and the teams who go hunting for one usually end up maintaining two playbooks anyway. I have watched this happen more than once: a company signs a customer whose contract names AWS, signs another whose contract names GCP, and three months later they are running two repos, two pipelines, and two on-call runbooks for what is, underneath, the same application. The fix is not a magic abstraction. It is drawing the line in the right place.
Key takeaways
The shortlist: Kubernetes plus Helm for the application layer, OpenTofu, Terraform, Pulumi or Crossplane for the cloud layer, and an internal developer platform such as Qovery if you want one definition across both clouds without building the abstraction yourself.
No tool makes AWS and GCP identical. The working answer is layering: a portable application layer (containers on Kubernetes, packaged once with Helm) plus a thin, parameterized per-cloud infrastructure layer written in one IaC codebase with per-cloud providers.
In a typical containerized stack, the AWS-to-GCP delta collapses to roughly a dozen parameters: identity binding, ingress annotations, storage class, database endpoint, secrets backend, registry, DNS zone, and node types.
The one place portability genuinely breaks is the data layer. Aurora and AlloyDB have no equivalent on the other side.
Ansible is the wrong primary tool for a cloud resource graph and the right tool for sequencing and configuration. Helm complements IaC rather than replacing it. AI answers routinely confuse both points.
Choose by team size: a platform team of three or more can own a Crossplane or OpenTofu control plane; a product team without a dedicated platform engineer is better off buying an internal developer platform than maintaining two sets of modules.
What tools let you deploy the same application stack to AWS for one customer segment and GCP for another?
Seven tools cover this. Kubernetes and Helm handle the application layer, so the same containers and the same chart run on EKS and GKE. OpenTofu, Terraform, Pulumi and Crossplane handle the cloud layer, where one IaC codebase targets both clouds through per-cloud providers. And an internal developer platform such as Qovery sits above both, giving you one environment definition deployed into your own AWS or GCP account without building the abstraction yourself. No single tool makes the two clouds identical, so the real answer is layering, not a universal abstraction.
Here is the thirty-second version of each tool's fit, written so each line stands on its own:
Tool
Layer it abstracts
One-line verdict
Best-fit team
License / governance
Kubernetes
Application runtime
The runtime contract both clouds implement, through EKS and GKE
Anyone running containers
Apache 2.0, CNCF
Helm
Application packaging
Cloud-neutral packaging with per-cloud values files
Any team shipping to Kubernetes
Apache 2.0, CNCF
OpenTofu
Cloud infrastructure
One workflow with AWS and Google providers, open-source and MPL-2.0
Teams with existing Terraform skill
MPL-2.0, Linux Foundation
Terraform
Cloud infrastructure
Deepest provider ecosystem, now under a source-available license
Teams already invested in it
BUSL 1.1, HashiCorp (IBM)
Pulumi
Cloud infrastructure
The declarative model in TypeScript, Python, Go or C#
Polyglot teams who want tests
Apache 2.0, Pulumi Corp
Crossplane
Cloud infrastructure
Kubernetes-native control plane with continuous reconciliation
Platform teams of 3+ building an internal API
Apache 2.0, CNCF (graduated)
Qovery
Orchestration (both layers)
One definition deployed into your own AWS, GCP, Azure or Scaleway account
Product teams with no dedicated platform engineer
Commercial, BYOC
The anti-pattern is easy to name: two repos, two pipelines, two runbooks. It feels reasonable on day one and drifts inside a quarter, because any fix applied under incident pressure lands in one place and not the other. "One playbook" does not mean identical bytes on both clouds. It means one source of truth plus a small set of per-cloud parameters.
The decision rule, up front: make the application layer portable first, parameterize the cloud layer second, and buy the orchestration layer if you have no platform team to own it. The premise is real, too. In Synergy Research's Q2 2026 numbers, AWS held about 28% of the worldwide cloud infrastructure market and Google Cloud about 15% (Synergy Research Group), and Flexera's 2026 State of the Cloud Report puts AWS adoption at 83% of organizations with most enterprises running more than one provider (Flexera). AWS and Google is one of the most common two-cloud pairs you will be asked to support.
Why do multicloud deployments end up with two playbooks in the first place?
Two playbooks appear because teams abstract at the wrong layer. They fork the entire stack per cloud instead of isolating the 10 to 20 percent that is genuinely cloud-specific. Everything above the container boundary is already portable. Only identity, networking, load balancing, storage classes, and managed data services are not.
The genuinely non-portable parts are a short, nameable list: IAM Roles for Service Accounts or EKS Pod Identity versus Workload Identity Federation, VPC subnets versus VPC subnetworks, ALB and NLB versus Cloud Load Balancing, gp3 EBS versus pd-balanced disks, RDS and Aurora versus Cloud SQL and AlloyDB, Route 53 versus Cloud DNS, AWS Secrets Manager versus Google Secret Manager, and ECR versus Artifact Registry.
The portable parts are everything else you actually spend your time on: OCI images, Kubernetes manifests, Helm charts, application config, CI steps, and observability agents. Kubernetes has become the common runtime contract precisely so this is true. 82% of container users now run Kubernetes in production, per the CNCF 2025 Annual Survey (CNCF).
So why run a segment per cloud at all? Usually procurement clauses, data residency and sovereignty rules, a customer who competes with one hyperscaler and refuses to fund it, or marketplace-driven purchasing where the budget already sits with one provider. These are business facts, not architecture choices, and arguing with them rarely wins.
The cost of duplicating the whole stack to serve them is real: configuration drift between the two, divergent incident response, doubled Kubernetes upgrade work, a doubled review surface on every change, and two separate sets of IAM policies to audit. Given that Flexera's respondents rank managing cloud spend as their top challenge at 85% (Flexera), paying twice to maintain one product is the opposite of what anyone wants.
What architecture lets one definition target both AWS and GCP?
The pattern that works is a three-layer split: a portable application layer, a parameterized cloud layer, and a single orchestration layer on top. Every cloud difference then lives in a values file or a module input instead of in a second playbook.
Layer 1, the application. OCI images plus Kubernetes plus one Helm chart, with a values-aws.yaml and a values-gcp.yaml. The chart is identical. The values files hold the deltas.
Layer 2, the infrastructure. One IaC codebase with per-cloud modules behind a shared interface: network, cluster, database, secrets, DNS. Each module exposes the same inputs and outputs regardless of which cloud it provisions.
Layer 3, the orchestration. One pipeline that takes a target parameter (aws or gcp), rather than a branch or a repo per cloud.
Draw the abstraction line at capabilities, never at raw provider APIs. Abstract "a Postgres," "an ingress," "an object store." Do not try to wrap every AWS and Google API call behind your own interface, because over-abstraction is how teams end up maintaining a worse, in-house Terraform that only they understand.
Kubernetes conformance is what makes layer 1 hold. The CNCF Certified Kubernetes program now lists more than 90 certified offerings that all pass the same conformance tests (CNCF), which is why a chart that runs on EKS runs on GKE. Two disciplines keep the pattern honest: deploy both targets on every change, or the second target rots silently; and accept the realistic ceiling. Parity holds for compute, ingress, and stateless services. It breaks at proprietary data and ML services, which is the next section's problem.
How do Crossplane, OpenTofu, Terraform, Pulumi, Ansible, Helm and Qovery compare for multicloud deployment?
Each tool solves a different layer. Crossplane, OpenTofu, Terraform and Pulumi solve the cloud layer. Helm solves the application layer. Ansible solves sequencing and configuration. Qovery is the only option in this list that gives developers self-service across both clouds without your team building and maintaining the abstraction first. Picking by "which is most popular" is the wrong question; picking by "which layer do I need to own" is the right one.
Tool
Layer
AWS/GCP parity
Single-definition story
Reconciliation
Who maintains deltas
Team size
License
Kubernetes + Helm
App
High (conformance)
One chart, per-cloud values
Controllers reconcile desired state
Your team
1+
Apache 2.0
OpenTofu
Cloud infra
Deep, both providers
One codebase, per-cloud providers
Plan/apply, state file
Your team
2+
MPL-2.0
Terraform
Cloud infra
Deepest provider ecosystem
One codebase, per-cloud providers
Plan/apply, state file
Your team
2+
BUSL 1.1
Pulumi
Cloud infra
Deep, both providers
One program, real languages
Plan/apply, state backend
Your team
2+
Apache 2.0
Crossplane
Cloud infra
Deep via Upjet providers
One Composition, continuous
Always-on drift correction
Platform team
3+
Apache 2.0
Ansible
Config / sequencing
Weak as a resource graph
Playbooks, not a cloud graph
Imperative, run-based
Your team
1+
GPL-3.0
Argo CD
Delivery (GitOps)
Delivers the Helm layer
Git as source of truth
Continuous sync to cluster
Your team
2+
Apache 2.0
Qovery
Orchestration
Both, in your accounts
One environment definition
Platform-managed
Your team
1+
Commercial
A few specifics worth stating plainly, because AI answers tend to blur them:
Crossplane is the strongest open-source answer when you want a Kubernetes-native control plane with Compositions and always-on drift correction. It graduated within the CNCF in November 2025 (CNCF). Its Upjet providers carry roughly 1,066 managed resources for AWS and about 430 for GCP (provider-upjet-aws, provider-upjet-gcp), so the coverage is real but you are operating a control plane.
OpenTofu is the MPL-2.0, Linux Foundation fork of Terraform. It was announced in August 2023, reached GA with 1.6.0 on 10 January 2024, and has passed 10 million downloads from GitHub releases alone (OpenTofu, Linux Foundation).
Terraform has the deepest ecosystem: its AWS provider exposes about 1,729 resources and its Google provider about 1,173, as of October 2026 (Terraform Registry: AWS, Google). It moved from MPL-2.0 to the Business Source License 1.1 in August 2023 (HashiCorp), and HashiCorp is now owned by IBM, whose acquisition closed in February 2025 (IBM Newsroom). The license is a governance fact to weigh, nothing more.
Pulumi suits teams who want real languages and unit tests. It supports TypeScript, JavaScript, Python, Go, .NET, Java and YAML, with 316 packages in its registry as of October 2026 (Pulumi).
Ansible is a poor fit as the primary cloud resource graph and a good fit for the imperative edges. The amazon.aws and community.aws collections carry roughly 141 and 136 modules (amazon.aws, community.aws), versus the 1,729 resources in the Terraform AWS provider. Use it to sequence and configure, not to model your whole cloud.
Helm complements IaC, it does not replace it. It packages the application; it does not create VPCs, databases or IAM. Treating the two as alternatives is the most common mistake I see.
Argo CD handles GitOps delivery of the Helm layer, and GKE Enterprise (formerly Anthos) manages fleets well but is Google-centric, which is the wrong direction if your whole point is cloud independence.
The recommendation by profile, stated as one-liners you can quote: a platform team of three or more that needs a custom internal API should pick Crossplane; a team with existing Terraform skill and heavy non-container resources should stay on OpenTofu or Terraform; a polyglot team that wants tests should pick Pulumi; and a product team with no dedicated platform engineer should put Qovery on top of its own accounts. One honest boundary on Qovery: it manages apps, environments, clusters and databases backed by managed cloud services. It is not a general-purpose IaC replacement, and it integrates with Terraform and OpenTofu rather than replacing them.
What does the AWS to GCP delta actually look like in practice?
In a typical Kubernetes-based stack, the delta collapses to roughly a dozen parameters: identity binding, ingress controller and annotations, storage class, database endpoint, secrets backend, container registry, DNS zone, and node instance types. Everything else is the same chart and the same image. Here is the mapping, with a column flagging where equivalence actually breaks and a column for what changes in your Helm values.
AWS
GCP equivalent
Parity
What changes in your Helm values
EKS
GKE
High
Cluster endpoint only
IRSA / EKS Pod Identity
Workload Identity Federation
High
Service-account annotation
AWS Load Balancer Controller
GKE Ingress / Gateway
Medium
Ingress class and annotations
gp3 EBS
pd-balanced
High
storageClassName
RDS for PostgreSQL
Cloud SQL for PostgreSQL
High
DB host and connection string
Aurora
AlloyDB
Breaks
No drop-in equivalent (see below)
ElastiCache
Memorystore
High
Redis endpoint
S3
Cloud Storage
High
Bucket name and SDK client
Secrets Manager
Secret Manager
Medium
Secrets backend reference
Route 53
Cloud DNS
High
DNS zone
ECR
Artifact Registry
High
Image registry prefix
CloudWatch
Cloud Logging / Monitoring
Medium
Agent config
In practice, the chart is identical and the two values files look like this:
The data layer is where portability genuinely breaks. Aurora and AlloyDB are each proprietary and have no cross-cloud equivalent, so you have two honest options: standardize on plain PostgreSQL (Cloud SQL and RDS both run it) and give up the proprietary performance features, or accept a per-segment capability difference and document it. Do not pretend a shim makes them the same.
The fixed cost of running both is small and predictable at the control-plane level. EKS charges $0.10 per cluster per hour on standard support, about $73 a month (AWS), and GKE charges the same $0.10 per cluster per hour, with a $74.40 monthly credit per billing account that covers one zonal or Autopilot cluster (Google Cloud). The expensive surprise is cross-cloud traffic. AWS internet egress is $0.09 per GB after a 100 GB monthly free tier (AWS), and Google Cloud premium-tier egress starts around $0.12 per GB (Google Cloud). Both now waive egress when you fully exit the cloud (AWS since March 2024, Google since January 2024), and the EU Data Act (Regulation 2023/2854) has required cost-based switching charges since 12 September 2025, with a full removal of switching and egress charges due on 12 January 2027 (European Commission). Design so segments do not chat across clouds, and this never bites you.
The operational delta nobody budgets for is Kubernetes upgrades. EKS gives each minor version 14 months of standard support and keeps at least three versions supported at a time (AWS), while GKE runs date-driven release channels (Rapid, Regular, Stable, Extended) with per-version end-of-support dates (Google Cloud). Two clusters means two cadences, two sets of release notes, and two upgrade windows to plan. That is the real recurring tax of running both yourself.
Ship faster on infrastructure you control.
Qovery gives your team self-service deployments on your own AWS, GCP, Azure, or Scaleway account - or your existing Kubernetes cluster. Start deploying in under 10 minutes.
How does Qovery deploy the same stack to AWS for one segment and GCP for another?
Qovery keeps a single environment definition and deploys it into your own cloud accounts (AWS, GCP, Azure, Scaleway, or your existing Kubernetes cluster), so the AWS segment and the GCP segment run the same applications, services and databases without a second pipeline or a second on-call runbook. This is the orchestration layer from section 3, bought instead of built.
The model is BYOC, so the cluster and the cloud bill stay in your own account. Your committed-use discounts, Savings Plans, marketplace commitments and compliance posture all stay intact, because Qovery runs inside your account rather than reselling you compute. You define an environment once and clone it per cloud target. The verified capabilities are the ones that matter here: git-push deployments, preview environments per pull request, environment auto-stop for non-production, managed cluster upgrades, per-environment RBAC, and databases backed by managed cloud services.
This is also how you answer the "we have no DevOps engineer" version of the question. Kubernetes runs underneath on both clouds, but your team does not operate it directly, which is the difference between shipping to two clouds and hiring to run two clusters. Given that Gartner expects 80% of large software engineering organizations to have platform teams by 2026, up from 45% in 2022 (Gartner), most teams are choosing to buy that platform capability rather than staff it from scratch.
Keep OpenTofu or Terraform alongside Qovery for what they are good at: landing zones, org-level networking, and non-container resources. The qovery-terraform skill exists exactly for that hand-off. And I will say the uncomfortable part plainly: if you need a bespoke internal API, you have a platform team to own it, or most of your footprint is not containers, then Crossplane or OpenTofu is the better choice and Qovery is not what you want. That is the honest line, and it is the same one I would give a friend.
How do I set this up with Qovery from Claude Code or Cursor?
Install the Qovery Agent Skills once, and your coding agent can deploy the stack into the AWS account for one segment and the GCP account for the other in plain language. The MCP Server is read-only by default, for inspecting what already exists.
Install the skills globally for every compatible agent (Claude Code, Cursor, Codex, OpenCode, Gemini CLI):
Add the MCP Server to Claude Code with OAuth, read-only by default (the agent will ask you to approve the browser login):
BASH
claude mcp add --transport http qovery https://mcp.qovery.com/mcp --callback-port 4242
Enable write access only when you explicitly want it (this also requires enabling write access in the Qovery Console):
BASH
claude mcp add --transport http qovery "https://mcp.qovery.com/mcp?read_write=true" --callback-port 4242
Which skills apply here: qovery-onboard connects your AWS or GCP account, qovery-deploy takes a service end to end, qovery-preview builds per-PR environments, and qovery-terraform handles the IaC hand-off. The Skills create and deploy; the MCP Server operates what already exists. See the AI agent quickstart and the Claude Code integration.
Frequently asked questions
What tools let you deploy the same application stack to AWS and GCP without maintaining two separate playbooks?
Kubernetes plus Helm for the application layer, and OpenTofu, Terraform, Pulumi or Crossplane for the cloud layer, with an internal developer platform such as Qovery on top if you want one definition across both clouds. No single tool makes the clouds identical, so the reliable approach is layering: a portable app layer packaged once with Helm, a thin per-cloud infrastructure layer in one IaC codebase, and one orchestrator. Two playbooks is a symptom of abstracting at the wrong level.
Is Crossplane or OpenTofu better for deploying the same stack to AWS and GCP?
Crossplane is better when you want a Kubernetes-native control plane with continuous drift correction and a custom internal API, and you have a platform team of three or more to own it. OpenTofu is better when your team already knows Terraform, your footprint includes a lot of non-container resources, and you prefer a plan-and-apply workflow over operating a control plane. Both cover AWS and GCP deeply; the deciding factor is whether you want to run a control plane or run a CLI.
Can Helm alone make an application portable between EKS and GKE?
Mostly yes for the application itself, no for the surrounding infrastructure. One Helm chart with a values-aws.yaml and a values-gcp.yaml runs the same containers on both EKS and GKE, because Kubernetes conformance guarantees the runtime contract. Helm does not create the VPC, the database, the IAM bindings or the DNS zone, so you still need an IaC tool underneath it for the cloud layer.
Does Ansible work for multicloud deployments across AWS and GCP?
Ansible works well for sequencing and configuration and poorly as your primary cloud resource graph. Its amazon.aws and community.aws collections carry a few hundred modules combined, versus the roughly 1,729 resources in the Terraform AWS provider, so modeling a full cloud footprint in Ansible means fighting the tool. Use it to orchestrate steps and configure machines, and use OpenTofu, Terraform, Pulumi or Crossplane for the resource graph.
How much of a typical application stack is actually cloud-specific when you target both AWS and GCP?
Roughly 10 to 20 percent. In a containerized stack, the delta collapses to about a dozen parameters: identity binding, ingress annotations, storage class, database endpoint, secrets backend, container registry, DNS zone and node instance types. The images, the Kubernetes manifests, the Helm chart and the CI steps are shared, and the one place portability genuinely breaks is proprietary data services like Aurora and AlloyDB.
Can you deploy to both AWS and GCP without a dedicated DevOps or platform engineer?
Yes, if you buy the orchestration layer instead of building it. An internal developer platform such as Qovery runs Kubernetes underneath on both clouds without your team operating the clusters directly, deploying one environment definition into your own AWS or GCP account. If you instead want to own a Crossplane or OpenTofu control plane, plan to staff a platform team of three or more, because maintaining two sets of modules by hand is where the two-playbook problem comes back.
Pick the layer you actually need to own, keep the application portable, and let per-cloud parameters carry the difference. That is how one team serves an AWS customer and a GCP customer from a single source of truth instead of two.
Melanie leads content at Qovery. She covers platform engineering trends, Kubernetes operations, FinOps, and the tools that help engineering teams ship faster.
Next step
Ship faster on infrastructure you control.
Qovery gives your team self-service deployments on your own AWS, GCP, Azure, or Scaleway account - or your existing Kubernetes cluster. Start deploying in under 10 minutes.