Containers
ARC zonal shift support for EKS Auto Mode and Karpenter
When an Availability Zone (AZ) experiences a failure, workloads running across multiple AZs need a fast, automated way to shift traffic and capacity away from the impaired zone. The AWS provider for Karpenter recently added support for Zonal Shift and Zonal Autoshift, features of Amazon Application Recovery Controller (ARC) designed to help you recover from these types of failures. In this post, we walk through how zonal shift integrates with Amazon Elastic Kubernetes Service (Amazon EKS) and what happens when a shift is triggered. We also show how to enable it on both self-managed Karpenter and EKS Auto Mode (EKS Auto) clusters.
When Zonal Shift integration is enabled, it performs the following functions automatically: first, it cordons the worker nodes running in the affected zone, preventing new pods from being scheduled there. Second, it deregisters the IP addresses of pods running on worker nodes in the impaired zone from application and network load balancers. It also removes the endpoints of those pods from their corresponding endpoint slices. This effectively prevents those pods from receiving network traffic. Third, it temporarily prevents Managed Node Groups (MNG), EKS Auto, and self-managed Karpenter from provisioning new capacity in the impaired zone. When using EKS Auto or self-managing Karpenter, voluntary disruptions (consolidation, drift, empty, and underutilized) are also temporarily suspended in the affected zone.
How it works
Like MNGs, Karpenter avoids provisioning capacity in impaired zones. It detects the type of shift (manual or auto) and which zones are currently affected by polling the ARC GetManagedResources API every 30 seconds. When service to the zones has been restored or when a zonal shift has expired, Karpenter resumes provisioning capacity in all the node pool’s configured zones. If your node pools don’t specify the topology.kubernetes.io/zone key, but subnet auto-discovery is enabled, Karpenter continues provisioning capacity in those subnets.
During zonal impairments, nodes in the affected zone are tainted and unable to have pods scheduled onto them. Because Karpenter also cannot provision in the impaired AZ, it doesn’t disrupt nodes in the affected zone until the zonal shift expires or services in that zone are restored. If a disruption requires replacement capacity that depends on the impaired zone, validation fails and the disruption does not proceed.
Best practices
There are several things you can do to improve the reliability of your applications.
Distribute pods across Availability Zones. Spread pods across worker nodes in at least two Availability Zones using topology spread constraints or node affinity. When using either option, allow the scheduler to ignore constraints if they cannot be met. Otherwise, pods never get scheduled during an outage. For node affinity, use preferredDuringSchedulingIgnoredDuringExecution instead of requiredDuringSchedulingIgnoredDuringExecution. For topology spread, set whenUnsatisfiable to ScheduleAnyway instead of DoNotSchedule, or increase maxSkew to allow more variance between the number of pods in targeted zones.
Avoid singletons. Don’t run a single replica in a Deployment. If your only replica is running in a zone that experiences an issue, that application will be unreachable for the duration of the outage.
Configure pod disruption budgets (PDBs). With PDBs, you can specify the minimum number of pods in a set that must always be running. Pods can’t be evicted unless replacement pods from that set are scheduled first. This prevents cluster autoscalers like Karpenter from voluntarily terminating a node before replacement pods are ready.
Note: Forceful terminations will still be processed, for example, Amazon Elastic Compute Cloud (Amazon EC2) Spot interruption events.
Be cognizant of where you run stateful services. Amazon Elastic Block Store (Amazon EBS) volumes are zonal, in that they’re confined to a particular Availability Zone. If that zone experiences an issue, you might lose access to the volumes in that zone. Create periodic snapshots of Amazon EBS volumes (using the Amazon EBS CSI Snapshotter API) and replicate them to other zones so those snapshots can be used to hydrate volumes in alternative zones. You can also investigate whether the stateful service you’re using natively supports replication. If replication isn’t an option, create a backup of the data, for example, with AWS Backup.
Knowing where you’re exposed
The practices above matter most for workloads that actually have zonal redundancy gaps, and at portfolio scale, finding those manually is hard. The next generation of AWS Resilience Hub runs generative-AI failure mode assessments against your services, evaluating them with the AWS Well-Architected best practices and the AWS Resilience Analysis Framework. It surfaces exactly the issues this section addresses: singleton deployments, missing multi-AZ spread, zonal stateful storage, and absent pod disruption budgets. Each finding maps to a requirement in a reusable resilience policy (for example, an availability SLO or an AZ-failure recovery time objective) and comes with how-to-fix guidance you can mark as resolved after you’ve addressed it. Use it to decide which workloads warrant Zonal Shift, then use the following test to prove the control behaves as expected.
Enabling Zonal Shift support (OSS Karpenter)
To enable zonal shift in Karpenter the following conditions must be met:
- Karpenter version 1.12.0 or higher.
- The flag for Zonal Shift,
--enableZonalShift, needs to be set to true on the Karpenter controller. - The AWS Identity and Access Management (IAM) role assigned to the Karpenter controller needs a policy that allows the ARC GetManagedResources API to be called.
- Zonal Shift must be enabled on the EKS cluster.
We’ve created a GitHub repository that includes Terraform examples and scripts that will help you install Karpenter and enable Zonal Shift in new and existing clusters. The module detects your current Karpenter state (not installed, < v1.12.0, or >= v1.12.0) and takes the appropriate action: install, upgrade, or attach the required IAM permission.
Enabling Zonal Shift on Auto Mode clusters
On Auto Mode, enabling Zonal Shift is a single step. There’s no Helm flag to set, no IAM policy to add, and no service-linked role to create. Auto Mode detects shift signals internally, so your cluster’s IAM configuration doesn’t change.
That’s it. Compare this to the four steps required for OSS Karpenter (upgrade, Helm flag, IAM policy, enable on cluster). The observable behavior during a Zonal Shift is identical.
Note: Enabling Zonal Shift on the cluster makes it eligible for manual shifts and registers it as a managed resource in ARC. If you also want AWS to automatically trigger shifts when it detects a zonal impairment, you need to separately enable Zonal Autoshift through the ARC console or API. Without autoshift, you trigger shifts manually.
Running a test
Here’s the full cycle running end to end on a live EKS Auto Mode cluster: deploy a multi-AZ workload, trigger a manual Zonal Shift, observe the behavior, and verify recovery.
Prerequisites
- An EKS Auto Mode cluster with Zonal Shift enabled (see the earlier section Enabling Zonal Shift on Auto Mode clusters).
kubectlconfigured to talk to the cluster.- AWS CLI v2.
Step 1: Deploy a multi-AZ workload
Deploy a 9-replica nginx deployment with topology spread constraints across all Availability Zones, and expose it with a LoadBalancer service:
Step 2: Verify pre-shift state
Wait for pods to spread across zones, then capture the baseline:
Three pods per zone, all nodes untainted, and all nine pod IPs listed as ready in the endpoint slices.
Step 3: Trigger a manual zonal shift
The ARC API uses AZ IDs (for example, eun1-az1) rather than AZ names (for example, eu-north-1a). Map names to IDs first:
Start a Zonal Shift with a 30-minute expiry:
Save the zonalShiftId for canceling the shift later.
Step 4: Observe zonal shift behavior
Wait 60–90 seconds for the shift to take effect, then observe:
Nodes in the affected zone are cordoned and tainted:
The taint eks-arc-zonal-shift/impaired-zone=<zone>:NoSchedule prevents new pods from being scheduled onto these nodes. The node.kubernetes.io/unschedulable taint cordons them as well, providing a redundant guarantee that no new work lands in the impaired zone.
Pods are still running (replica count is unchanged):
All nine pods remain Running. Zonal shift doesn’t evict existing pods. Instead, it prevents new scheduling and removes them from load balancing.
Note: When pods that are part of a Kubernetes Service are deregistered from an AWS Load Balancer or removed from their corresponding EndpointSlices, the carrying capacity of that service temporarily decreases. If the replicas in healthy zones can’t process the incoming traffic for the service, you might need to scale out those services. After the Zonal Shift expires or the impairment is resolved, you can scale the services back in.
Endpoints in the impaired zone are deregistered:
Only six of nine pod IPs remain in the endpoint slices, all from eu-north-1b and eu-north-1c. The three pods running on the eu-north-1a node are excluded from load balancing. Traffic no longer routes to the impaired zone.
New capacity respects the shift:
New nodes launched to handle the scale-up are placed only in healthy zones (eu-north-1b and eu-north-1c). Karpenter doesn’t provision new capacity in the impaired zone. Voluntary disruptions (consolidation, drift) are also suspended in the affected zone, so existing workloads remain stable until recovery.
Step 5: Cancel the shift and verify recovery
Wait 60–90 seconds for recovery to propagate:
Taints are removed, all 15 pod IPs are restored across all three zones, and Karpenter resumes normal provisioning everywhere.
Step 6: (Optional) Test with AWS Fault Injection Service
To simulate how zonal autoshift would trigger automatically during a real impairment using the AWS Fault Injection Service (FIS):
- Enable Zonal Autoshift on the cluster through the ARC console.
- Create a FIS experiment using the “AZ Availability: Power Interruption” scenario from the scenario library.
- The
aws:arc:start-zonal-autoshiftrecovery action triggers automatically 5 minutes into the experiment. - Observe the same previous behavior, but triggered by AWS rather than a manual API call.
See the FIS Zonal Autoshift testing documentation for detailed instructions.
Clean up
This test uses Amazon EKS and Amazon EC2 resources that incur costs. Complete the following steps to avoid ongoing charges.
Delete the sample workload
(Optional) Disable zonal shift on the cluster
Conclusion
ARC Zonal Shift gives you a single-API recovery mechanism when an Availability Zone goes bad. On EKS Auto Mode, that integration is one configuration flag away. No IAM changes, no Helm values, no controller upgrades. Enable it, and Karpenter handles the rest: tainting nodes in the affected zone, deregistering endpoints, blocking new capacity there, and suspending voluntary disruptions until the zone recovers. Pair it with Zonal Autoshift and you don’t even need to press the button. AWS detects the impairment and shifts for you.
Zonal Shift is the recovery control. The next generation of AWS Resilience Hub is how you find the workloads that need it and confirm they’re built to survive an AZ loss. Assess with Resilience Hub, implement the multi-AZ practices it recommends, validate with a zonal shift (or FIS-driven autoshift), and you’ve closed the resilience loop: assess, implement, test, recover.
To get started, see the following resources:
Enable EKS zonal shift (EKS User Guide)
Amazon Application Recovery Controller (service page)
Karpenter ARC Zonal Shift Terraform module (GitHub)
Enhance Kubernetes high availability with ARC and Karpenter integration (related blog)
End-to-end recovery from AZ impairments in Amazon EKS using EKS Zonal shift and Istio (related blog)