Skip to main content

EKS Control Plane Deep Dive — CRD at Scale Comprehensive Guide

41 min read

When operating platforms based on Custom Resource Definitions (CRDs) on EKS, the control plane is the first point to become a bottleneck. This guide explains how the control plane works, the specific impact of CRDs, and practical strategies for responding proactively with Provisioned Control Plane (PCP) and monitoring.


Contents​

  1. EKS Control Plane Internal Architecture
  2. Control Plane Auto-Scaling
  3. EKS Provisioned Control Plane (PCP)
  4. Impact of CRDs on Control Plane
  5. EKS Control Plane Monitoring
  6. CRD Design Best Practices
  7. Recommendations & Adoption Roadmap

1. EKS Control Plane Internal Architecture​

1.1 Physical Infrastructure Layout​

The EKS control plane runs in a dedicated VPC managed by AWS. Its infrastructure is independent of the customer's worker nodes.

EKS Control Plane (AWS Managed)
├── kube-apiserver (at least 2, distributed across multiple AZs)
├── kube-controller-manager
├── kube-scheduler
├── etcd (distributed key-value store)
└── Network Load Balancer (API Server endpoint)

Key points:

  • Control plane components are distributed across multiple AZs for high availability.
  • Customers access a single API server endpoint through an NLB.
  • AWS fully manages the control plane in an environment separate from the customer VPC.

1.2 etcd — The Heart of the Control Plane​

etcd is the distributed key-value store that holds all Kubernetes state, including Pods, Services, and CRD objects. The following characteristics make it a key control plane performance bottleneck:

CharacteristicDescriptionCRD Impact
DB Size LimitStandard tier: 8GB; Provisioned tier: 16GBMore CRD objects increase database size
Request Size LimitMaximum of 1.5MB per objectCRs with large specs can approach the limit
Watch StreamPropagates changes in real timeEach additional watch from a CRD controller increases load
RAFT ConsensusWrites require agreement from a majorityWrite-heavy CRD patterns introduce latency
etcd Architecture Evolution

AWS continues to improve the EKS etcd layer, with work on predictable performance (consistent latency), data durability, and availability.


2. Control Plane Auto-Scaling​

2.1 How Auto-Scaling Works​

EKS automatically scales control plane instances vertically. Resources for the API server, etcd, and other components adjust to workload demand. The main scaling signals are:

  • API server load: Number of inflight requests and request latency
  • etcd load: Database size and number of watch streams
  • Scheduling load: Number of Pods waiting to be scheduled
  • Data plane size: Proactive scale-up based on worker node count

2.2 Scaling Characteristics​

  • Scale up: Automatically scales up when increased load is detected.
  • Scale down: Scales down conservatively after load decreases to avoid abrupt reductions.
  • Standard mode has an upper scaling limit, which Provisioned mode can extend.
Key Insight

In the Standard tier, etcd database size is fixed at 8GB. This limit is the first bottleneck for platforms with many CRD objects. Increasing CPU and memory through auto-scaling does not expand etcd capacity.


3. EKS Provisioned Control Plane (PCP)​

3.1 Overview​

EKS Provisioned Control Plane (PCP) became generally available at re:Invent 20251. It allows customers to select a control plane scaling tier, or T-shirt size, to establish pre-allocated capacity.

PCP provisions the selected tier’s capacity in advance. Actual API throughput and latency depend on request types, controller patterns, and the Kubernetes version, so workload validation is required.

3.2 Two Operating Modes​

ModeDescription
Standard (dynamic mode)Existing behavior: scales automatically with load and scales down conservatively when load decreases
Provisioned (provisioned mode)Customers select XL, 2XL, 4XL, or 8XL. There is no automatic transition between tiers; an administrator changes the tier or configures separate automation

3.3 Tier Specifications and Pricing​

Tieretcd DBSLAHourly Price
Standard8GB99.95%$0.10
XL16GB99.99%$1.65
2XL16GB99.99%$3.40
4XL16GB99.99%$6.90
8XL16GB99.99%$13.90

Standard’s $0.10/hour is the Kubernetes standard-support charge. Provisioned row prices are tier charges added to standard/extended-support charges. Refer to AWS EKS Pricing for current prices.

The official tier specifications give Standard an 8 GB etcd limit and XL, 2XL, 4XL, and 8XL the same 16 GB limit. GB follows the official documentation’s unit. Raising a Provisioned tier does not increase etcd capacity. Check the Kubernetes-version-specific API concurrency and scheduling settings.

3.4 Features Available Only in Provisioned Tiers​

FeatureStandardXL and Above
Pre-allocated API concurrency capacityAutomatic capacity adjustment with loadCapacity selected by Kubernetes version and tier
16GB etcd databaseFixed at 8GB16GB
etcd Event ShardingUnavailableAvailable (separates event objects into a dedicated etcd partition)
99.99% SLA99.95%99.99%
Why Provisioned for CRD Platforms

etcd database size is the first limit reached by CRD-based platforms. The Standard tier's 8GB limit can be exhausted quickly in environments with many CRD objects. Provisioned tiers double the capacity to 16GB, and Event Sharding can isolate the load from event objects.

Detailed Sizing Guidance

For Kubernetes parameters by tier (API server inflight requests and scheduler QPS), the APF seat calculation formula, a 10K-node sizing example, customer examples, and ClusterLoader2 performance validation, refer to the PCP Tier Sizing & Performance Validation Guide.

3.5 CLI/API Usage​

Specify a tier when creating a cluster:

aws eks create-cluster --name prod \
--role-arn arn:aws:iam::012345678910:role/eks-service-role \
--resources-vpc-config subnetIds=subnet-xxx,securityGroupIds=sg-xxx \
--control-plane-scaling-config tier=XL

Change the tier of an existing cluster:

aws eks update-cluster-config --name example \
--control-plane-scaling-config tier=XL

Check update progress:

aws eks describe-update --name example --update-id <update-id>
# Response: { "update": { "type": "ScalingTierConfigUpdate", "status": "Successful" } }

Check cluster information:

aws eks describe-cluster --name example
# The response includes the controlPlaneScalingConfig.tier field

Note: The CLI flag syntax (--control-plane-scaling-config tier=XL) may vary by AWS CLI version. Refer to the AWS CLI Command Reference - EKS for the current syntax.

3.6 PCP Cluster Properties​

PropertyDescription
controlPlaneScalingConfig.tierCurrently provisioned tier (Standard/XL/2XL/4XL/8XL)

4. Impact of CRDs on Control Plane​

Operating a CRD-based platform requires an accurate understanding of its control plane impact. The two main areas are etcd and the API server.

4.1 Impact on etcd​

etcd is the most important area of impact.

FactorMechanismImpact
DB Size GrowthCRD objects occupy etcd storageHigh
Watch Stream LoadCRD controllers create watch streams, increasing etcd gRPC loadHigh
Request SizeIndividual CRD objects can approach the 1.5MB limitMedium
List Call CostCRDs use JSON encoding rather than protobuf, creating a performance bottleneckHigh

etcd database size limits by PCP tier:

TierDB Size LimitPer-Object Limit
Standard8GB1.5MB (cannot be changed)
Provisioned (XL and above)16GB1.5MB (cannot be changed)

4.2 Impact on API Server​

CRD-related API server performance issues include:

  1. JSON vs Protobuf: CRDs use JSON serialization, which significantly reduces List/Watch performance compared with built-in resources.
  2. API Priority and Fairness (APF): The work estimator can assign up to 10 seats to a List request, quickly consuming the inflight request limit.
  3. Watch Cache: The default watch cache capacity for CRDs is 100, the same as for built-in resources.

4.3 Mapping Symptoms to Causes​

The following diagram maps operational symptoms to their causes:

Expand the diagram to read labels and follow connections.
Diagram
CRD Load Formula

Control Plane Load = CRD Type Count x Object Size x Controller Pattern (List/Watch Frequency)

All three factors require management. Even with few CRD types, large objects or inefficient controllers can cause the same problems.


5. EKS Control Plane Monitoring​

EKS provides four dimensions of observability for the control plane:

┌──────────────────────────────────────────────────────────────────────────────────────────┐
│ EKS Control Plane Observability │
├──────────────────────┬──────────────────────┬──────────────────────┬─────────────────────┤
│ ① CloudWatch │ ② Prometheus │ ③ Control Plane │ ④ Cluster │
│ Vended Metrics │ Metrics Endpoint │ Logging │ Insights │
├──────────────────────┼──────────────────────┼──────────────────────┼─────────────────────┤
│ AWS/EKS namespace │ KCM/KSH/etcd │ API/Audit/ │ Upgrade readiness │
│ (automatic, free) │ (Prometheus- │ Auth/CM/Sched │ Health issues │
│ │ compatible K8s API) │ (CloudWatch Logs) │ Addon compatibility │
├──────────────────────┼──────────────────────┼──────────────────────┼─────────────────────┤
│ v1.28+, automatic │ v1.28+, manual │ All versions │ All versions, auto │
└──────────────────────┴──────────────────────┴──────────────────────┴─────────────────────┘

5.1 CloudWatch Vended Metrics (Automatic, Free)​

For clusters running Kubernetes 1.28 or later, key control plane metrics are automatically published to the CloudWatch AWS/EKS namespace at no additional charge.

Key vended metrics:

ComponentMetricDescriptionPriority
API Serverapiserver_request_totalTotal API requestsEssential
API Serverapiserver_request_total_4XXRequests with 4xx errorsEssential
API Serverapiserver_request_total_5XXRequests with 5xx errorsEssential
API Serverapiserver_request_total_429Requests throttled with 429 responsesEssential
API Serverapiserver_request_duration_seconds_GET_P99GET request latency at p99Recommended
etcdetcd_mvcc_db_total_size_in_bytesPhysical file size, including unused space; not the quota-enforcement metricRecommended
Schedulerscheduler_schedule_attempts_totalTotal scheduling attemptsRecommended
Schedulerscheduler_schedule_attempts_SCHEDULEDSuccessful scheduling attemptsEssential
Schedulerscheduler_schedule_attempts_UNSCHEDULABLEUnschedulable attemptsRecommended

Tier utilization metrics:

MetricDescriptionUsage
apiserver_flowcontrol_current_executing_seatsCurrently executing concurrent seats on the API serverMonitor against the tier's API Request Concurrency limit
etcd_mvcc_db_total_size_in_use_in_bytesActual etcd database space in useMonitor against the tier's Cluster Database Size limit
etcd_mvcc_db_total_size_in_bytesPhysical etcd file sizeCompare with actual usage to identify unused space

These names follow the CloudWatch AWS/EKS metrics. Prometheus apiserver_storage_size_bytes also measures physical file size, which differs from actual usage used for quota enforcement. Use etcd_mvcc_db_total_size_in_use_in_bytes for usage alarms. Check whether the cluster exposes that metric through Prometheus; otherwise, use its CloudWatch value.

5.2 Prometheus-Compatible Metrics Endpoints​

In addition to API server metrics, metrics from kube-controller-manager (KCM), kube-scheduler (KSH), and etcd can also be scraped.

Metrics endpoint paths:

# API Server metrics (existing endpoint)
kubectl get --raw=/metrics

# Kube-Controller-Manager metrics
kubectl get --raw=/apis/metrics.eks.amazonaws.com/v1/kcm/container/metrics

# Kube-Scheduler metrics
kubectl get --raw=/apis/metrics.eks.amazonaws.com/v1/ksh/container/metrics

# etcd metrics
kubectl get --raw=/apis/metrics.eks.amazonaws.com/v1/etcd/container/metrics

Example Prometheus scrape configuration:

scrape_configs:
- job_name: 'kcm-metrics'
honor_labels: true
kubernetes_sd_configs:
- role: endpoints
scheme: https
metrics_path: /apis/metrics.eks.amazonaws.com/v1/kcm/container/metrics
tls_config:
ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt
bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token
relabel_configs:
- source_labels:
[__meta_kubernetes_namespace, __meta_kubernetes_service_name,
__meta_kubernetes_endpoint_port_name]
action: keep
regex: default;kubernetes;https

Required RBAC permissions:

rules:
- apiGroups: ["metrics.eks.amazonaws.com"]
resources: ["kcm/metrics", "ksh/metrics", "etcd/metrics"]
verbs: ["get"]

KCM/KSH metrics particularly useful for CRD operations:

MetricSourceDescription
workqueue_depthKCMWork queue depth per controller; indicates CRD controller load
workqueue_adds_totalKCMTotal items added to the queue
workqueue_retries_totalKCMRetry count; indicates CRD controller error rates
scheduler_pending_podsKSHNumber of pending Pods
scheduler_scheduling_duration_secondsKSHScheduling latency
apiserver_flowcontrol_current_executing_seatsAPI ServerCurrently executing seats by APF; indicates the impact of CRD List requests

Amazon Managed Prometheus (AMP) integration:

The EKS Agentless Collector (Poseidon) can automatically collect control plane metrics into an AMP workspace without installing Prometheus in the cluster.

EKS Console → Observability tab → Add scraper → Select AMP Workspace

5.3 Control Plane Logging​

EKS can export five types of control plane logs to CloudWatch Logs:

Log TypeDescriptionCRD Use Case
API Server (api)API request/response logsAnalyze CRD API call patterns
Audit (audit)Audit logs recording who did whatTrack CRD changes and perform security audits
AuthenticatorIAM authentication logsDebug authentication issues
Controller ManagerKCM diagnostic logsAnalyze CRD controller errors
SchedulerScheduler decision logsAnalyze Pod scheduling issues

Enable logging:

aws eks update-cluster-config --name my-cluster \
--logging '{"clusterLogging":[{"types":["api","audit","authenticator","controllerManager","scheduler"],"enabled":true}]}'

Example CloudWatch Logs Insights query to analyze CRD-related API call patterns:

-- Analyze CRD-related API call patterns
fields @timestamp, userAgent, verb, requestURI
| filter requestURI like /customresourcedefinitions/
| stats count(*) by verb, userAgent
| sort count(*) desc
| limit 20

5.4 Cluster Insights​

EKS Cluster Insights automatically scans clusters to detect potential issues and provide recommendations:

CategoryDescriptionFrequency
Upgrade InsightsDetects items that could cause issues during a Kubernetes version upgradeEvery 24 hours + manual
Configuration InsightsDetects cluster configuration errorsEvery 24 hours + manual
Addon CompatibilityChecks whether EKS add-ons are compatible with the next Kubernetes versionEvery 24 hours
Cluster Health IssuesReports current cluster health issuesEvery 24 hours
aws eks list-insights --cluster-name my-cluster
aws eks describe-insight --cluster-name my-cluster --id <insight-id>

5.5 EKS Console Observability Dashboard​

The EKS console includes an integrated observability dashboard:

EKS Console → Select cluster → Observability tab
├── Health and Performance Summary (summary cards)
├── Cluster Health Issues (list of health issues)
├── Control Plane Monitoring
│ ├── Metrics (CloudWatch-based graphs)
│ │ ├── API Server Request Types (Total, 4XX, 5XX, 429)
│ │ ├── etcd Database Size
│ │ └── Kube-Scheduler Scheduling Attempts
│ ├── CloudWatch Log Insights (predefined queries)
│ └── Control Plane Logs (CloudWatch links)
└── Upgrade Insights (upgrade readiness)

5.6 Monitoring Channel Comparison​

ChannelCostSetupData TypePCP Support
CloudWatch Vended MetricsFree (AWS/EKS)Automatic (v1.28+)Key Kubernetes metrics (time series)Includes tier usage metrics
Prometheus EndpointFree (scraping)Manual configuration requiredDetailed KCM/KSH/etcd metricsExtensible
Control Plane LoggingStandard CloudWatch ratesManual enablementLogs (API/Audit/Auth/CM/Sched)—
Cluster InsightsFreeAutomaticCluster health and upgrade recommendationsPCP tier recommendations (future)
EKS Console DashboardFreeAutomaticVisualized metrics + log queriesDisplays tier information

6. CRD Design Best Practices​

6.1 Minimize Object Size​

  • Keep each CR instance's spec as small as possible, within the etcd 1.5MB request limit.
  • Move large data into ConfigMaps or external storage references.
  • Include only necessary information in the status field; keep history and log data externally.

6.2 Manage CRD Count​

  • As the number of CRD types grows, the API server watch cache and etcd watch streams grow proportionally.
  • Where possible, consolidate similar resources into one CRD using a subresource pattern.
  • Remove unused CRDs.

6.3 Optimize Controllers​

PatternCorrect UsageUsage to Avoid
Watch resourceVersionUse resourceVersion correctlyDo not use resourceVersion="" (retrieves the full list again)
List CallsAlways use paginationRetrieving the entire list in one call
InformerUse the client-go SharedInformer patternCreating independent watches for each controller
ReconnectionApply exponential backoff when a watch disconnectsReconnecting immediately (thundering herd)

6.4 Keep Kubernetes Versions Current​

  • Kubernetes 1.33+ supports Streaming List, significantly improving large-scale List performance.
  • Use the latest Kubernetes version where possible to benefit from control plane performance improvements.

6.5 Cluster Architecture Recommendations​

Separate clusters by workload:

  • For large CRD deployments, separate the core CRD cluster from workload execution clusters.
  • Platform CRDs and tenant workloads affect each other when they share a cluster.

Namespace-based isolation:

  • Use Kubernetes ResourceQuota to limit object counts per namespace.
  • Prevent runaway object creation caused by faulty automation or bugs.

7. Recommendations & Adoption Roadmap​

7.1 PCP Tier Selection by CRD Scale​

Do not select a tier from node count alone. Narrow the candidates using the conditions below, then validate API latency, APF seat utilization, and scheduling rate under representative peak load.

Validation ConditionMode/Tier to ConsiderCheck
Standard meets latency and throughput targets with sufficient etcd headroomStandardDefault choice for most use cases
Pre-allocated capacity, 16 GB etcd, or a 99.99% SLA is requiredProvisioned XL or aboveValidate that XL meets actual peak demand
XL API concurrency or scheduling capacity is insufficient2XLCompare with the tier specifications for the Kubernetes version
2XL capacity does not meet the target4XL or 8XL8XL still has 16 GB etcd and may have the same scheduling setting as 4XL

7.2 Control Plane Metrics Reference by Scale​

Do not use unsupported industry averages for QPS, object counts, or latency by node count to select a tier. Separate published capacity limits from operating targets measured for your own workload.

MetricMeasurementDecision Basis
etcd DB SizeCollect actual usage and physical file size separatelyCompare actual usage with the 8 GB Standard or 16 GB Provisioned limit
etcd Object CountCount and size by resourceInvestigate growth and retention rather than infer a tier from counts alone
API QPS (requests/second)Request rate by verb and resourceValidate APF costs by request type and peak demand
API Request Latency (p99)Latency distribution by verbCompare with the service’s own latency target
429 ThrottleFraction of requests returning 429 and durationInvestigate APF, client retries, and request patterns
Watch ConnectionsLong-running WATCH request countCheck reconnect storms and changes by controller
CRD TypesInstalled CRDs and CR countsDo not infer capacity or performance from type counts alone
Controller Reconciliations/SecondRate, processing time, and queue depth by controllerDistinguish retry storms from processing delays
How to Measure
  • Actual etcd usage: CloudWatch etcd_mvcc_db_total_size_in_use_in_bytes; distinguish it from physical file size
  • API QPS: Rate of apiserver_request_total (separate by verb where possible)
  • 429 throttling: apiserver_request_total{code="429"}; investigate immediately if nonzero
  • Watch connections: apiserver_longrunning_requests{verb="WATCH"}; proportional to controller and node counts
  • Reconciliation rate: Rate of controller_runtime_reconcile_total for each controller
etcd Size Alert Thresholds

These are illustrative operating thresholds, not AWS default alarms. For the example calculation, GB is converted to 10⁹ bytes. Adjust thresholds for usage growth and response time so action occurs before the limit is reached.

  • Standard (8 GB): Warning at 6 GB; Critical at 7.2 GB
  • XL/2XL/4XL/8XL (16 GB): Warning at 12 GB; Critical at 14.4 GB
  • Remove unused CRs and retained data, and investigate object growth. Standard can move to Provisioned, but raising a Provisioned tier does not increase the etcd limit. Consider external data storage or separate clusters if usage continues to grow.

7.3 Key Alarm Configuration​

The following thresholds and durations are operating examples. For one-minute CloudWatch metrics, use Sum for request/scheduling counts and Maximum for etcd usage. Do not interpret missing data as zero usage. Tune these examples to your SLOs and normal load.

Alarm NameMetricThresholdSeverityResponse
API Throttlingapiserver_request_total_429> 10/minute for 5 minutesCriticalInvestigate APF, retries, and request load before changing capacity
API Server Errorsapiserver_request_total_5XX> 5/minute for 3 minutesCriticalCheck control plane logs
etcd DB Usageetcd_mvcc_db_total_size_in_use_in_bytes> 6 GB (Standard) / > 12 GB (Provisioned)WarningRemove unnecessary CRD resources
etcd DB Headroometcd_mvcc_db_total_size_in_use_in_bytes> 7.2 GB (Standard) / > 14.4 GB (Provisioned)CriticalRestrain growth, clean up data, or consider separation before reaching the limit
Scheduling Failuresscheduler_schedule_attempts_UNSCHEDULABLE> 0 for 10 minutesWarningCheck node resources
API Concurrencyapiserver_flowcontrol_current_executing_seats> 80% of tier seats for the Kubernetes versionWarningConsider provisioning a higher tier
Integrated Monitoring Architecture
│
[1] CloudWatch Vended Metrics (automatic)
│ → Configure alarms in the AWS/EKS namespace
│ → Use the console observability dashboard
│
[2] Prometheus Endpoint (manual configuration)
│ → AMP Agentless Scraper or self-hosted Prometheus
│ → Monitor CRD controllers with KCM workqueue metrics
│ → Configure Grafana dashboards
│
[3] Control Plane Logging (manual enablement)
│ → Enable audit + controllerManager logs as a requirement
│ → Analyze CRD-related API call patterns
│
[4] Cluster Insights (automatic)
→ Review before every upgrade
→ PCP tier recommendations (future)

7.5 Phased Adoption Roadmap​

PhaseDurationMain Activities
Phase 1: Basic Setup1 weekConfigure CloudWatch alarms and enable control plane logging (audit + controllerManager)
Phase 2: Prometheus Integration2 weeksConfigure AMP Scraper, collect KCM/KSH metrics, and create Grafana dashboards
Phase 3: PCP Adoption1 weekAnalyze the workload profile and select an appropriate PCP tier (XL or above recommended)
Phase 4: OptimizationOngoingUse Cluster Insights, adjust tiers based on monitoring data, and tune CRD controllers

7.6 Summary of Responses to Key Challenges​

ChallengeEKS CapabilitiesCRD Design Response
etcd Overload from CRDsProvisioned tier: 16GB etcd + Event ShardingReduce CR object size and retention; consider Provisioned based on actual storage usage
API Server Performance DegradationAPI concurrency capacity by Kubernetes version and PCP tier + APF priority managementValidate API throughput and latency under representative peak load; optimize controller List/Watch patterns
Scheduling LimitsScheduling settings by Kubernetes version and PCP tierValidate scheduling throughput under representative peak load before selecting capacity
Control Plane StabilityMulti-AZ and 99.99% SLA (Provisioned)Select Standard or Provisioned based on SLOs and the need for pre-allocated capacity
Cost PredictabilityKubernetes support charges plus the selected PCP tier’s hourly chargeSelect a tier that matches the workload profile
Limited VisibilityFour monitoring channels (Vended Metrics, Prometheus, Logging, Insights)Introduce monitoring through Phases 1–4

Footnotes​

  1. The 8XL tier and 99.99% SLA guarantee were added in March 2026. ↩