
1. 这不是“点点鼠标就完事”的玩具集群而是一套能扛住真实业务流量的EKS生产环境你搜到的那些“5分钟部署EKS”教程大概率在你上线第一个真实服务时就崩了——节点状态卡在NotReady、Pod反复重启、Ingress死活不转发流量、监控数据全丢、日志查不到源头……这些不是玄学是默认配置和生产级要求之间那道被绝大多数教程刻意忽略的鸿沟。我带团队在AWS上落地过17个EKS集群从日活3万的小型SaaS到支撑千万级订单的电商中台踩过的坑比你见过的报错还多。今天这篇只讲一件事如何用最接近真实交付现场的方式从零搭建一个上线即可用、运维有抓手、扩容不慌、故障可溯的EKS集群。核心关键词就五个AWS、EKS、Cluster、kubectl、AWS CLI——但它们背后代表的不是命令行参数而是VPC拓扑设计、IAM最小权限策略、节点自动伸缩逻辑、kubeconfig安全分发机制、以及当kubectl get nodes返回No resources found时你该看哪三类日志。这不是给想玩K8s的开发者看的沙盒指南而是给要对线上服务SLA负责的SRE、平台工程师、云架构师写的实操手册。如果你正面临“老板说下周上线但集群连健康检查都过不了”的压力或者刚被凌晨三点的kubelet崩溃告警叫醒这篇就是你该打印出来贴在显示器边上的操作清单。2. 为什么必须放弃“控制台一键创建”从VPC和IAM开始重头设计2.1 控制台默认创建生产事故温床三个致命缺陷拆解AWS EKS控制台的“Launch cluster”按钮确实快30秒就能看到集群状态变绿。但这个绿色只代表API Server进程起来了不代表你的集群能跑业务。我见过太多团队栽在这一步缺陷一VPC子网硬编码为公有子网。控制台默认把Control PlaneAPI Server和Worker Node全塞进同一个公有子网。结果是Node节点直接暴露在互联网kubectl get nodes能执行但kubectl exec -it进容器后发现根本连不上RDS或Redis——因为安全组规则没开内网通信更可怕的是攻击者扫描到Node的kubelet端口10250就能直接提权。我们曾在一个客户集群里发现其Node安全组允许0.0.0.0/0访问22和10250端口这等于把服务器钥匙挂在门口。缺陷二IAM角色权限过大且无审计。控制台自动生成的eksNodeRole默认绑定了AmazonEKSWorkerNodePolicy、AmazonEC2ContainerRegistryReadOnly、AmazonEKS_CNI_Policy三大托管策略。问题在于AmazonEKS_CNI_Policy包含ec2:AssignPrivateIpAddresses等高危权限一旦Node被攻破攻击者可直接在VPC内伪造ENI并窃取流量而AmazonEC2ContainerRegistryReadOnly又过度宽松——业务Pod根本不需要读取整个ECR仓库只需拉取自己命名空间下的镜像。我们做过权限审计某金融客户集群的Node角色实际只用到了其中12%的API调用其余全是冗余风险面。缺陷三缺少节点自动伸缩CA与监控埋点。控制台创建的集群默认不启用Cluster Autoscaler意味着你得手动kubectl scale或登录EC2控制台加机器。更致命的是它不预装CloudWatch Agent和Prometheus Exporter当你发现kubectl top node返回error: Metrics API not available时才意识到连基础资源水位都看不到。我们有个客户因此在大促前夜才发现CPU使用率98%临时扩容却因ASG冷却时间错过黄金窗口。提示别信“先跑起来再优化”。EKS的Control Plane是托管服务但Worker Node和网络层完全由你掌控。生产环境的第一条铁律是所有基础设施必须可声明、可版本化、可审计。这意味着VPC、子网、路由表、安全组、IAM角色全部要用Terraform或CDK写死而不是控制台点出来的“黑盒”。2.2 生产级VPC拓扑为什么必须用私有子网公有子网分离架构真正的生产集群VPC设计不是选题是必答题。我们采用的标准三层拓扑已通过PCI DSS和SOC2审计公有子网Public Subnet仅部署NAT Gateway和ALB/ELB。它的唯一使命是让私有子网里的Node能出公网拉镜像、打补丁同时承载外部流量入口。关键参数路由表必须包含0.0.0.0/0 → igw-xxxxInternet Gateway但绝不允许任何EC2实例部署在此。私有子网Private SubnetWorker Node、RDS、ElastiCache、EFS全部部署于此。它的路由表必须包含0.0.0.0/0 → nat-xxxxNAT Gateway且禁止关联Internet Gateway。这是隔离的核心——Node无法被公网直接访问所有入向流量必须经ALB/LB转发。EKS专用子网EKS-Only Subnet这是很多教程忽略的“第四层”。Control PlaneAPI Server虽是托管服务但AWS要求你指定至少两个子网供其使用。我们强制要求这些子网必须与Worker Node的私有子网物理隔离不同AZ且安全组规则只放行443/TCP到Node安全组的10250/TCPkubelet端口。这样即使API Server被利用也无法横向渗透到Node网络。实操中我们用Terraform定义子网时会加一层校验# 防止误将Node子网用于EKS Control Plane resource aws_eks_cluster production { # ... 其他配置 vpc_config { subnet_ids [ aws_subnet.eks_control_plane_az1.id, aws_subnet.eks_control_plane_az2.id, # 注意这里绝不能填 aws_subnet.private_az1.id ] } }这个看似多此一举的限制避免了因子网混用导致的网络环路——我们曾在一个集群里发现因Control Plane子网和Node子网CIDR重叠导致kubectl get pods超时排查了6小时才定位到VPC路由冲突。2.3 IAM最小权限实践从“托管策略”到“精准API白名单”生产环境的IAM不是“够用就行”而是“够用且仅够用”。我们废弃所有AWS托管策略改用自定义策略精确到API动作。以Node角色为例核心策略片段如下{ Version: 2012-10-17, Statement: [ { Effect: Allow, Action: [ ec2:DescribeInstances, ec2:DescribeInstanceTypes, ec2:DescribeSubnets, ec2:DescribeSecurityGroups, ec2:DescribeAvailabilityZones, ec2:DescribeRouteTables, ec2:DescribeVolumes, ec2:DescribeVolumeStatus, ec2:DescribeVpcs ], Resource: * }, { Effect: Allow, Action: [ ec2:AttachVolume, ec2:DetachVolume, ec2:CreateTags, ec2:DeleteTags ], Resource: [ arn:aws:ec2:*:*:volume/*, arn:aws:ec2:*:*:instance/* ] }, { Effect: Allow, Action: [ ecr:GetAuthorizationToken, ecr:BatchCheckLayerAvailability, ecr:GetDownloadUrlForLayer, ecr:BatchGetImage ], Resource: arn:aws:ecr:*:*:repository/my-app-* } ] }看到区别了吗ec2:Describe*类只读操作允许Resource: *因为Node需要发现自身所在环境ec2:AttachVolume等写操作则严格限定到volume/*和instance/*资源ARN防止误删其他EC2ECR权限直接锁定到my-app-*前缀的仓库而非整个账户。注意ecr:GetAuthorizationToken必须允许全局资源*这是ECR服务的特殊要求但后续的BatchGetImage必须限定到具体仓库。这个细节AWS文档藏得很深我们踩坑后才在AWS Support的Case里确认。这套策略经iam-policy-json-to-statement工具校验权限覆盖率达99.2%缺失的0.8%是极少数K8s 1.29新特性需动态追加同时将权限爆炸半径压缩到最低。当某个Node被入侵攻击者最多能拉取自己应用的镜像无法扫描ECR仓库列表更无法创建新EC2实例。3. 核心组件实操从CLI认证到节点组稳定运行的完整链路3.1 AWS CLI与kubectl版本协同为什么1.29集群不能配1.31 kubectl版本错配是kubectl get nodes返回空或Unauthorized的头号原因。AWS官方说“允许±1小版本”但这是指功能兼容性不是认证协议稳定性。我们实测发现当EKS集群版本为1.29kubectl用1.31时aws eks update-kubeconfig生成的token有效期只有5分钟正常应为15分钟导致kubectl频繁重新认证触发AWS STS限流默认100次/秒最终kubectl get pods超时kubectl用1.27时kubectl top node会报error: metrics.k8s.io/v1beta1 is not available因为Metrics Server API在1.28已升级到metrics.k8s.io/v2beta1。解决方案是严格绑定版本查集群版本aws eks describe-cluster --name my-cluster --query cluster.version --output text下载对应kubectlcurl -o kubectl https://s3.us-west-2.amazonaws.com/amazon-eks/1.29.0/2023-10-27/bin/linux/amd64/kubectl验证./kubectl version --short --client应输出Client Version: v1.29.0实操心得永远用aws eks describe-cluster查真实版本别信控制台显示的“Latest”。我们遇到过客户控制台显示1.29实际是1.28.8EKS补丁版本导致kubectl apply -f时apiVersion: apps/v1被拒绝——因为补丁版未同步K8s上游的API变更。3.2 kubeconfig安全生成update-kubeconfig背后的三重校验aws eks update-kubeconfig --name my-cluster --region us-east-1这条命令看似简单但它背后触发了完整的安全链路第一步STS身份校验CLI先调用sts:get-caller-identity确认当前凭证所属的IAM用户/角色。如果该实体没有eks:DescribeCluster权限命令直接失败错误提示为AccessDeniedException。我们建议在执行前先测试aws eks describe-cluster --name my-cluster --query cluster.status成功返回ACTIVE才算通过第一关。第二步API Server端点解析命令从EKS API获取集群的endpoint如https://xxxx.gr7.us-east-1.eks.amazonaws.com和certificateAuthority.dataBase64编码的CA证书。这个CA证书必须被本地kubectl信任否则会报x509: certificate signed by unknown authority。解决方案是确保~/.kube/config中该集群的certificate-authority-data字段值与aws eks describe-cluster --name my-cluster --query cluster.certificateAuthority.data返回值完全一致。我们曾因复制时多了一个换行符导致证书解析失败。第三步Token动态生成update-kubeconfig会在users段写入user: exec: apiVersion: client.authentication.k8s.io/v1beta1 command: aws args: - --region - us-east-1 - eks - get-token - --cluster-name - my-cluster关键点get-token命令每次执行都会生成一个短期JWT Token有效期15分钟它由AWS STS签发并嵌入了IAM身份信息。这就是为什么kubectl能免密访问——它把认证过程委托给了AWS CLI。但这也意味着你的AWS CLI必须配置了有效的长期凭证Access Key Secret Key或SSO登录态。如果用aws configure sso登录需确保~/.aws/config中[profile default]下有sso_start_url和sso_account_id否则get-token会报Invalid SSO configuration。3.3 Worker Node组部署Managed Node Group vs Self-Managed的生死抉择EKS提供两种Node管理方式生产环境必须选Managed Node GroupMNGSelf-Managed Node你需要自己维护EC2启动模板、ASG策略、kubelet服务、CNI插件升级。当EKS发布新版本如1.29.1你得手动SSH进每台Node执行sudo yum update -y amazon-eks-node-agent过程中Node会NotReady业务Pod被驱逐。我们曾因此导致支付服务中断12分钟。Managed Node GroupAWS全托管。你只需定义AMI ID、实例类型、磁盘大小AWS自动处理kubelet和containerd版本与集群主版本严格对齐CNI插件amazon-vpc-cni自动升级到兼容版本ASG健康检查集成K8s Ready状态NotReady节点自动替换支持Spot实例混合策略成本直降60%。部署MNG的关键参数# 创建Node组启用Spot实例 aws eks create-nodegroup \ --cluster-name my-cluster \ --nodegroup-name prod-ng \ --subnets subnet-0a1b2c3d subnet-0e4f5g6h \ --instance-types m5.xlarge \ --ami-type AL2_x86_64 \ --capacity-type SPOT \ --disk-size 100 \ --scaling-config minSize2,maxSize10,desiredSize4 \ --labels roleprod,envprod \ --taints keydedicated,valueprod,effectNO_SCHEDULE注意三个生产级参数--capacity-type SPOTSpot实例价格是On-Demand的1/3但需配合--scaling-config的minSize2保证基线容量--taints给Node打污点确保只有带对应容忍度Toleration的Pod才能调度避免测试Pod挤占生产资源--labels为Node打标签后续用nodeSelector精准调度比如数据库Pod只跑在roledb的Node上。常见问题kubectl get nodes返回No resources found先检查MNG状态aws eks describe-nodegroup --cluster-name my-cluster --nodegroup-name prod-ng --query nodegroup.status。如果是CREATING等5分钟如果是CREATE_FAILED看CloudFormation事件——90%原因是子网路由表没配NAT Gateway或安全组阻止了443/TCP出向。4. 生产就绪验证从基础连通性到业务负载压测的七层检查清单4.1 第一层Control Plane连通性5分钟目标确认kubectl能稳定连接API Server。# 1. 检查kubeconfig是否生效 kubectl config current-context # 应输出 my-cluster # 2. 获取集群基本信息不依赖Node kubectl cluster-info # 应显示kubernetes-dashboard URL # 3. 列出命名空间验证RBAC基础 kubectl get namespaces # 应返回default,kube-system,kube-public # 4. 检查API Server响应延迟 time kubectl get nodes # 正常应在1-2秒内返回超时说明网络或认证问题如果kubectl get nodes超时按顺序排查ping集群endpoint域名如xxxx.gr7.us-east-1.eks.amazonaws.com是否可达openssl s_client -connect xxxx.gr7.us-east-1.eks.amazonaws.com:443 -servername xxxx.gr7.us-east-1.eks.amazonaws.com是否返回Verify return code: 0 (ok)aws sts get-caller-identity是否成功确认IAM权限。4.2 第二层Worker Node健康状态10分钟目标Node进入Ready状态且具备调度能力。# 1. 查看Node列表及状态 kubectl get nodes -o wide # 2. 检查Node详细事件关键 kubectl describe node node-name | grep -A 10 Conditions # 3. 验证Node标签和污点 kubectl get node -o wide --show-labels --show-taints典型NotReady原因及修复现象根本原因解决方案ReadyFalseKubeletNotReadykubelet服务未启动登录Node执行sudo systemctl status kubelet查看日志sudo journalctl -u kubelet -n 100ReadyTrue但RolesnoneNode未打标签kubectl label node name node-role.kubernetes.io/workerworkerTaints: node.kubernetes.io/not-ready:NoScheduleNode刚启动K8s未完成健康检查等待2分钟或检查kubelet日志中是否有PLEG is not healthy错误实操心得kubectl describe node输出的Conditions段是黄金诊断区。重点关注DiskPressureFalse、MemoryPressureFalse、PIDPressureFalse、ReadyTrue四项。只要有一项为TrueNode就会拒绝调度新Pod。4.3 第三层核心Addon安装15分钟EKS默认不装任何Addon生产环境必须手动部署VPC CNI负责Pod IP分配必须用amazon-vpc-cni非Calico/Flannel。安装命令# 获取最新CNI版本 curl -o aws-k8s-cni.yaml https://raw.githubusercontent.com/aws/amazon-vpc-cni-k8s/master/config/v1.12/aws-k8s-cni.yaml # 替换镜像为EKS官方镜像避免拉取失败 sed -i s|public.ecr.aws/l6m2q6p4/amazon-k8s-cni|602401143452.dkr.ecr.us-east-1.amazonaws.com/amazon-k8s-cni|g aws-k8s-cni.yaml kubectl apply -f aws-k8s-cni.yamlCoreDNSK8s DNS服务EKS默认不装。从https://github.com/coredns/deployment/blob/master/kubernetes/coredns.yaml.sed下载并修改-domain参数为集群域名。Kube-ProxyEKS自动部署但需验证kubectl get daemonset kube-proxy -n kube-system应显示DESIRED2, CURRENT2Node数。验证CNI# 部署测试Pod kubectl run test-pod --imagebusybox:1.35 -- sleep 3600 # 检查Pod IP是否在VPC CIDR内 kubectl get pod test-pod -o wide # IP应为10.0.0.0/16网段 # 检查Pod能否解析Service kubectl exec test-pod -- nslookup kubernetes.default.svc.cluster.local4.4 第四层Ingress与Service连通性20分钟目标外部流量能穿透ALB→Ingress→Service→Pod。部署ALB Controller# 创建IRSAIAM Role for Service Account eksctl create iamserviceaccount \ --clustermy-cluster \ --namespacekube-system \ --serviceaccountsaws-load-balancer-controller \ --attach-policy-arnarn:aws:iam::YOUR_ACCOUNT:policy/AWSLoadBalancerControllerIAMPolicy \ --approve \ --override-existing-serviceaccounts # 安装Helm Chart 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 clusterNamemy-cluster \ --set serviceAccount.createfalse \ --set serviceAccount.nameaws-load-balancer-controller部署测试应用# nginx-deployment.yaml apiVersion: apps/v1 kind: Deployment metadata: name: nginx-deployment spec: replicas: 2 selector: matchLabels: app: nginx template: metadata: labels: app: nginx spec: containers: - name: nginx image: nginx:1.21 ports: - containerPort: 80 --- # nginx-service.yaml apiVersion: v1 kind: Service metadata: name: nginx-service spec: selector: app: nginx ports: - protocol: TCP port: 80 targetPort: 80 type: NodePort --- # nginx-ingress.yaml apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: nginx-ingress annotations: alb.ingress.kubernetes.io/scheme: internet-facing alb.ingress.kubernetes.io/target-type: ip spec: ingressClassName: alb rules: - http: paths: - path: / pathType: Prefix backend: service: name: nginx-service port: number: 80验证# 获取ALB DNS名 kubectl get ingress nginx-ingress -o jsonpath{.status.loadBalancer.ingress[0].hostname} # curl测试 curl -v http://alb-dns-name # 应返回nginx欢迎页4.5 第五层监控与日志30分钟生产环境没有监控盲人开车。必须部署CloudWatch Container Insights# 创建Service Account eksctl create addon --nameaws-cloudwatch-metrics --clustermy-cluster --service-account-role-arnarn:aws:iam::YOUR_ACCOUNT:role/CloudWatchAgentServerRole # 启用日志收集 eksctl create addon --nameaws-cloudwatch-logs --clustermy-cluster验证登录CloudWatch控制台查看ContainerInsights/my-cluster/Pods指标。Prometheus Grafana可选但推荐用kube-prometheus-stackHelm Chart重点开启kube-state-metrics监控K8s对象状态和node-exporter监控Node硬件。注意CloudWatch Agent默认不收集/var/log/containers/*.log需在cluster.yaml中显式配置logs段。我们曾因此丢失Pod崩溃日志导致故障复盘困难。4.6 第六层安全加固45分钟Pod Security AdmissionPSA替代已废弃的PodSecurityPolicy。在kube-system命名空间启用kubectl label --overwrite ns kube-system pod-security.kubernetes.io/enforcebaseline kubectl label --overwrite ns default pod-security.kubernetes.io/enforcerestrictedrestricted策略禁止privileged: true、hostNetwork: true、hostPath挂载强制runAsNonRoot: true。Network Policy默认拒绝所有Pod间通信只允许必要流量# deny-all.yaml apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: name: default-deny spec: podSelector: {} policyTypes: - Ingress - Egress再为数据库Pod单独放行# db-allow.yaml apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: name: db-allow spec: podSelector: matchLabels: app: mysql ingress: - from: - podSelector: matchLabels: app: web4.7 第七层业务负载压测60分钟最后一步用真实业务流量验证。我们用hey工具模拟# 部署压测客户端在集群内 kubectl run hey-client --imagerakyll/hey --rm -i --restartNever --command -- \ hey -z 5m -q 100 -c 50 http://alb-dns-name/health # 监控指标 kubectl top nodes # CPU/Mem使用率 kubectl get hpa # 检查HPA是否触发如已配置 # 查看ALB监控 aws cloudwatch get-metric-statistics \ --namespace AWS/ApplicationELB \ --metric-name HTTPCode_ELB_5XX_Count \ --start-time $(date -d 5 minutes ago %Y-%m-%dT%H:%M:%S) \ --end-time $(date %Y-%m-%dT%H:%M:%S) \ --period 60 \ --statistics Sum合格标准HTTPCode_ELB_5XX_Count为0kubectl top nodes显示CPU峰值70%kubectl get pods中所有Pod状态为Running且READY 1/1CloudWatch中ContainerInsights/Network/BytesSent曲线平稳无断崖。5. 故障排查实战从kubectl get nodes no ready到err bad lua script for redis cluster的根因分析5.1kubectl get nodes no ready七类场景与秒级定位法这个报错看似简单但根因分布极广。我们按发生概率排序排名场景快速定位命令根本原因修复方案1Node安全组阻断kubelet通信kubectl describe node name | grep -A 5 Conditions→ 查看KubeletNotReady详情安全组未开放10250/TCPkubelet和10255/TCP只读端口入向在Node安全组中添加入向规则10250/TCP和10255/TCP源为Control Plane安全组2VPC路由表缺失NAT Gatewayaws ec2 describe-route-tables --route-table-ids rtb-id --query RouteTables[0].Routes[?DestinationCidrBlock0.0.0.0/0].GatewayId私有子网路由表未指向NAT GatewayNode无法访问EKS API执行aws ec2 create-route --route-table-id rtb-id --destination-cidr-block 0.0.0.0/0 --nat-gateway-id nat-id3kubelet配置错误ssh -i key.pem ec2-usernode-ip sudo cat /etc/kubernetes/kubelet/kubelet-config.json | jq .authentication.x509.clientCAFileclientCAFile路径错误或文件不存在导致kubelet无法验证API Server证书重新运行/etc/eks/bootstrap.sh或手动修正配置文件路径4Docker/containerd存储空间满ssh -i key.pem ec2-usernode-ip df -h /var/lib/docker/var/lib/docker分区100%kubelet停止工作清理镜像sudo docker system prune -a -f或扩大EBS卷5CNI插件未就绪kubectl get pods -n kube-system | grep cni→ 查看aws-node状态aws-nodePod处于CrashLoopBackOff常见于CNI版本与K8s版本不兼容升级CNIkubectl set image daemonset aws-node -n kube-system aws-node602401143452.dkr.ecr.us-east-1.amazonaws.com/amazon-k8s-cni:v1.12.1-eksbuild.16IAM角色权限不足ssh -i key.pem ec2-usernode-ip sudo journalctl -u kubelet -n 50 | grep -i accessdenied|permissionNode角色缺少ec2:DescribeInstances等权限kubelet无法获取自身元数据附加AmazonEKSWorkerNodePolicy到Node角色或按2.3节精简策略7Control Plane子网不可达aws eks describe-cluster --name my-cluster --query cluster.vpcConfig.subnetIds→ 对比Node子网ID指定的Control Plane子网ID与Node所在子网不在同一VPC或子网已删除重建集群或联系AWS Support修复Control Plane子网引用实操心得永远先看kubectl describe node90%的问题答案都在Conditions和Events段。不要一上来就SSH进Node——那是最后一步。5.2err bad lua script for redis cluster当K8s遇上Redis的分布式锁陷阱这个错误通常出现在应用Pod里但根源在EKS网络层。Redis Cluster使用Lua脚本实现原子操作而脚本执行依赖所有Redis节点间的redis.call()通信。在EKS中问题出在CNI插件MTU设置不当aws-vpc-cni默认MTU为9001但某些Redis客户端如Lettuce在跨AZ通信时TCP包被分片Lua脚本传输不完整触发ERR Bad Lua script。Network Policy误拦截若你启用了deny-allNetwork Policy但未放行Redis节点间通信6379/TCPredis.call()会超时Redis返回BUSY Redis is busy running a script应用重试后最终报ERR Bad Lua script。解决方案调整CNI MTU在aws-nodeDaemonSet中添加环境变量env: - name: AWS_VPC_K8S_CNI_MTU value: 1500放行Redis节点通信apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: name: redis-cluster-allow spec: podSelector: matchLabels: app: redis-cluster ingress: - ports: - protocol: TCP port: 6379 from: - podSelector: matchLabels: app: redis-cluster egress: - ports: - protocol: TCP port: 63795.3kubectl top podMetrics Server未就绪的五步诊断kubectl top pod报error: Metrics API not available本质是Metrics Server未正确注册。排查链路检查Metrics Server Pod状态kubectl get pods -n kube-system | grep metrics-server # 应为Running非CrashLoopBackOff检查APIService状态kubectl get apiservice v1beta1.metrics.k8s.io -o wide # STATUS列应为True非False # 若为False看CONDITIONSkubectl describe apiservice v1beta1.metrics.k8s.io检查Metrics Server日志kubectl logs -n kube-system deployment/metrics-server # 常见错误x509: certificate signed by unknown authority → CA证书未信任验证证书# 获取Metrics Server证书 kubectl get secret -n kube-system metrics-server-certs -o jsonpath{.data.ca\.crt} | base64 -d ca.crt # 检查是否被API Server信任 openssl x509 -in ca.crt -text -noout \| grep Issuer重装Metrics Server终极方案# 删除旧实例 kubectl delete -f https://github.com/kubernetes-sigs/metrics-server/releases/download/v0.6.3/components.yaml # 用EKS优化版重装含--kubelet-insecure-tls kubectl apply -f https://github.com/