深色模式
AWS EKS 实战
面向需要在 AWS 上落地生产 EKS 的工程师。覆盖托管架构、IRSA 权限、VPC CNI、存储与 Ingress、Addon 与排障。
厂商特定
本文全部内容依赖 AWS EKS 的特定实现(IAM、ENI/IP 分配、EBS CSI、ALB)。跨云不适用,其他云请看同目录下 ACK / TKE 篇。
适用版本与前提
- EKS:托管控制面(
[版本相关],EKS 版本跟随上游 K8s 并有独立的生命周期终止日期) - 前提:AWS 账号、VPC、有权限创建 IAM 与 EKS 资源
背景与问题
EKS 帮你托管控制面(kube-apiserver、etcd、scheduler 等),你负责数据面(节点、网络插件、存储驱动、Ingress)。这种分工带来的好处与坑都源于同一个事实:控制面不可见、不可改。
- 好处:不用运维 etcd 与 apiserver 高可用。
- 坑:很多"改 apiserver 启动参数"类调优手段不可用;排障时看不到控制面日志(需开启控制面日志)。
核心概念
| 概念 | 说明 |
|---|---|
| EKS 控制面 | AWS 托管,跨 AZ 部署,按小时计费,对你只有一个 endpoint |
| 节点组 | Managed Node Group(AWS 托管节点生命周期)/ Self-managed / Fargate(无节点) |
| IRSA | IAM Roles for Service Accounts,用 OIDC 把 IAM 角色绑到 K8s ServiceAccount |
| VPC CNI | 默认 CNI,Pod 直接使用 VPC 的 ENI 次级 IP |
| EKS Addons | AWS 托管的集群插件(CoreDNS、kube-proxy、VPC CNI、EBS CSI 等) |
| AWS Load Balancer Controller | 把 Service/Ingress 映射为 ALB/NLB |
架构与原理
关键点:Pod 直接拿 VPC IP(VPC CNI 默认行为)。好处是网络简单、可直接被 VPC 内其他资源访问;代价是 IP 消耗快,一个节点的 Pod 数上限受 ENI 数与每 ENI 的 IP 数限制。
生产实践
1. 创建集群(eksctl)
bash
# 创建集群(示例;生产建议用 IaC 如 OpenTofu/CDK 固化)
eksctl create cluster \
--name prod-cluster \
--region ap-southeast-1 \
--version 1.29 \
--nodegroup-name general \
--nodes 3 --nodes-min 3 --nodes-max 10 \
--managed
# 验证
aws eks describe-cluster --name prod-cluster --query 'cluster.status'
kubectl get nodes1
2
3
4
5
6
7
8
9
10
11
12
2
3
4
5
6
7
8
9
10
11
12
建议
生产环境必须跨至少 2~3 个 AZ 部署节点,并把 Pod 用
topologySpreadConstraints打散,否则单 AZ 故障即全站故障。
2. IRSA:把 IAM 权限给到 Pod
先在集群启用 IAM OIDC Provider:
bash
eksctl utils associate-iam-oidc-provider --cluster prod-cluster --approve1
创建 IAM 角色并绑定到 ServiceAccount:
bash
eksctl create iamserviceaccount \
--cluster prod-cluster \
--namespace prod \
--name app-sa \
--attach-policy-arn arn:aws:iam::123456789012:policy/app-s3-policy \
--approve1
2
3
4
5
6
2
3
4
5
6
yaml
apiVersion: v1
kind: ServiceAccount
metadata:
name: app-sa
namespace: prod
annotations:
eks.amazonaws.com/role-arn: arn:aws:iam::123456789012:role/eksctl-prod-cluster-iamserviceaccount-Role
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: app
namespace: prod
spec:
template:
spec:
serviceAccountName: app-sa # 关键:绑定 SA
containers:
- name: app
image: 123456789012.dkr.ecr.ap-southeast-1.amazonaws.com/app:1.8.01
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
生产危险
严禁为图省事给节点实例角色(
NodeInstanceRole)附加过宽泛的策略——那样该节点上所有 Pod都会获得这些权限。权限必须下沉到 IRSA。
3. 用 Addon 管理核心插件
bash
# 查看可用 addon 及版本
aws eks describe-addon-versions --kubernetes-version 1.29
# 安装/更新 EBS CSI(有状态服务必需)
eksctl create addon --name aws-ebs-csi-driver --cluster prod-cluster1
2
3
4
5
2
3
4
5
yaml
# 默认 StorageClass(gp3)
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: ebs-gp3
annotations:
storageclass.kubernetes.io/is-default-class: "true"
provisioner: ebs.csi.aws.com
parameters:
type: gp3
encrypted: "true"
volumeBindingMode: WaitForFirstConsumer
reclaimPolicy: Delete1
2
3
4
5
6
7
8
9
10
11
12
13
2
3
4
5
6
7
8
9
10
11
12
13
版本相关
in-tree 的
kubernetes.io/aws-ebs供应器已随 CSI 迁移废弃,新的卷必须使用ebs.csi.aws.com。迁移存量卷需额外处理。
4. Ingress 用 AWS Load Balancer Controller
yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: web
namespace: prod
annotations:
kubernetes.io/ingress.class: alb
alb.ingress.kubernetes.io/scheme: internet-facing
alb.ingress.kubernetes.io/target-type: ip
spec:
rules:
- http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: web
port:
number: 801
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
注意
target-type: ip直接把 Pod IP 注册到 ALB(配合 VPC CNI),性能好;instance模式走 NodePort,多一跳。选择前确认 Pod IP 数量不会超出 ALB 目标组限制。
验证
bash
kubectl get nodes -o wide
kubectl get pods -n kube-system
aws eks describe-cluster --name prod-cluster --query 'cluster.{version:version,status:status,endpoint:endpoint}'
kubectl -n prod get ingress web -o jsonpath='{.status.loadBalancer.ingress[0].hostname}'1
2
3
4
2
3
4
回滚与清理
bash
# 插件升级失败可回退版本
aws eks describe-addon --cluster-name prod-cluster --addon-name aws-ebs-csi-driver
aws eks update-addon --cluster-name prod-cluster --addon-name aws-ebs-csi-driver --addon-version <prev>
# 删除集群(会连带删除节点组)[危险]
eksctl delete cluster --name prod-cluster1
2
3
4
5
6
2
3
4
5
6
生产危险
删除集群前必须确认:EBS 卷(含 PV 数据)是否已备份/是否会随删除策略被回收、ALB 是否残留、IAM 角色是否需清理。
故障排查
| 现象 | 定位 |
|---|---|
| 节点加不进集群 | 检查节点 IAM 角色、子网路由(需能到 EKS endpoint)、安全组、aws-auth/EKS 访问条目 |
| Pod 一直 Pending(IP 不足) | VPC CNI IP 耗尽:检查子网可用 IP、调 WARM_ENI_TARGET/启用前缀委派 |
| PVC 一直 Pending | EBS CSI 未安装或 IRSA 权限不足:kubectl describe pvc 看事件 |
| Ingress 不生成 ALB | AWS LB Controller 日志、子网标签(kubernetes.io/role/elb) |
kubectl 连不上 | kubeconfig 过期/权限变更:aws eks update-kubeconfig |
bash
kubectl logs -n kube-system deployment/aws-load-balancer-controller
kubectl logs -n kube-system daemonset/aws-node # VPC CNI
kubectl describe pvc <pvc> -n prod1
2
3
2
3
开启控制面日志(托管控制面看不到进程,只能靠日志):
bash
aws eks update-cluster-config --name prod-cluster --logging '{"clusterLogging":[{"types":["api","audit","authenticator","controllerManager","scheduler"],"enabled":true}]}'1
安全与合规
- 集群 endpoint 访问:生产建议限制公网访问或启用访问控制列表。
- 启用 EKS 加密(KMS 加密 secrets)。
- 用 EKS 访问条目(Access Entries)或
aws-auth精细控制谁有cluster-admin。 - 审计 IAM:
eksctl create iamserviceaccount会创建 IAM 资源,需纳入 IaC 与审计。
性能、容量与成本
- 控制面按小时计费 + 节点按 EC2 计费,跨 AZ 流量会产生额外费用。
- Fargate 免运维节点但单价通常更高、功能受限(如不支持 DaemonSet 的某些形态)
[未实测]。 - VPC CNI 的 IP 消耗是大规模集群的主要容量约束,需提前规划子网 CIDR。
参考资料
- Amazon EKS 用户指南,访问日期:2026-10-09。
- AWS Load Balancer Controller 文档,访问日期:2026-10-09。
- Amazon EBS CSI Driver 文档,访问日期:2026-10-09。
- IRSA 文档,访问日期:2026-10-09。