Multi-Region Kubernetes Clusters
A step-by-step guide to running two Kubernetes clusters in two regions behind a single environment. You'll provision a cluster in each region, attach both to one environment, and let SeaGit route each visitor to the nearest region with latency-based DNS — for high availability and lower global latency.
What You'll Build
Region A — us-east-1:
- ✓ Dedicated VPC (10.0.0.0/16)
- ✓ EKS cluster (2 nodes)
- ✓ ALB + cert-manager + External DNS
Region B — eu-west-1:
- ✓ Dedicated VPC (10.1.0.0/16)
- ✓ EKS cluster (2 nodes)
- ✓ ALB + cert-manager + External DNS
One environment routing to both clusters (latency-based)
Estimated time: ~45 minutes (most of it EKS provisioning, which runs in parallel across both regions)
Prerequisites
- A connected cloud provider — see Providers. The two clusters can share one provider or use two different accounts.
- A domain managed by SeaGit for automatic DNS and TLS — see DNS & Domains.
- A completed single-region setup helps — if this is your first cluster, start with the Getting Started guide first.
- A paid plan. This guide needs two clusters, and the Free plan allows one — see Pricing.
Before you start:
Routing needs the two clusters to be attached to the same environment. Failover needs two clusters in two different regions, so the Failover option only appears once the environment has clusters in at least two regions.
Step 1: Create a VPC in Region A
A network (VPC) is region-scoped, so each region needs its own. Go to Networks → Create Network.
- Name:
vpc-us-east-1 - Region:
us-east-1 - CIDR Block:
10.0.0.0/16 - Availability Zones: 2 (for high availability)
- Public + Private Subnets: Yes
Use a distinct CIDR per region so the two VPCs never overlap. See Networks for details.
✓ Step complete
Region A VPC ready.
Step 2: Provision the Cluster in Region A
Go to Clusters → Create Cluster and place it in the Region A VPC.
- Name:
cluster-us-east-1 - Network:
vpc-us-east-1 - Kubernetes Version: latest stable
- Node Group:
t3.medium, min 2 / max 5
Install these add-ons (required for managed DNS + TLS):
- ☑ ALB Controller
- ☑ Cert-Manager — per-cluster TLS certificates
- ☑ External DNS — writes the region-aware DNS records
- ☑ Metrics Server
EKS provisioning takes ~15-20 minutes. Start Step 3 while it runs.
✓ Step complete
Region A cluster provisioning.
Step 3: Create a VPC in Region B
Repeat Step 1 for your second region. Back in Networks → Create Network:
- Name:
vpc-eu-west-1 - Region:
eu-west-1 - CIDR Block:
10.1.0.0/16(non-overlapping) - Availability Zones: 2
✓ Step complete
Region B VPC ready.
Step 4: Provision the Cluster in Region B
Repeat Step 2, placing the cluster in the Region B VPC and selecting the same add-ons so both regions behave identically.
- Name:
cluster-eu-west-1 - Network:
vpc-eu-west-1 - Add-ons: ALB, Cert-Manager, External DNS, Metrics Server
Wait until both clusters show Ready before continuing.
✓ Step complete
Both regional clusters are Ready.
Step 5: Create an Environment and Attach Both Clusters
One environment spans both regions. Go to Environments → Create Environment.
5.1 Configure the Environment
- Name:
production-global - Root Domain:
yourdomain.com - Ingress Class:
alb - TLS: Enabled (auto-issue certificates)
5.2 Attach Both Clusters
In Attach Clusters, select both cluster-us-east-1 and cluster-eu-west-1. This is what makes the environment multi-region: every deployment to it rolls out to both clusters. See Environments.
✓ Step complete
One environment now spans both regional clusters.
Step 6: Set the Routing Policy
The routing policy decides how visitors are steered across the two regions. Under the environment's DNS / Routing settings, choose one of the options below. The diagrams and record tables in the next section show exactly what each one creates in Route 53.
- Latency (recommended for two regions) — each visitor is answered with the region that has the lowest latency for them. Needs the clusters to be in different regions; if two clusters share a region, SeaGit uses Weighted instead.
- Failover — one primary region serves traffic; the other is a standby that answers only while the primary has no healthy targets. Needs exactly two clusters in two regions.
- Simple — one record pointing at one cluster. When the environment has two or more clusters, SeaGit does not use Simple and applies Latency (or Weighted) instead.
How it works: each cluster's External DNS add-on publishes its own record for that region, and the environment-level record for the hostname points at those cluster records. cert-manager issues a valid certificate in each region. So app.yourdomain.com resolves to the region the policy picks.
✓ Step complete
Routing policy set. Traffic now follows the policy you chose.
How the Route 53 Records Look for Each Policy
All examples use example.com and placeholder load balancer names. The naming follows what SeaGit writes:
- Deployment hostname:
<deployment>.<domain>, for exampleapp.example.com. This is the name visitors use. - Cluster record (leaf):
<deployment>-<cluster code>.<domain>, for exampleapp-use1.example.com. One per attached cluster. It is an alias to that cluster's load balancer.
The request path
Whatever the policy, a request follows the same path. The policy only chooses which cluster record Route 53 returns.
Simple
One record, no routing set. It can only point at one cluster. Use it for a single-cluster environment. A multi-cluster deployment does not keep Simple: SeaGit replaces it with Latency (or Weighted).
| Record name | Type | Routing policy | Differentiator (set ID) | Alias target / value | Weight / failover role / region |
|---|---|---|---|---|---|
| app.example.com | A (alias) | Simple | — | app-use1.example.com | — |
Latency
The hostname gets one latency record per cluster. Each record points at that cluster's record and has a set ID named after its region (for example us-east-1-latency). Route 53 returns the record with the lowest latency for the visitor. Latency needs each cluster in a different region, because the set ID is per region.
| Record name | Type | Routing policy | Differentiator (set ID) | Alias target / value | Weight / failover role / region |
|---|---|---|---|---|---|
| app.example.com | A (alias) | Latency | us-east-1-latency | app-use1.example.com | Region: us-east-1 |
| app.example.com | A (alias) | Latency | eu-west-1-latency | app-euw1.example.com | Region: eu-west-1 |
Failover
Two records, one marked PRIMARY and one SECONDARY. The primary is the cluster in the region you set as Primary failover region. If that region is not one of the attached regions, SeaGit uses the first cluster instead. Route 53 switches to SECONDARY when the PRIMARY load balancer has no healthy targets. SeaGit does not create a health check resource for this.
| Record name | Type | Routing policy | Differentiator (set ID) | Alias target / value | Weight / failover role / region |
|---|---|---|---|---|---|
| app.example.com | A (alias) | Failover | primary | app-use1.example.com | Role: PRIMARY (us-east-1) |
| app.example.com | A (alias) | Failover | secondary | app-euw1.example.com | Role: SECONDARY (eu-west-1) |
Weighted (chosen automatically)
Weighted is not an option in the settings. SeaGit uses it when two or more clusters attached to the environment are in the same region, because latency records cannot share a region. The hostname gets one weighted record per cluster, all with the same weight, so Route 53 answers about evenly across them.
| Record name | Type | Routing policy | Differentiator (set ID) | Alias target / value | Weight / failover role / region |
|---|---|---|---|---|---|
| app.example.com | A (alias) | Weighted | app-use1a.example.com.-weighted | app-use1a.example.com | Weight: 100 |
| app.example.com | A (alias) | Weighted | app-use1b.example.com.-weighted | app-use1b.example.com | Weight: 100 |
Cluster records and ownership TXT
Each cluster record is written by that cluster's External DNS. External DNS also writes a TXT record next to it, which says which owner manages the name. If the load balancer is not ready when SeaGit deploys, SeaGit can write a temporary placeholder address (192.0.2.1) plus the owner TXT, so the alias chain resolves. External DNS then replaces the placeholder with the real load balancer.
| Record name | Type | Routing policy | Differentiator (set ID) | Alias target / value | Weight / failover role / region |
|---|---|---|---|---|---|
| app-use1.example.com | A (alias) | Simple | — | k8s-app-appuse1-0a1b2c3d4e-1234.us-east-1.elb.amazonaws.com | Written by External DNS |
| app-use1.example.com | TXT | — | — | "heritage=external-dns,external-dns/owner=use1.edns.aws,external-dns/resource=ingress/app/app" | Ownership record |
| app-euw1.example.com | A (alias) | Simple | — | k8s-app-appeuw1-9f8e7d6c5b-5678.eu-west-1.elb.amazonaws.com | Written by External DNS |
| Record name | Type | Routing policy | Differentiator (set ID) | Alias target / value | Weight / failover role / region |
|---|---|---|---|---|---|
| app-use1.example.com | A | Simple | — | 192.0.2.1 | Placeholder until External DNS adopts it |
Which Policy Should I Choose?
| Policy | When to use it | Clusters | Regions | Failover behaviour |
|---|---|---|---|---|
| Simple | One cluster only | 1 | Any | None. Only one target. |
| Latency | Active-active, lowest latency for visitors | 2 or more | Different region per cluster | Records whose load balancer has no healthy targets are skipped |
| Failover | One primary region, one standby | Exactly 2 | Two different regions | Standby answers while the primary load balancer has no healthy targets |
| Weighted (automatic) | Two or more clusters in the same region | 2 or more | Usually the same region | None by weight. Equal share across clusters. |
- Failover speed depends on DNS caching. SeaGit does not create a Route 53 health check for failover, and the records have no TTL set by SeaGit. How quickly visitors move to the standby depends on how long their resolvers keep the previous answer.
- Not set yet? If no routing policy is saved, the stored default is Simple. With several clusters, SeaGit then applies Latency or Weighted as described above.
- Failover needs a primary region. The form requires one when you choose Failover.
Step 7: Verify DNS & TLS
Confirm both regions answer for your hostname over HTTPS:
# Resolve the app hostname (should return a regional endpoint)
dig +short app.yourdomain.com
# Verify HTTPS + a valid certificate in each region
curl -sSI https://app.yourdomain.com | head -n 1If a region doesn't resolve yet, DNS propagation can take a few minutes. See Certificates & TLS and Troubleshooting if a certificate stays pending.
✓ Step complete
Both regions resolve and serve valid TLS.
Next: Deploy Your Application to This Environment
Your multi-region environment is ready. From here you deploy exactly like a single-region setup — nothing about the application changes. Create an application instance that targets the production-global environment and deploy it normally. Each deployment automatically rolls out to both attached clusters, and the environment's routing policy sends every visitor to the nearest healthy region.
👉 Follow the standard Deployments guide to create and manage instances and releases against this environment. For configuring the application template itself, see Applications.
Frequently Asked Questions
Do I need a separate network for each region?
Yes. A SeaGit network (VPC) is region-scoped, so a two-region setup needs one VPC per region. You create a VPC in each region first, then provision one EKS cluster into each VPC.
Which routing policy should I use for multi-region clusters?
Use the Latency-based policy so each visitor is routed to the region closest to them for the lowest response time. Add a Failover policy when you want one region to act as a standby that only receives traffic if the primary region becomes unhealthy.
How does SeaGit route traffic across two regions?
When both clusters are attached to one environment and a routing policy is set, SeaGit programs region-aware DNS records (via External DNS on each cluster) and issues TLS certificates per cluster. Requests resolve to the nearest healthy region automatically — you deploy once and both regions serve the same application.
Can the two clusters live in different cloud accounts?
Yes. Each cluster can use its own provider, so the two regions can sit in different AWS accounts. SeaGit still manages cross-region DNS and per-cluster certificates from the single environment.
Can I choose weighted routing?
Not directly. Weighted is not offered as a policy in the environment settings. SeaGit uses weighted records automatically when two or more clusters attached to the environment are in the same AWS region, because latency routing needs a distinct region per record.
What happens if I pick Failover with three clusters?
Failover is only applied when the deployment resolves to exactly two cluster records. With three or more, SeaGit falls back to Latency routing (or Weighted when two clusters share a region) and logs that it did so.
Does Failover use a Route 53 health check?
No. SeaGit does not create a Route 53 health check resource. The PRIMARY and SECONDARY records are alias records with target health evaluation on, so Route 53 switches to SECONDARY when the PRIMARY load balancer has no healthy targets.