AWS Builder Center
Multi-Cloud DR Infrastructure in Minutes: A Kiro Walkthrough for DevOps Engineers

Multi-Cloud DR Infrastructure in Minutes: A Kiro Walkthrough for DevOps Engineers

4 prompts. 6 minutes. 3 cloud providers. 16 files. I went from zero to multi-cloud Kubernetes infrastructure in a single Kiro session — and it was absolutely wild how well it carried context forward!

I was spending too much time writing Terraform modules across AWS, Azure, and GCP. With more organizations adopting multi-cloud strategies for DR, compliance, and vendor diversification, I found myself — like many SRE and DevOps engineers — expected to maintain consistent infrastructure across all three providers, each with its own networking model, identity system, and Kubernetes flavor. It was time-consuming, error-prone, and I wasn't an expert in all three simultaneously.
So I tried Kiro  — an agentic IDE that goes beyond code completion. It creates files, runs commands, recovers from errors, and maintains context across multi-step conversations. I wanted to see if it could generate production-grade, provider-idiomatic Terraform for EKS, AKS, and GKE in a single session.
4 prompts. 6 minutes. Here's what happened.

Step 1: The AWS Prompt

I opened Kiro and typed a single, detailed prompt:
Create a Terraform module for an AWS VPC with public and private subnets across three availability zones, designed to host an EKS cluster.1. Include an internet gateway, NAT gateway with a variable to toggle between single or one-per-AZ, proper route tables, and VPC flow logs to CloudWatch with a configurable retention period defaulting to 14 days.
2. Add an EKS cluster with a managed node group in the private subnets, including the required IAM roles and security groups. Make it reusable with variables for CIDR blocks, environment naming, node instance type, and desired node count.
3. Output the VPC ID, subnet IDs, NAT gateway IDs, EKS cluster endpoint, and cluster certificate authority.
No special syntax. No structured template. Just how I'd describe the requirement to a colleague.

What Kiro Did

Kiro hit a minor file access error initially, but recovered on its own — it ran pwd to understand the workspace, then created all the files successfully. This self-recovery is one of the things that separates an agentic IDE from a simple code generator.
Kiro recovering from the error and creating all Terraform files
Kiro recovering from the error and creating all Terraform files
Within 1 minute 50 seconds, Kiro produced a complete module:
1
2
3
4
5
6
terraform-eks-vpc/
├── main.tf # VPC, subnets, IGW, NAT, route tables, flow logs
├── eks.tf # EKS cluster, node group, IAM roles, security groups
├── variables.tf # All configurable inputs
├── outputs.tf # VPC ID, subnet IDs, NAT IDs, EKS endpoint & CA
└── terraform.tfvars.example # Example variable values
Final output showing file structure and key design decisions
Final output showing file structure and key design decisions

Key Design Decisions Kiro Made

  • NAT gateway toggle — single_nat_gateway = true uses one NAT (cost-saving for dev), false creates one per AZ (HA for prod). Private route tables wired accordingly.
  • EKS-ready subnet tagging — Public subnets tagged for external ELBs, private subnets tagged for internal ELBs, both with the cluster name for auto-discovery.
  • Security groups — Separate SGs for the cluster control plane and worker nodes with least-privilege rules allowing node↔control-plane communication.
  • IAM — Cluster role gets AmazonEKSClusterPolicy + AmazonEKSVPCResourceController. Node role gets AmazonEKSWorkerNodePolicy, AmazonEKS_CNI_Policy, and AmazonEC2ContainerRegistryReadOnly.
  • Flow logs — Sent to CloudWatch with a dedicated IAM role; retention defaults to 14 days via flow_log_retention_days.
Every one of these is a decision I'd have made manually — but Kiro made them all in under 2 minutes.

The Generated Code

Here's what the actual eks.tf looks like — IAM roles with proper trust policies, policy attachments, and security group rules scoped to cluster↔node communication:
AWS eks.tf showing IAM roles, policy attachments, and security group rules
AWS eks.tf showing IAM roles, policy attachments, and security group rules
Notice: proper assume_role_policy with sts:AssumeRole for the EKS service principal, separate security group rules for egress and ingress (port 443 for API server communication), and local.common_tags applied consistently. This isn't boilerplate — it's production-ready IAM and networking.

Step 2: Adding Azure — One Sentence

Impressed with the AWS output, I simply said:
It looks good, lets create a folder for the azure cloud provider
That's it. No detailed prompt. Kiro understood the context from the AWS module and created an equivalent Azure module in an azure/ subdirectory.
Kiro creating the Azure module with 5 files in the azure/ directory]
Kiro creating the Azure module with 5 files in the azure/ directory]

Azure-Specific Intelligence

Kiro didn't just copy-paste the AWS module with different resource names. It provided a cross-provider mapping table and made Azure-specific architectural choices:
Azure response showing the AWS-to-Azure comparison table and design choices
Azure response showing the AWS-to-Azure comparison table and design choices
AWSAzure
VPCVirtual Network
Internet GatewayBuilt-in (route to Internet)
NAT GatewayAzure NAT Gateway
CloudWatch Flow LogsNSG Flow Logs → Log Analytics
EKSAKS
IAM RolesSystem-Assigned Managed Identity
Security GroupsNetwork Security Groups
Azure-specific choices:
  • Azure CNI networking so pods get VNet IPs directly — required for proper subnet integration
  • Calico network policy for pod-level traffic control
  • System-assigned managed identity instead of service principals — simpler lifecycle management
  • NSG flow logs with Traffic Analytics enabled, routed to a Log Analytics workspace
  • NAT gateway toggle works the same way — single vs. one-per-zone
Elapsed time: 1 minute 5 seconds.

The Generated Code

Here's the aks.tf — AKS cluster with Azure CNI, Calico network policy, system-assigned managed identity, and a Network Contributor role assignment for VNet integration:
Azure aks.tf showing AKS cluster configuration with CNI, Calico, and managed identity
Azure aks.tf showing AKS cluster configuration with CNI, Calico, and managed identity
Kiro correctly set network_plugin = "azure" for CNI, network_policy = "calico", and added the azurerm_role_assignment for Network Contributor — a detail many engineers miss that causes AKS networking failures.

Step 3: Adding GCP — One Sentence

At this point I was curious how far the conversational context would carry. I typed:
Wow, can you also do the same for GCP
Kiro creating the GCP module with gke.tf and all supporting files
Kiro creating the GCP module with gke.tf and all supporting files
Kiro created a gcp/ subdirectory with the same file structure and another comparison table:
GCP response with cross-provider comparison and GCP-specific design choices
GCP response with cross-provider comparison and GCP-specific design choices
AWS / AzureGCP
VPC / VNetVPC Network (custom mode)
Internet GatewayImplicit (public subnets route to internet)
NAT GatewayCloud NAT + Cloud Router
Flow Logs → CloudWatch / Log AnalyticsSubnet flow logs → Cloud Logging bucket
EKS / AKSGKE
IAM Roles / Managed IdentityService Account + IAM bindings
Security Groups / NSGsFirewall rules
GCP-specific choices:
  • VPC-native cluster with secondary IP ranges for pods and services — required for private GKE clusters
  • Private cluster — nodes have no public IPs, egress goes through Cloud NAT
  • Workload Identity enabled for secure pod-to-GCP-service authentication
  • Calico network policy for pod-level traffic control
  • Dedicated service account for nodes with least-privilege roles (logging, monitoring, artifact registry)
  • Cloud NAT toggle — single Cloud Router/NAT vs. one per zone, same pattern as AWS and Azure
  • Flow logs enabled at the subnet level with a custom logging bucket and configurable retention
Elapsed time: 1 minute 14 seconds.

The Generated Code

Here's gke.tf — a dedicated service account with least-privilege IAM bindings, private cluster configuration with VPC-native networking, and secondary IP ranges for pods and services:
GCP gke.tf showing service account, IAM bindings, private cluster config, and VPC-native networking
GCP gke.tf showing service account, IAM bindings, private cluster config, and VPC-native networking
Kiro created individual IAM bindings for roles/logging.logWriter, roles/monitoring.metricWriter, roles/monitoring.viewer, and roles/artifactregistry.reader — exactly the least-privilege set a GKE node pool needs. The private_cluster_config block with enable_private_nodes = true and master_ipv4_cidr_block is correct GKE private cluster setup.

Step 4: Final Restructuring and Documentation

I wanted a clean project structure with documentation, so I asked:
Could you move the AWS to an aws directory and create a readme to show what this code base will achieve and highlight the key things for each cloud provider
Kiro moving AWS files to aws/ directory and creating README.md
Kiro moving AWS files to aws/ directory and creating README.md
Kiro moved the root-level AWS files into an aws/ directory, deleted the originals, and generated a comprehensive README:
Final project structure with aws/, azure/, gcp/ directories and README.md
Final project structure with aws/, azure/, gcp/ directories and README.md

The Final Structure

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
Terraform/
├── README.md
├── aws/ # Amazon Web Services (EKS)
│ ├── main.tf # VPC, subnets, IGW, NAT, route tables, flow logs
│ ├── eks.tf # EKS cluster, managed node group, IAM, security groups
│ ├── variables.tf
│ ├── outputs.tf
│ └── terraform.tfvars.example
├── azure/ # Microsoft Azure (AKS)
│ ├── main.tf # VNet, subnets, NAT gateway, NSGs, flow logs
│ ├── aks.tf # AKS cluster with default node pool
│ ├── variables.tf
│ ├── outputs.tf
│ └── terraform.tfvars.example
└── gcp/ # Google Cloud Platform (GKE)
├── main.tf # GCP VPC, subnets, Cloud NAT, firewall rules, flow logs
├── gke.tf # GKE cluster + node pool
├── variables.tf
├── outputs.tf
└── terraform.tfvars.example

The Generated README

Kiro generated a README with full documentation — not boilerplate, but genuinely useful content:
README.md showing the full documentation with common variables table and project structure
README.md showing the full documentation with common variables table and project structure
The README includes:
  • What This Deploys — bullet points covering all infrastructure components
  • Project Structure — annotated directory tree
  • Common Variables (All Providers) — table showing shared inputs (environment, single_nat_gateway, flow_log_retention_days, kubernetes_version, node_desired_count, node_min_count, node_max_count)
  • Outputs (All Providers) — VPC/VNet ID, subnet IDs, NAT gateway IDs, cluster endpoint, cluster CA certificate
  • Provider-specific highlights and variables
  • Cross-provider comparison table
  • Usage instructions per provider
  • Cost optimization tips
Elapsed time for this step: 1 minute 51 seconds.

The Numbers

AWSAzureGCPRestructure
Prompt complexityDetailed (3 points)One sentenceOne sentenceOne sentence
Files created55511 changes (move + README)
Time1m 50s1m 5s1m 14s1m 51s
Credits used1.331.031.151.75
Total: 4 prompts → 6 minutes → 3 cloud providers → 16 files → 1 comprehensive README.

Cost Comparison: What This Infrastructure Actually Costs

I asked Kiro to add a cost comparison to the README. It searched real pricing data from AWS, Azure, and GCP pricing pages, then generated a detailed breakdown:
Kiro generating the cost comparison by searching provider pricing pages and building the table
Kiro generating the cost comparison by searching provider pricing pages and building the table
Here's the baseline for the default configuration (2 nodes, single NAT, 24/7):
AWS (us-east-1)Azure (East US)GCP (us-central1)
Control plane$73/mo$0 (Free tier) / $73 (Standard)$73 (or $0 with free tier)
Compute (2 nodes)$61/mo (t3.medium)$140/mo (Standard_D2s_v3)$98/mo (e2-standard-2)
NAT gateway$33/mo$33/mo$64/mo
Other (IPs, logs)~$5~$8~$5
Total~$172/mo~$181–$254/mo~$167–$240/mo
Cost optimization tips:
  • Set single_nat_gateway = true for non-production (saves 2× NAT cost)
  • Use smaller instances in dev (t3.small, Standard_B2s, e2-small)
  • Set node_min_count = 0 if workloads tolerate scale-from-zero
  • Reduce flow log retention to 7 days for dev environments
  • Reserved/committed-use pricing cuts compute costs 30–60%

What Kiro Got Right

Provider-specific idioms. Kiro didn't just swap resource names between providers. It understood that Azure uses managed identities instead of IAM roles, that GCP needs secondary IP ranges for GKE pods, and that Cloud NAT requires a Cloud Router. These are the details that trip up engineers working across clouds.
Consistent architecture across providers. All three modules share the same variable interface (environment, single_nat_gateway, node_desired_count) and output contract (VPC ID, subnet IDs, cluster endpoint). This makes it trivial to deploy the same workload across clouds.
Self-recovery. When Kiro hit a file access error on the first attempt, it diagnosed the issue, found the workspace path, and continued without me intervening. This is the difference between an agent and an autocomplete tool.
Conversational context. After the detailed AWS prompt, I only needed one sentence each for Azure and GCP. Kiro carried the architectural intent forward and adapted it per provider.
Documentation generation. The README wasn't an afterthought — it included variables tables, outputs, project structure, cross-provider comparison, and cost tips. That's documentation I'd normally write last (or never).

Challenges I Hit and How I Worked Around Them

It wasn't all smooth. Here's where Kiro stumbled and how I steered it back:
File access error on first attempt. Kiro initially couldn't write to the workspace — it threw an "Access denied" error. I didn't intervene; Kiro self-recovered by running pwd to locate the correct path and retried successfully. Lesson: make sure your workspace is set correctly before starting, or trust that Kiro's agentic recovery will sort it out.
No state backend or version constraints. Kiro didn't include remote state setup (S3, Azure Storage, GCS) or a separate versions.tf with pinned provider versions. These are arguably environment-specific decisions, but for production use I had to explicitly ask as a follow-up. If you need these upfront, include them in your initial prompt.
Context carry-forward dependency. The one-sentence prompts for Azure and GCP ("do the same for GCP") only worked because the AWS module was still in context. In a new session, I'd need to re-describe the full architecture. For long-running projects, I'd recommend using Kiro's steering files to persist architectural decisions across sessions.
The pattern I found: Kiro handles structural complexity well (resource wiring, IAM trust policies, cross-resource references) but needs explicit prompting for operational concerns (state management, version pinning, production hardening). Once I learned to add those as follow-up prompts, the workflow became predictable.

What I'd Still Adjust

  • State backend configuration — not included (intentionally, since it's environment-specific)
  • Terraform version constraints — I'd add a versions.tf per module
  • Module composition — for a real multi-cloud deployment, I'd extract shared variables into a root module
  • Security hardening — I'd review the security group rules and add tighter CIDR restrictions for production

What I'd Ask Kiro Next

If I were taking this to production, here's what I'd ask Kiro to add in follow-up prompts:
  1. Remote state backend — S3/DynamoDB for AWS, Azure Storage for Azure, GCS for GCP. Each with locking and encryption.
  2. Cluster add-ons — Ingress controller (ALB Controller / NGINX), cert-manager for TLS, external-dns for Route53/Cloud DNS integration.
  3. Monitoring and alerting — CloudWatch Container Insights, Azure Monitor, or GCP Cloud Monitoring with alerts for node pressure and pod failures.
  4. CI/CD pipeline for the Terraform itself — GitHub Actions workflow that runs terraform plan on PRs and terraform apply on merge to main, per environment.
  5. Network policies — Default-deny ingress with explicit allow rules per namespace, enforced via Calico across all three providers.
Each of these is a single conversational prompt away — and based on what I've seen, Kiro would carry the existing module context forward and wire everything correctly.

Where Kiro Fits in the IaC Workflow

After this exercise, here's my honest take:
Kiro is a force multiplier for infrastructure engineers who already understand the architecture. It generated correct, provider-idiomatic Terraform across three clouds in a single conversation. The cross-provider comparison tables alone saved me from looking up Azure and GCP equivalents.
The conversational flow is the killer feature. I didn't need three separate detailed prompts. One detailed prompt established the pattern, and Kiro extrapolated to other providers with minimal guidance. This is what makes it an agent rather than a code generator.
You still need to review everything. The generated code is a strong starting point — maybe 85-90% production-ready. But decisions about state backends, CIDR ranges, node sizing, and security boundaries still require human judgment.
For multi-cloud teams, this is transformative. Nobody is an expert in AWS, Azure, and GCP Terraform idioms simultaneously. Kiro bridges that gap in minutes instead of hours of documentation reading.
The gap between "I know what I need" and "I have working code" used to be 2-3 hours for a multi-cloud setup like this. Now it's a 6-minute conversation.
Get started with Kiro at kiro.dev .

Try It Yourself

Want to reproduce this? Here are the exact prompts I used in Kiro :
Prompt 1 (AWS):
Create a Terraform module for an AWS VPC with public and private subnets across three availability zones, designed to host an EKS cluster.1. Include an internet gateway, NAT gateway with a variable to toggle between single or one-per-AZ, proper route tables, and VPC flow logs to CloudWatch with a configurable retention period defaulting to 14 days.
2. Add an EKS cluster with a managed node group in the private subnets, including the required IAM roles and security groups. Make it reusable with variables for CIDR blocks, environment naming, node instance type, and desired node count.
3. Output the VPC ID, subnet IDs, NAT gateway IDs, EKS cluster endpoint, and cluster certificate authority.
Prompt 2 (Azure):
It looks good, lets create a folder for the azure cloud provider
Prompt 3 (GCP):
Wow, can you also do the same for GCP
Prompt 4 (Restructure + README):
Could you move the AWS to an aws directory and create a readme to show what this code base will achieve and highlight the key things for each cloud provider
That's it — four prompts, six minutes, three cloud providers. Try it and see what Kiro generates for your infrastructure patterns.

Source Code

The complete generated Terraform modules are available on GitHub:
Clone it, inspect the code, and deploy to your own accounts. PRs welcome if you extend it with additional providers or cluster add-ons.
Any opinions in this article are those of the individual author and may not reflect the opinions of AWS.
Enjoyed reading this content? Let the author know!

Your likes, comments, shares, and saves help creators reach more builders.

Loading recommendations

Loading article