1. 为什么选择EKS部署Kubernetes集群
在容器编排领域摸爬滚打多年,我见证过各种K8s部署方式的优缺点。当团队需要生产级Kubernetes服务时,Amazon Elastic Kubernetes Service(EKS)往往是最稳妥的选择。与自建集群相比,EKS免除了控制平面(Control Plane)的运维负担,AWS会负责etcd、API Server等核心组件的可用性保障。实测下来,控制平面的SLA能达到99.95%,这对需要24/7稳定运行的服务至关重要。
最近帮一个电商客户从自托管集群迁移到EKS,最直观的感受是:再也不用半夜被control plane故障的告警吵醒了。EKS的另一个优势是与AWS其他服务(如ALB、RDS、IAM)的深度集成,通过几个配置就能实现服务发现、权限控制和流量管理。比如用ALB Ingress Controller暴露服务,比自建Nginx Ingress省心不少。
2. 前期准备与环境配置
2.1 账号与权限规划
在控制台点击创建按钮前,需要做好这些准备:
- IAM权限:确保操作账号有EKS相关权限,建议附加
AmazonEKSClusterPolicy和AmazonEKSServicePolicy。生产环境推荐创建专属IAM Role,遵循最小权限原则。 - VPC网络:准备好至少2个AZ的私有子网(建议/19以上CIDR块),EKS会将worker节点部署在这些子网。注意避免与现有服务的IP段冲突。
- EC2密钥对:用于SSH登录worker节点排查问题(虽然不推荐生产环境直接SSH,但调试时很有用)。
重要提示:EKS集群创建后无法修改VPC配置,务必提前规划好网络拓扑。曾经有客户因IP地址不足导致集群无法扩容,只能重建。
2.2 工具链安装
本地环境需要这些工具(以MacOS为例):
bash复制# AWS CLI v2(必须)
brew install awscli
aws --version # 确认≥2.7.0
# eksctl(官方管理工具)
brew tap weaveworks/tap
brew install weaveworks/tap/eksctl
# kubectl(版本需匹配EKS)
brew install kubectl
kubectl version --client
3. 集群创建实战步骤
3.1 通过eksctl快速部署
这是我最推荐的创建方式,eksctl会自动处理很多底层配置:
bash复制eksctl create cluster \
--name production-cluster \
--version 1.27 \
--region ap-northeast-1 \
--nodegroup-name linux-nodes \
--node-type t3.large \
--nodes 3 \
--nodes-min 1 \
--nodes-max 5 \
--ssh-access \
--ssh-public-key my-keypair \
--managed
关键参数解析:
--version:指定K8s版本,建议选择EKS支持的最新稳定版--node-type:根据负载选择,内存型应用选r系列,计算密集型选c系列--managed:使用AWS托管节点组,自动处理节点更新和扩缩容
3.2 验证集群状态
创建完成后(通常需要10-15分钟),检查组件健康状态:
bash复制aws eks describe-cluster --name production-cluster --query "cluster.status"
kubectl get nodes # 应显示3个Ready状态的节点
kubectl -n kube-system get pods # 检查CoreDNS等系统Pod
3.3 配置kubectl凭证
EKS使用IAM进行认证,需要更新kubeconfig:
bash复制aws eks update-kubeconfig --name production-cluster --region ap-northeast-1
4. 关键组件与生产级配置
4.1 网络插件选择
EKS默认安装的VPC CNI插件负责Pod网络,但需要特别注意:
- ENI限制:每个EC2实例可挂载的ENI数量有限(如t3.large是3个),这会直接影响节点能运行的Pod数量
- 自定义配置:通过DaemonSet修改
aws-node的配置:yaml复制env: - name: AWS_VPC_K8S_CNI_CUSTOM_NETWORK_CFG value: "true" - name: ENI_CONFIG_LABEL_DEF value: "failure-domain.beta.kubernetes.io/zone"
4.2 负载均衡器集成
通过AWS Load Balancer Controller实现Ingress:
bash复制helm repo add eks https://aws.github.io/eks-charts
helm install aws-load-balancer-controller eks/aws-load-balancer-controller \
-n kube-system \
--set clusterName=production-cluster
典型Ingress配置示例:
yaml复制apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: store-front
annotations:
alb.ingress.kubernetes.io/scheme: internet-facing
alb.ingress.kubernetes.io/target-type: ip
spec:
ingressClassName: alb
rules:
- host: store.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: frontend-service
port:
number: 80
5. 运维监控与问题排查
5.1 日志与监控方案
必须配置的监控组件:
- CloudWatch Container Insights:
bash复制
aws eks create-addon --cluster-name production-cluster \ --addon-name amazon-cloudwatch-observability \ --region ap-northeast-1 - Prometheus+Grafana(通过EKS Blueprints快速部署):
bash复制
eksctl create addon --name adot --cluster production-cluster \ --service-account-role-arn arn:aws:iam::123456789012:role/otel-service-role
5.2 常见故障处理
节点NotReady:
- 检查EC2实例状态:
bash复制aws ec2 describe-instances --instance-ids $(kubectl get nodes -o json | jq -r '.items[].spec.providerID' | cut -d'/' -f5) - 查看kubelet日志:
bash复制
journalctl -u kubelet -n 100 --no-pager
Pod无法分配IP:
- 检查VPC CNI插件日志:
bash复制kubectl logs -n kube-system -l k8s-app=aws-node --tail=50 - 确认子网剩余IP数量:
bash复制aws ec2 describe-subnets --subnet-ids $(aws eks describe-cluster --name production-cluster --query "cluster.resourcesVpcConfig.subnetIds" --output text) --query "Subnets[*].[SubnetId,CidrBlock,AvailableIpAddressCount]"
6. 成本优化实践
6.1 节点选择策略
混合使用不同机型降低成本:
- Spot实例:对非关键工作负载,可配置50% Spot实例
yaml复制# 在eksctl配置文件中添加: nodeGroups: - name: spot-workers instanceTypes: ["t3.large", "t3a.large"] spot: true minSize: 2 maxSize: 10 - ARM架构:兼容的应用可选用Graviton实例,性价比提升40%
6.2 自动伸缩配置
安装Cluster Autoscaler:
bash复制helm repo add autoscaler https://kubernetes.github.io/autoscaler
helm install cluster-autoscaler autoscaler/cluster-autoscaler \
--set "autoDiscovery.clusterName=production-cluster" \
--set "awsRegion=ap-northeast-1"
配合Horizontal Pod Autoscaler使用:
yaml复制apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: api-hpa
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: api-server
minReplicas: 2
maxReplicas: 10
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 70
7. 安全加固建议
7.1 网络策略
启用Calico网络策略:
bash复制kubectl apply -f https://raw.githubusercontent.com/aws/amazon-vpc-cni-k8s/master/config/master/calico-operator.yaml
kubectl apply -f https://raw.githubusercontent.com/aws/amazon-vpc-cni-k8s/master/config/master/calico-crs.yaml
示例策略(禁止default命名空间所有入站流量):
yaml复制apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny-ingress
namespace: default
spec:
podSelector: {}
policyTypes:
- Ingress
7.2 IAM细粒度权限
为每个应用创建独立IAM Role:
- 创建IAM OIDC Provider:
bash复制
eksctl utils associate-iam-oidc-provider --cluster production-cluster --approve - 通过IRSA绑定权限:
yaml复制配套ServiceAccount:# 在Deployment中添加: spec: serviceAccountName: s3-access-sa containers: - name: app image: my-appyaml复制apiVersion: v1 kind: ServiceAccount metadata: name: s3-access-sa annotations: eks.amazonaws.com/role-arn: arn:aws:iam::123456789012:role/s3-readonly-role
8. 升级与维护
8.1 控制平面升级
EKS控制平面升级流程:
- 检查可用版本:
bash复制aws eks describe-cluster --name production-cluster --query "cluster.version" aws eks list-updates --name production-cluster - 执行升级(会有短暂API中断):
bash复制
aws eks update-cluster-version --name production-cluster --kubernetes-version 1.28
8.2 Worker节点升级
托管节点组升级策略:
bash复制aws eks update-nodegroup-config --cluster-name production-cluster \
--nodegroup-name linux-nodes \
--scaling-config minSize=2,maxSize=5,desiredSize=2 \
--update-config maxUnavailable=1
建议采用滚动更新策略,设置maxUnavailable: 1确保服务不中断。曾经有客户在流量高峰时全量更新节点,导致服务雪崩,这个教训值得记取。