前言:一個讓人懷疑人生的 Pending 狀態

最近部署 Strapi CMS 到 AWS EKS 時,遇到一個詭異的情況:

$ kubectl get pods -n default
NAME                                    READY   STATUS    RESTARTS   AGE
mycompany-strapi-prod-695854fbd4-dzw66  0/1     Pending   0          3h42m

一個 Pod 卡在 Pending 狀態超過三小時,CPU 和 Memory 明明還很充足,但就是起不來。

如果你曾經盯著 kubectl get pods 看著那個永遠不會變成 Running 的 Pending 狀態,同時懷疑是不是 Kubernetes 在跟你開玩笑——恭喜你,你不孤單。

在嘗試了 Google 前五個搜尋結果、檢查了三次 YAML 設定、並認真考慮是否該轉行當咖啡師之後,我終於找到了問題的根源…

⚠️ 劇透警告:問題的根源不是 CPU、不是 Memory,而是一個你可能從沒注意過的限制——網卡(ENI)和 IP 數量


問題診斷:一步步找出真兇

Step 1:查看 Pod 事件

遇到 Pending 狀態,第一步當然是看看 Kubernetes 到底在抱怨什麼:

$ kubectl describe pod mycompany-strapi-prod-695854fbd4-dzw66 -n default

輸出內容很長,但最重要的是 Events 區塊:

Name:           mycompany-strapi-prod-695854fbd4-dzw66
Namespace:      default
Priority:       0
Node:           <none>
Labels:         app=strapi
                pod-template-hash=695854fbd4
Annotations:    <none>
Status:         Pending
IP:
IPs:            <none>
Controlled By:  ReplicaSet/mycompany-strapi-prod-695854fbd4

Containers:
  strapi:
    Image:      mycompany/strapi:v1.2.3
    Port:       1337/TCP
    Host Port:  0/TCP
    Requests:
      cpu:      250m
      memory:   512Mi
    Limits:
      cpu:      500m
      memory:   1Gi

Events:
  Type     Reason            Age   From               Message
  ----     ------            ----  ----               -------
  Warning  FailedScheduling  3h    default-scheduler  0/1 nodes are available:
                                                       1 Too many pods.

「Too many pods」?我只跑了十幾個 Pod,怎麼可能太多?

這個錯誤訊息極具誤導性。它讓你以為是 Pod 數量的「軟限制」問題,實際上是硬性的網路限制

Step 2:檢查 Node 資源使用狀況

既然說 Pod 太多,那來看看 Node 的資源狀況:

$ kubectl describe node ip-10-0-1-xxx.ap-northeast-1.compute.internal
Name:               ip-10-0-1-xxx.ap-northeast-1.compute.internal
Roles:              <none>
Labels:             beta.kubernetes.io/arch=amd64
                    beta.kubernetes.io/instance-type=t3.medium
                    beta.kubernetes.io/os=linux
                    kubernetes.io/arch=amd64
                    kubernetes.io/hostname=ip-10-0-1-xxx.ap-northeast-1.compute.internal
                    kubernetes.io/os=linux
                    node.kubernetes.io/instance-type=t3.medium
                    topology.kubernetes.io/region=ap-northeast-1
                    topology.kubernetes.io/zone=ap-northeast-1a

Allocated resources:
  (Total limits may be over 100 percent, i.e., overcommitted.)
  Resource           Requests      Limits
  --------           --------      ------
  cpu                680m (35%)    1200m (61%)
  memory             756Mi (22%)   1536Mi (44%)
  ephemeral-storage  0 (0%)        0 (0%)
  hugepages-1Gi      0 (0%)        0 (0%)
  hugepages-2Mi      0 (0%)        0 (0%)

CPU 使用 35%、Memory 使用 22%,資源明明還很充裕!

Step 3:發現關鍵線索——Pod 容量限制

繼續往下看 Node 的詳細資訊:

$ kubectl describe node <node-name> | grep -A 10 "Capacity"
Capacity:
  attachable-volumes-aws-ebs:  25
  cpu:                         2
  ephemeral-storage:           20959212Ki
  hugepages-1Gi:               0
  hugepages-2Mi:               0
  memory:                      3943376Ki
  pods:                        17          # 👈 注意這裡!

Allocatable:
  attachable-volumes-aws-ebs:  25
  cpu:                         1930m
  ephemeral-storage:           19316009748
  hugepages-1Gi:               0
  hugepages-2Mi:               0
  memory:                      3388496Ki
  pods:                        17          # 👈 最大 Pod 數量是 17!

再查看目前執行中的 Pod 數量:

$ kubectl get pods -A --field-selector spec.nodeName=ip-10-0-1-xxx --no-headers | wc -l
17

真相大白:Node 上已經有 17 個 Pod,而這個 Node 的 Pod 上限剛好是 17!

但問題來了:為什麼 t3.medium 這種看起來還不錯的 Instance,Pod 上限只有 17 個?


深入理解:AWS VPC CNI 的運作機制

為什麼 EKS 要用 VPC CNI?

在深入 ENI 限制之前,我們先了解 EKS 的網路架構選擇。

Kubernetes 本身不處理 Pod 網路,而是依賴 CNI(Container Network Interface) 插件。常見的 CNI 插件包括:

  • Calico:使用 BGP 或 VXLAN 建立虛擬網路
  • Flannel:使用 VXLAN 或 host-gw 模式
  • Weave:使用自己的虛擬網路協定
  • AWS VPC CNI:直接使用 VPC 原生 IP

AWS EKS 預設使用 AWS VPC CNI,它的特別之處在於:

每個 Pod 都會獲得一個真實的 VPC IP 位址

Mermaid Diagram

VPC CNI 的優缺點

優點:

特性說明
✅ 原生 VPC 整合Pod 可直接與 RDS、ElastiCache 等 VPC 資源通訊
✅ 無需 NATPod IP 就是真實 VPC IP,不需要轉換
✅ 安全群組支援可以直接對 Pod 套用 Security Groups
✅ 網路效能沒有 overlay 網路的額外開銷
✅ 除錯簡單IP 直接對應,方便追蹤網路問題

缺點:

特性說明
❌ IP 數量限制受限於 ENI 和 IP 配額
❌ Subnet 規劃需要足夠大的 CIDR 區塊
❌ Pod 數量限制比其他 CNI 方案更嚴格

ENI 是什麼?為什麼會有限制?

ENI(Elastic Network Interface) 是 AWS EC2 的虛擬網路卡。每個 ENI 可以:

  • 綁定一個 Primary IP(主要 IP)
  • 綁定多個 Secondary IP(次要 IP)
  • 附加到 EC2 Instance
Mermaid Diagram

AWS 對每種 EC2 Instance 類型都有 ENI 和 IP 的限制,這些限制是硬性的,由底層硬體和網路架構決定。

Pod 數量計算公式

AWS VPC CNI 的 Pod 數量上限計算公式為:

Max Pods = (ENI 數量 × 每個 ENI 的 IP 數) - ENI 數量

為什麼要減掉 ENI 數量?

因為每個 ENI 的 Primary IP 是保留給 ENI 本身使用的,不能分配給 Pod。只有 Secondary IP 可以用於 Pod。

以 t3.medium 為例

t3.medium 的限制:
├─ 最大 ENI 數量:3
└─ 每個 ENI 的 IPv4 數量:6

計算過程:
├─ 總 IP 數:3 × 6 = 18 個
├─ Primary IP(保留):3 個
└─ 可用於 Pod:18 - 3 = 15 個

實際上 EKS 顯示的是 17,這是因為:
└─ AWS 有一些額外的優化和 CNI 版本差異

常見 Instance 類型的 Pod 限制

Instance 類型vCPUMemoryENI 數量每 ENI IP 數Max Pods適用場景
t3.micro21 GB224學習/測試
t3.small22 GB3411小型開發
t3.medium24 GB3617開發/小型生產
t3.large28 GB31235中型生產
t3.xlarge416 GB41558大型生產
t3.2xlarge832 GB41558高負載生產
m5.large28 GB31029生產環境
m5.xlarge416 GB41558高負載生產
m5.2xlarge832 GB41558大型應用
c5.large24 GB31029運算密集
c5.xlarge48 GB41558高運算需求
r5.large216 GB31029記憶體密集

💡 完整清單AWS 官方文件 - 每個 Instance 類型的 ENI 和 IP 限制


視覺化診斷流程

當你遇到 Pod Pending 問題時,可以按照以下流程進行診斷:

Mermaid Diagram

快速診斷指令

#!/bin/bash
# quick-diagnosis.sh - EKS Pod Capacity 快速診斷腳本

echo "======================================"
echo "EKS Pod Capacity 診斷報告"
echo "======================================"
echo ""

# 取得所有 Node
for node in $(kubectl get nodes -o name); do
    node_name=$(echo $node | cut -d'/' -f2)

    echo "📍 Node: $node_name"
    echo "-----------------------------------"

    # 取得 Instance 類型
    instance_type=$(kubectl get $node -o jsonpath='{.metadata.labels.node\.kubernetes\.io/instance-type}')
    echo "   Instance Type: $instance_type"

    # 取得 Pod 容量
    max_pods=$(kubectl get $node -o jsonpath='{.status.allocatable.pods}')
    echo "   Max Pods: $max_pods"

    # 取得目前 Pod 數
    current_pods=$(kubectl get pods -A --field-selector spec.nodeName=$node_name --no-headers 2>/dev/null | wc -l)
    echo "   Current Pods: $current_pods"

    # 計算使用率
    if [ "$max_pods" -gt 0 ]; then
        usage=$((current_pods * 100 / max_pods))
        echo "   Usage: ${usage}%"

        # 警告訊息
        if [ $usage -ge 90 ]; then
            echo "   ⚠️  WARNING: Pod 容量即將耗盡!"
        elif [ $usage -ge 80 ]; then
            echo "   ⚡ NOTICE: Pod 容量使用率較高"
        else
            echo "   ✅ OK: Pod 容量充足"
        fi
    fi

    echo ""
done

echo "======================================"
echo "診斷完成"
echo "======================================"

執行結果範例:

======================================
EKS Pod Capacity 診斷報告
======================================

📍 Node: ip-10-0-1-101.ap-northeast-1.compute.internal
-----------------------------------
   Instance Type: t3.medium
   Max Pods: 17
   Current Pods: 17
   Usage: 100%
   ⚠️  WARNING: Pod 容量即將耗盡!

📍 Node: ip-10-0-1-102.ap-northeast-1.compute.internal
-----------------------------------
   Instance Type: t3.medium
   Max Pods: 17
   Current Pods: 12
   Usage: 70%
   ✅ OK: Pod 容量充足

======================================
診斷完成
======================================

五種解決方案詳解

方案一:水平擴展(增加 Node 數量)

適用場景:

  • 需要快速解決問題
  • 預算允許
  • 希望同時增加整體運算能力

使用 eksctl 擴展:

# 查看目前的 Node Group
eksctl get nodegroup --cluster=my-cluster

# 擴展 Node 數量
eksctl scale nodegroup \
  --cluster=my-cluster \
  --name=my-nodegroup \
  --nodes=3 \
  --nodes-min=2 \
  --nodes-max=5

使用 AWS CLI 擴展:

aws eks update-nodegroup-config \
  --cluster-name my-cluster \
  --nodegroup-name my-nodegroup \
  --scaling-config minSize=2,maxSize=5,desiredSize=3

優缺點分析:

優點缺點
✅ 最直接的解決方案❌ 成本增加
✅ 同時增加運算能力❌ 可能造成資源浪費
✅ 提高整體可用性❌ 需要更多管理
✅ 無需修改應用程式❌ Subnet IP 消耗增加

方案二:垂直擴展(升級 Instance 類型)

適用場景:

  • 單個 Pod 資源需求大
  • 希望在較少 Node 上運行更多 Pod
  • 需要更高的單機效能

Instance 升級建議路徑:

Mermaid Diagram

使用 eksctl 更新 Node Group:

# nodegroup-config.yaml
apiVersion: eksctl.io/v1alpha5
kind: ClusterConfig

metadata:
  name: my-cluster
  region: ap-northeast-1

managedNodeGroups:
  - name: production-ng
    instanceType: t3.large    # 從 t3.medium 升級
    desiredCapacity: 2
    minSize: 1
    maxSize: 4
    volumeSize: 50
    volumeType: gp3
    labels:
      role: production
      environment: prod
    tags:
      Owner: DevOps
      Project: MyApp
    iam:
      withAddonPolicies:
        autoScaler: true
        cloudWatch: true
# 建立新的 Node Group
eksctl create nodegroup -f nodegroup-config.yaml

# 刪除舊的 Node Group(確保 Pod 已遷移後)
eksctl delete nodegroup \
  --cluster=my-cluster \
  --name=old-nodegroup

方案三:啟用 Cluster Autoscaler

適用場景:

  • Pod 數量會動態變化
  • 希望自動調整成本
  • 需要應對流量高峰

架構圖:

Mermaid Diagram

Step 1:設定 Node Group Tags

# 在 AWS Console 或使用 CLI 為 Auto Scaling Group 加上這些 tag
aws autoscaling create-or-update-tags \
  --tags \
    "ResourceId=my-asg-name,ResourceType=auto-scaling-group,Key=k8s.io/cluster-autoscaler/enabled,Value=true,PropagateAtLaunch=true" \
    "ResourceId=my-asg-name,ResourceType=auto-scaling-group,Key=k8s.io/cluster-autoscaler/my-cluster,Value=owned,PropagateAtLaunch=true"

Step 2:部署 Cluster Autoscaler

# cluster-autoscaler.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: cluster-autoscaler
  namespace: kube-system
  labels:
    app: cluster-autoscaler
spec:
  replicas: 1
  selector:
    matchLabels:
      app: cluster-autoscaler
  template:
    metadata:
      labels:
        app: cluster-autoscaler
    spec:
      serviceAccountName: cluster-autoscaler
      containers:
        - name: cluster-autoscaler
          image: registry.k8s.io/autoscaling/cluster-autoscaler:v1.28.0
          command:
            - ./cluster-autoscaler
            - --v=4
            - --stderrthreshold=info
            - --cloud-provider=aws
            - --skip-nodes-with-local-storage=false
            - --expander=least-waste
            - --node-group-auto-discovery=asg:tag=k8s.io/cluster-autoscaler/enabled,k8s.io/cluster-autoscaler/my-cluster
            - --balance-similar-node-groups
            - --skip-nodes-with-system-pods=false
          resources:
            limits:
              cpu: 100m
              memory: 600Mi
            requests:
              cpu: 100m
              memory: 600Mi
          env:
            - name: AWS_REGION
              value: ap-northeast-1
kubectl apply -f cluster-autoscaler.yaml

Step 3:建立 IAM 權限

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "autoscaling:DescribeAutoScalingGroups",
        "autoscaling:DescribeAutoScalingInstances",
        "autoscaling:DescribeLaunchConfigurations",
        "autoscaling:DescribeScalingActivities",
        "autoscaling:DescribeTags",
        "autoscaling:SetDesiredCapacity",
        "autoscaling:TerminateInstanceInAutoScalingGroup",
        "ec2:DescribeLaunchTemplateVersions",
        "ec2:DescribeInstanceTypes"
      ],
      "Resource": "*"
    }
  ]
}

方案四:啟用 VPC CNI Prefix Delegation(進階)

適用場景:

  • 需要在同一個 Node 上運行大量小型 Pod
  • 希望最大化單一 Node 的 Pod 密度
  • Subnet 有足夠的 IP 空間

什麼是 Prefix Delegation?

原本 VPC CNI 是為每個 Pod 分配單一 IP,Prefix Delegation 改為分配一個 /28 的 IP 前綴(16 個 IP)給每個 ENI slot。

比較:

模式每個 ENI slott3.medium Max Pods
傳統模式1 個 IP17
Prefix Delegation16 個 IP (/28)110

啟用步驟:

# Step 1: 更新 VPC CNI 到最新版本
kubectl describe daemonset aws-node -n kube-system | grep Image

# Step 2: 啟用 Prefix Delegation
kubectl set env daemonset aws-node \
  -n kube-system \
  ENABLE_PREFIX_DELEGATION=true

# Step 3: 設定 warm pool(預先分配的 IP prefix 數量)
kubectl set env daemonset aws-node \
  -n kube-system \
  WARM_PREFIX_TARGET=1

# Step 4: 驗證設定
kubectl get ds aws-node -n kube-system -o yaml | grep -A 5 "env:"

注意事項:

⚠️ 重要考量:

  • 需要 VPC CNI 版本 1.9.0 以上
  • 需要 Nitro-based Instance(大多數新型 Instance 都支援)
  • Subnet 需要足夠大的 CIDR(建議至少 /19)
  • 現有 Node 需要 drain 並重新加入

驗證腳本:

#!/bin/bash
# verify-prefix-delegation.sh

echo "檢查 VPC CNI 設定..."

# 檢查 CNI 版本
cni_version=$(kubectl get ds aws-node -n kube-system -o jsonpath='{.spec.template.spec.containers[0].image}' | grep -oP 'v\d+\.\d+\.\d+')
echo "VPC CNI 版本: $cni_version"

# 檢查 Prefix Delegation 狀態
prefix_enabled=$(kubectl get ds aws-node -n kube-system -o jsonpath='{.spec.template.spec.containers[0].env[?(@.name=="ENABLE_PREFIX_DELEGATION")].value}')
echo "Prefix Delegation: ${prefix_enabled:-未啟用}"

# 檢查 Node 的 max-pods
for node in $(kubectl get nodes -o name); do
    node_name=$(echo $node | cut -d'/' -f2)
    max_pods=$(kubectl get $node -o jsonpath='{.status.allocatable.pods}')
    echo "Node $node_name - Max Pods: $max_pods"
done

方案五:使用 AWS Fargate(無伺服器)

適用場景:

  • Stateless 服務
  • 測試環境
  • 不想管理 Node
  • 需要快速擴展

架構比較:

Mermaid Diagram

建立 Fargate Profile:

# fargate-profile.yaml
apiVersion: eksctl.io/v1alpha5
kind: ClusterConfig

metadata:
  name: my-cluster
  region: ap-northeast-1

fargateProfiles:
  - name: fp-default
    selectors:
      # Namespace 選擇器
      - namespace: staging
        labels:
          compute-type: fargate
      - namespace: dev
      # 特定 workload 選擇器
      - namespace: production
        labels:
          workload-type: stateless
eksctl create fargateprofile -f fargate-profile.yaml

將 Pod 部署到 Fargate:

# deployment-fargate.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-app
  namespace: staging    # 匹配 Fargate Profile 的 namespace
spec:
  replicas: 3
  selector:
    matchLabels:
      app: my-app
  template:
    metadata:
      labels:
        app: my-app
        compute-type: fargate    # 匹配 Fargate Profile 的 label
    spec:
      containers:
        - name: app
          image: my-app:latest
          resources:
            requests:
              cpu: "256m"
              memory: "512Mi"
            limits:
              cpu: "512m"
              memory: "1Gi"

Fargate 優缺點分析:

優點缺點
✅ 無需管理 Node❌ 啟動時間較長(30-60 秒)
✅ 按實際使用付費❌ 不支援 DaemonSet
✅ 自動擴展❌ 不支援 GPU
✅ 無 Pod 數量限制❌ 某些 CSI Driver 不支援
✅ 安全隔離(每 Pod 獨立 VM)❌ 無法 SSH 進入 Node
✅ 自動套用安全更新❌ 成本可能較高

快速解法:清理不需要的 Pod

如果你只是臨時需要空間,最快的方法是找出並刪除不必要的 Pod:

# 查看所有 Pod 的資源使用狀況(按 memory 排序)
kubectl top pods -A --sort-by=memory

# 查看所有 Pod(按啟動時間排序)
kubectl get pods -A -o wide --sort-by='.status.startTime'

# 找出長時間運行的 Pod
kubectl get pods -A -o custom-columns=\
NAMESPACE:.metadata.namespace,\
NAME:.metadata.name,\
STATUS:.status.phase,\
AGE:.metadata.creationTimestamp \
--sort-by='.metadata.creationTimestamp'

# 刪除特定 Pod(如果有 Deployment,會自動重建)
kubectl delete pod <pod-name> -n <namespace>

# 完全移除一個服務
kubectl delete deployment <deployment-name> -n <namespace>

# 檢查是否有 Completed 或 Failed 的 Pod 可以清理
kubectl get pods -A | grep -E 'Completed|Error|Failed'
kubectl delete pods -A --field-selector=status.phase==Succeeded
kubectl delete pods -A --field-selector=status.phase==Failed

我的情況: 刪除了一個用於測試的 debug Pod,Strapi 就成功啟動了。

(經過三小時的 debug 和兩杯咖啡的犧牲,問題終於解決。)


預防措施:監控 Pod 容量

建立 CloudWatch 告警

# 使用 AWS CLI 建立告警
aws cloudwatch put-metric-alarm \
  --alarm-name "EKS-Pod-Capacity-Warning" \
  --alarm-description "Pod capacity usage exceeds 80%" \
  --metric-name "pod_count" \
  --namespace "ContainerInsights" \
  --dimensions Name=ClusterName,Value=my-cluster \
  --statistic Average \
  --period 300 \
  --threshold 80 \
  --comparison-operator GreaterThanThreshold \
  --evaluation-periods 2 \
  --alarm-actions arn:aws:sns:ap-northeast-1:123456789012:alerts

使用 Prometheus 監控

# prometheus-rules.yaml
apiVersion: monitoring.coreos.com/v1
kind: PrometheusRule
metadata:
  name: pod-capacity-alerts
  namespace: monitoring
spec:
  groups:
    - name: pod-capacity
      rules:
        - alert: HighPodUtilization
          expr: |
            sum(kube_pod_status_phase{phase="Running"}) by (node)
            /
            sum(kube_node_status_allocatable{resource="pods"}) by (node)
            > 0.8
          for: 5m
          labels:
            severity: warning
          annotations:
            summary: "Node {{ $labels.node }} Pod 使用率超過 80%"
            description: "Node {{ $labels.node }} 的 Pod 使用率已達 {{ $value | humanizePercentage }},請考慮擴展。"

        - alert: CriticalPodUtilization
          expr: |
            sum(kube_pod_status_phase{phase="Running"}) by (node)
            /
            sum(kube_node_status_allocatable{resource="pods"}) by (node)
            > 0.95
          for: 2m
          labels:
            severity: critical
          annotations:
            summary: "Node {{ $labels.node }} Pod 容量即將耗盡!"
            description: "Node {{ $labels.node }} 的 Pod 使用率已達 {{ $value | humanizePercentage }},可能導致新 Pod 無法排程。"

定期檢查腳本(加入 cron job)

#!/bin/bash
# /usr/local/bin/check-pod-capacity.sh

LOG_FILE="/var/log/pod-capacity-check.log"
SLACK_WEBHOOK="https://hooks.slack.com/services/xxx/yyy/zzz"

echo "$(date): Starting pod capacity check" >> $LOG_FILE

WARNING_NODES=""

for node in $(kubectl get nodes -o name); do
    node_name=$(echo $node | cut -d'/' -f2)
    max_pods=$(kubectl get $node -o jsonpath='{.status.allocatable.pods}')
    current_pods=$(kubectl get pods -A --field-selector spec.nodeName=$node_name --no-headers | wc -l)

    if [ "$max_pods" -gt 0 ]; then
        usage=$((current_pods * 100 / max_pods))

        if [ $usage -ge 80 ]; then
            WARNING_NODES="$WARNING_NODES\n- $node_name: ${usage}% ($current_pods/$max_pods)"
        fi
    fi
done

if [ -n "$WARNING_NODES" ]; then
    # 發送 Slack 通知
    curl -X POST -H 'Content-type: application/json' \
        --data "{\"text\":\"⚠️ EKS Pod Capacity Warning\n\nThe following nodes have high pod utilization:$WARNING_NODES\"}" \
        $SLACK_WEBHOOK

    echo "$(date): Warning sent for nodes:$WARNING_NODES" >> $LOG_FILE
fi

echo "$(date): Check completed" >> $LOG_FILE
# 加入 crontab,每 15 分鐘檢查一次
*/15 * * * * /usr/local/bin/check-pod-capacity.sh

架構規劃建議

經過這次踩坑,我總結了幾個 EKS 架構規劃的重點:

1. 依環境分離 Node Group

Mermaid Diagram

2. 選擇適當的 Instance 類型

用途建議 Instance原因
System Podst3.small / t3.medium系統元件數量固定,不需太大
Productionm5.large / m5.xlarge平衡的 CPU/Memory,足夠的 Pod 容量
CPU 密集c5.large / c5.xlarge高 CPU 配置
Memory 密集r5.large / r5.xlarge高 Memory 配置
開發測試t3.medium成本較低,足夠測試用途

3. 規劃足夠的 VPC CIDR

如果計劃使用 Prefix Delegation,確保 Subnet 有足夠的 IP 空間:

建議規劃:
├─ VPC CIDR: /16(65,536 個 IP)
├─ 每個 AZ 的 Subnet: /19(8,192 個 IP)
└─ 預留給 Pod 的空間: 至少 /20 per AZ

結語:EKS Pod 限制的真相

這次經驗讓我深刻體會到,EKS 的「Pod 數限制」是一個經常被誤解的概念:

📌 記住:EKS 上 Pod 數上限 ≠ CPU/Memory 限制,而是 ENI + IP 的網路限制!

當你看到「Too many pods」錯誤時,不要急著加 CPU 或 Memory,而是要:

  1. 檢查 Instance 類型的 ENI/IP 限制
  2. 評估是否需要升級 Instance 或增加 Node
  3. 考慮啟用 Prefix Delegation 或使用 Fargate
  4. 建立監控機制,提早發現問題

希望這篇文章能幫你省下我花掉的那三小時。至於那兩杯咖啡的錢,就當作是我請你的。☕


參考資源