EKS 节点组管理
节点组类型
Managed Node Groups(推荐)
什么是 Managed Node Groups:
特点:
├─ AWS 完全托管节点生命周期
├─ 自动化的节点更新和打补丁
├─ 基于 Auto Scaling Groups
├─ 集成 EKS 控制平面
├─ 一键创建和管理
└─ 自动注册到集群
管理的内容:
├─ EC2 实例创建和终止
├─ Auto Scaling Group 配置
├─ 节点健康检查
├─ 滚动更新
├─ AMI 自动更新
└─ 集群加入配置
用户控制的内容:
├─ 实例类型选择
├─ 磁盘大小
├─ SSH 密钥
├─ 标签和污点
├─ 启动模板
└─ 扩展策略
节点组网络配置
子网选择(重要):
推荐配置:
├─ 节点组使用 3 个私有子网
│ ├─ us-east-1a: 10.0.11.0/24
│ ├─ us-east-1b: 10.0.12.0/24
│ └─ us-east-1c: 10.0.13.0/24
│
├─ 节点部署在私有子网的优势:
│ ├─ 无公网 IP,安全性更高
│ ├─ 通过 NAT Gateway 访问互联网
│ ├─ 内部服务间直接通信
│ └─ 符合企业安全要求
│
└─ 出站流量路径:
├─ 节点 → NAT Gateway → Internet Gateway → 互联网
├─ 用于:拉取镜像、下载包、API 调用
└─ 每个 AZ 独立 NAT Gateway(高可用)
为什么不使用公有子网:
├─ 节点直接暴露公网(安全风险)
├─ 需要分配公网 IP(成本增加)
├─ 不符合企业安全策略
└─ 增加攻击面
节点实例类型选择
实例类型分类
按用途分类:
1. 通用型(推荐大多数场景)
t3 系列(突发性能):
├─ t3.medium:2 vCPU, 4GB RAM, 最多 17 Pod
├─ t3.large:2 vCPU, 8GB RAM, 最多 35 Pod
└─ t3.xlarge:4 vCPU, 16GB RAM, 最多 58 Pod
m5 系列(平衡型):
├─ m5.large:2 vCPU, 8GB RAM, 最多 29 Pod
├─ m5.xlarge:4 vCPU, 16GB RAM, 最多 58 Pod
└─ m5.2xlarge:8 vCPU, 32GB RAM, 最多 58 Pod
适用场景:
├─ Web 应用
├─ 微服务
├─ 开发/测试环境
└─ 混合工作负载
2. 计算优化型
c5 系列:
├─ c5.large:2 vCPU, 4GB RAM, 最多 29 Pod
├─ c5.xlarge:4 vCPU, 8GB RAM, 最多 58 Pod
└─ c5.2xlarge:8 vCPU, 16GB RAM, 最多 58 Pod
适用场景:
├─ CPU 密集型应用
├─ 批处理
├─ 科学计算
└─ 游戏服务器
3. 内存优化型
r5 系列:
├─ r5.large:2 vCPU, 16GB RAM, 最多 29 Pod
├─ r5.xlarge:4 vCPU, 32GB RAM, 最多 58 Pod
└─ r5.2xlarge:8 vCPU, 64GB RAM, 最多 58 Pod
适用场景:
├─ 缓存
├─ 内存数据库
├─ 大数据分析
└─ 实时处理
4. 存储优化型
i3 系列(NVMe SSD):
├─ i3.large:2 vCPU, 15GB RAM, 475GB NVMe
└─ i3.xlarge:4 vCPU, 30GB RAM, 950GB NVMe
适用场景:
├─ 数据库
├─ NoSQL
├─ 高 IOPS 需求
└─ 日志处理
5. GPU 加速型
p3 系列(深度学习):
├─ p3.2xlarge:8 vCPU, 61GB RAM, 1x V100
└─ p3.8xlarge:32 vCPU, 244GB RAM, 4x V100
g4 系列(图形渲染):
├─ g4dn.xlarge:4 vCPU, 16GB RAM, 1x T4
└─ g4dn.2xlarge:8 vCPU, 32GB RAM, 1x T4
实例选型决策树
如何选择实例类型:
问题 1:预算如何?
├─ 预算紧张 → t3 系列(突发性能,性价比高)
└─ 预算充足 → 继续
问题 2:主要负载类型?
├─ Web/API 服务 → m5 系列(通用平衡)
├─ CPU 密集 → c5 系列(计算优化)
├─ 内存密集 → r5 系列(内存优化)
├─ 存储密集 → i3 系列(NVMe SSD)
└─ GPU 加速 → p3/g4 系列
问题 3:Pod 密度需求?
├─ 高密度(>30 Pod/节点)→ xlarge 及以上
├─ 中密度(15-30 Pod)→ large
└─ 低密度(<15 Pod)→ medium
问题 4:可用性要求?
├─ 高可用(99.95%+)→ On-Demand
├─ 成本优先(可中断)→ Spot
└─ 混合(推荐)→ 70% On-Demand + 30% Spot
推荐配置示例:
├─ 小型集群:3-6x t3.large
├─ 中型集群:6-12x m5.xlarge
├─ 大型集群:12-30x m5.2xlarge
└─ 混合:基线 On-Demand + 弹性 Spot
每种实例类型的 Pod 数量
ENI 和 IP 限制:
实例类型 ENI数 每ENI IP数 最大Pod数
─────────────────────────────────────
t3.medium 3 6 17
t3.large 3 12 35
t3.xlarge 4 15 58
t3.2xlarge 4 15 58
m5.large 3 10 29
m5.xlarge 4 15 58
m5.2xlarge 4 15 58
m5.4xlarge 8 30 234
c5.large 3 10 29
c5.xlarge 4 15 58
c5.2xlarge 4 15 58
r5.large 3 10 29
r5.xlarge 4 15 58
r5.2xlarge 4 15 58
公式:
最大 Pod 数 = (ENI 数 × 每 ENI IP 数) - ENI 数 + 2
说明:
├─ 每个节点保留一些 IP 用于节点本身
├─ -ENI 数:每个 ENI 占用一个主 IP
├─ +2:额外的 Pod 地址池
└─ 实际可用 Pod 数略少于理论值
实战:创建节点组
单节点组配置
#!/bin/bash
# create-node-group.sh
set -e
source eks-vpc-config.env
NODE_GROUP_NAME="general-nodes"
INSTANCE_TYPES=("t3.large" "t3.xlarge")
DISK_SIZE=50
MIN_SIZE=3
MAX_SIZE=10
DESIRED_SIZE=6
echo "================================================"
echo "创建 EKS Managed Node Group"
echo "================================================"
# 1. 创建节点组
echo "1. 创建节点组:$NODE_GROUP_NAME"
aws eks create-nodegroup \
--cluster-name $CLUSTER_NAME \
--nodegroup-name $NODE_GROUP_NAME \
--scaling-config \
minSize=$MIN_SIZE,\
maxSize=$MAX_SIZE,\
desiredSize=$DESIRED_SIZE \
--disk-size $DISK_SIZE \
--subnets ${PRIVATE_SUBNET_IDS[0]} ${PRIVATE_SUBNET_IDS[1]} ${PRIVATE_SUBNET_IDS[2]} \
--instance-types ${INSTANCE_TYPES[0]} ${INSTANCE_TYPES[1]} \
--ami-type AL2_x86_64 \
--node-role $EKS_NODE_ROLE_ARN \
--labels \
role=general,\
environment=production,\
nodegroup=$NODE_GROUP_NAME \
--tags \
Name=$NODE_GROUP_NAME,\
Environment=production,\
ManagedBy=eks \
--capacity-type ON_DEMAND \
--update-config maxUnavailable=1 \
--region $REGION
echo " ✓ 节点组创建请求已提交"
echo " ⏳ 等待节点组创建完成(约 5-10 分钟)..."
# 2. 等待节点组就绪
aws eks wait nodegroup-active \
--cluster-name $CLUSTER_NAME \
--nodegroup-name $NODE_GROUP_NAME \
--region $REGION
echo " ✓ 节点组已就绪"
# 3. 验证节点
echo ""
echo "2. 验证节点..."
kubectl get nodes -o wide
kubectl get nodes -o json | jq -r '.items[] | "\(.metadata.name): \(.status.nodeInfo.instanceType), \(.status.capacity.pods) max pods"'
echo ""
echo "================================================"
echo "节点组创建完成!"
echo "================================================"
echo "节点组名称:$NODE_GROUP_NAME"
echo "实例类型:${INSTANCE_TYPES[@]}"
echo "节点数量:$DESIRED_SIZE (最小 $MIN_SIZE, 最大 $MAX_SIZE)"
echo "磁盘大小:${DISK_SIZE}GB"
echo "子网:私有子网(3个 AZ)"
echo "出站流量:通过 NAT Gateway"
echo "================================================"
多节点组配置(生产推荐)
#!/bin/bash
# create-multiple-node-groups.sh
set -e
source eks-vpc-config.env
echo "================================================"
echo "创建多个 EKS 节点组"
echo "================================================"
# 1. 通用型节点组(On-Demand)
echo "1. 创建通用型节点组(On-Demand)..."
aws eks create-nodegroup \
--cluster-name $CLUSTER_NAME \
--nodegroup-name general-on-demand \
--scaling-config minSize=3,maxSize=10,desiredSize=6 \
--disk-size 50 \
--subnets ${PRIVATE_SUBNET_IDS[0]} ${PRIVATE_SUBNET_IDS[1]} ${PRIVATE_SUBNET_IDS[2]} \
--instance-types t3.large m5.large \
--ami-type AL2_x86_64 \
--node-role $EKS_NODE_ROLE_ARN \
--labels \
role=general,\
capacity-type=on-demand \
--tags \
Name=general-on-demand,\
CostCenter=baseline \
--capacity-type ON_DEMAND \
--update-config maxUnavailable=1 \
--region $REGION
echo " ✓ 通用型节点组创建完成"
# 2. Spot 实例节点组(成本优化)
echo ""
echo "2. 创建 Spot 实例节点组..."
aws eks create-nodegroup \
--cluster-name $CLUSTER_NAME \
--nodegroup-name general-spot \
--scaling-config minSize=0,maxSize=20,desiredSize=3 \
--disk-size 50 \
--subnets ${PRIVATE_SUBNET_IDS[0]} ${PRIVATE_SUBNET_IDS[1]} ${PRIVATE_SUBNET_IDS[2]} \
--instance-types t3.large t3.xlarge m5.large m5.xlarge \
--ami-type AL2_x86_64 \
--node-role $EKS_NODE_ROLE_ARN \
--labels \
role=general,\
capacity-type=spot \
--taints \
key=spot,value=true,effect=NoSchedule \
--tags \
Name=general-spot,\
CostCenter=flexible \
--capacity-type SPOT \
--update-config maxUnavailable=1 \
--region $REGION
echo " ✓ Spot 节点组创建完成"
# 3. 计算密集型节点组
echo ""
echo "3. 创建计算密集型节点组..."
aws eks create-nodegroup \
--cluster-name $CLUSTER_NAME \
--nodegroup-name compute-intensive \
--scaling-config minSize=0,maxSize=10,desiredSize=2 \
--disk-size 100 \
--subnets ${PRIVATE_SUBNET_IDS[0]} ${PRIVATE_SUBNET_IDS[1]} ${PRIVATE_SUBNET_IDS[2]} \
--instance-types c5.xlarge c5.2xlarge \
--ami-type AL2_x86_64 \
--node-role $EKS_NODE_ROLE_ARN \
--labels \
role=compute,\
capacity-type=on-demand \
--taints \
key=compute-intensive,value=true,effect=NoSchedule \
--tags \
Name=compute-intensive,\
Workload=cpu-bound \
--capacity-type ON_DEMAND \
--update-config maxUnavailable=1 \
--region $REGION
echo " ✓ 计算密集型节点组创建完成"
# 4. 等待所有节点组就绪
echo ""
echo "4. 等待所有节点组就绪..."
aws eks wait nodegroup-active \
--cluster-name $CLUSTER_NAME \
--nodegroup-name general-on-demand \
--region $REGION &
aws eks wait nodegroup-active \
--cluster-name $CLUSTER_NAME \
--nodegroup-name general-spot \
--region $REGION &
aws eks wait nodegroup-active \
--cluster-name $CLUSTER_NAME \
--nodegroup-name compute-intensive \
--region $REGION &
wait
echo " ✓ 所有节点组已就绪"
# 5. 验证节点
echo ""
echo "5. 验证所有节点..."
kubectl get nodes -L role,capacity-type -o wide
echo ""
echo "================================================"
echo "多节点组创建完成!"
echo "================================================"
echo ""
echo "节点组配置:"
echo " 1. general-on-demand: 基线工作负载(3-10 节点)"
echo " 2. general-spot: 弹性工作负载(0-20 节点,节省 70%)"
echo " 3. compute-intensive: CPU 密集型(0-10 节点)"
echo ""
echo "所有节点组使用私有子网:"
echo " - 10.0.11.0/24 (AZ-A)"
echo " - 10.0.12.0/24 (AZ-B)"
echo " - 10.0.13.0/24 (AZ-C)"
echo ""
echo "出站流量通过 NAT Gateway"
echo "================================================"
使用启动模板(高级配置)
#!/bin/bash
# create-node-group-with-launch-template.sh
set -e
source eks-vpc-config.env
echo "================================================"
echo "使用启动模板创建节点组"
echo "================================================"
# 1. 创建启动模板
echo "1. 创建 EC2 启动模板..."
# 用户数据脚本(自定义节点初始化)
cat > userdata.sh << 'EOF'
#!/bin/bash
set -o xtrace
# 配置节点标签
/etc/eks/bootstrap.sh ${CLUSTER_NAME} \
--kubelet-extra-args '--node-labels=custom=true,environment=production'
# 自定义配置
echo "vm.max_map_count=262144" >> /etc/sysctl.conf
sysctl -p
# 安装额外工具
yum install -y amazon-ssm-agent
systemctl enable amazon-ssm-agent
systemctl start amazon-ssm-agent
EOF
# 创建启动模板
LT_ID=$(aws ec2 create-launch-template \
--launch-template-name eks-custom-node-template \
--launch-template-data '{
"BlockDeviceMappings": [{
"DeviceName": "/dev/xvda",
"Ebs": {
"VolumeSize": 100,
"VolumeType": "gp3",
"Iops": 3000,
"Throughput": 125,
"DeleteOnTermination": true,
"Encrypted": true
}
}],
"MetadataOptions": {
"HttpTokens": "required",
"HttpPutResponseHopLimit": 2
},
"TagSpecifications": [{
"ResourceType": "instance",
"Tags": [
{"Key": "Name", "Value": "eks-custom-node"},
{"Key": "ManagedBy", "Value": "launch-template"}
]
}],
"UserData": "'$(base64 -w 0 userdata.sh)'"
}' \
--region $REGION \
--query 'LaunchTemplate.LaunchTemplateId' \
--output text)
echo " ✓ 启动模板 ID: $LT_ID"
# 2. 使用启动模板创建节点组
echo ""
echo "2. 创建节点组(使用启动模板)..."
aws eks create-nodegroup \
--cluster-name $CLUSTER_NAME \
--nodegroup-name custom-nodes \
--scaling-config minSize=2,maxSize=8,desiredSize=4 \
--subnets ${PRIVATE_SUBNET_IDS[0]} ${PRIVATE_SUBNET_IDS[1]} ${PRIVATE_SUBNET_IDS[2]} \
--node-role $EKS_NODE_ROLE_ARN \
--launch-template id=$LT_ID,version='$Latest' \
--labels \
custom=true,\
template=enabled \
--tags \
Name=custom-nodes \
--update-config maxUnavailable=1 \
--region $REGION
echo " ✓ 节点组创建完成"
# 等待就绪
aws eks wait nodegroup-active \
--cluster-name $CLUSTER_NAME \
--nodegroup-name custom-nodes \
--region $REGION
rm -f userdata.sh
echo ""
echo "================================================"
echo "自定义节点组创建完成!"
echo "使用了启动模板进行高级配置"
echo "================================================"
节点组更新和维护
更新节点组
#!/bin/bash
# update-node-group.sh
set -e
source eks-vpc-config.env
NODE_GROUP_NAME="general-on-demand"
echo "================================================"
echo "更新节点组"
echo "================================================"
# 1. 更新节点数量
echo "1. 更新节点数量..."
aws eks update-nodegroup-config \
--cluster-name $CLUSTER_NAME \
--nodegroup-name $NODE_GROUP_NAME \
--scaling-config minSize=4,maxSize=15,desiredSize=8 \
--region $REGION
# 2. 更新标签
echo ""
echo "2. 更新标签..."
aws eks update-nodegroup-config \
--cluster-name $CLUSTER_NAME \
--nodegroup-name $NODE_GROUP_NAME \
--labels addOrUpdateLabels={version=v1.28,updated=true} \
--region $REGION
# 3. 更新 AMI(滚动更新)
echo ""
echo "3. 触发滚动更新(更新 AMI)..."
aws eks update-nodegroup-version \
--cluster-name $CLUSTER_NAME \
--nodegroup-name $NODE_GROUP_NAME \
--region $REGION
echo ""
echo "================================================"
echo "节点组更新已触发"
echo "更新过程:逐个替换节点(滚动更新)"
echo "================================================"
# 4. 监控更新进度
echo ""
echo "4. 监控更新进度..."
while true; do
STATUS=$(aws eks describe-nodegroup \
--cluster-name $CLUSTER_NAME \
--nodegroup-name $NODE_GROUP_NAME \
--region $REGION \
--query 'nodegroup.status' \
--output text)
if [ "$STATUS" == "ACTIVE" ]; then
echo " ✓ 更新完成"
break
elif [ "$STATUS" == "UPDATING" ]; then
echo " ⏳ 更新中... ($(date '+%H:%M:%S'))"
sleep 30
else
echo " ⚠️ 状态异常: $STATUS"
break
fi
done
节点耗尽和维护
#!/bin/bash
# drain-and-maintain-node.sh
# 1. 标记节点不可调度
echo "标记节点不可调度..."
kubectl cordon ip-10-0-11-100.ec2.internal
# 2. 耗尽节点(驱逐 Pod)
echo "耗尽节点..."
kubectl drain ip-10-0-11-100.ec2.internal \
--ignore-daemonsets \
--delete-emptydir-data \
--force \
--grace-period=120
# 3. 执行维护操作
echo "执行维护..."
# 例如:重启节点、更新配置等
# 4. 恢复节点调度
echo "恢复节点调度..."
kubectl uncordon ip-10-0-11-100.ec2.internal
节点组最佳实践
推荐配置
生产环境节点组配置:
├─ 基线节点组(On-Demand)
│ ├─ 实例类型:m5.large 或 t3.large
│ ├─ 数量:min=3, desired=6, max=10
│ ├─ 子网:3个私有子网
│ ├─ 用途:关键工作负载
│ └─ 成本:稳定可预测
│
├─ 弹性节点组(Spot)
│ ├─ 实例类型:多种混合(提高可用性)
│ ├─ 数量:min=0, desired=3, max=20
│ ├─ 子网:3个私有子网
│ ├─ 污点:spot=true:NoSchedule
│ ├─ 用途:无状态、可中断工作负载
│ └─ 成本:节省 70%
│
└─ 专用节点组(可选)
├─ 实例类型:根据需求(c5/r5/i3)
├─ 数量:按需配置
├─ 子网:3个私有子网
├─ 污点:专用标记
├─ 用途:特殊工作负载
└─ 成本:优化配置
网络配置:
✅ 所有节点组使用私有子网
✅ 每个 AZ 独立 NAT Gateway
✅ 跨 AZ 均匀分布节点
✅ 合理规划 IP 地址空间
✅ 使用 VPC Endpoints 降低成本
安全配置:
✅ 使用 IAM 角色(不要硬编码凭证)
✅ 启用 IMDSv2(元数据服务)
✅ 最小权限原则
✅ 定期更新 AMI
✅ 配置 Pod Security Standards
扩展配置:
✅ 配置 Cluster Autoscaler
✅ 设置合理的最小/最大值
✅ 配置 Pod Disruption Budgets
✅ 使用多实例类型(Spot)
✅ 监控节点利用率
成本优化:
✅ 混合 On-Demand 和 Spot
✅ 使用 Savings Plans
✅ 右调优实例类型
✅ 监控未使用资源
✅ 定期清理僵尸资源
节点组管理完成,下一步配置网络和存储!