
利用 AWS 自动诊断工具简化 EBS CSI Driver 故障排除流程
在现代 Kubernetes 环境中,持久性存储是有状态 (Stateful) 应用程序的重要组件。Amazon EKS 用户通常会使用 Amazon EBS Container Storage Interface (CSI) 驱动程序来为应用程序提供持久性存储空间 (使用 Amazon EBS)。然而,当任何原因导致驱动故障时,排查问题通常复杂且耗时,并且间接可能导致应用程序停机和数据可用性问题。为了帮助团队更有效地管理和维护 EKS 集群中的 EBS CSI 驱动程序问题,AWS 推出了一个新的自动化诊断工具。这套工具不只能显著缩短故障排除时间,还能提供更准确的问题分析报告。本文将深入探讨如何运用这项工具来优化您的 Kubernetes 运营流程。
AWS Support Automation Workflow (SAW) 简介
AWS Support Automation Workflow (SAW) 是一个专门设计用来自动化 AWS 服务疑难排解流程的工具集。它能够大幅简化复杂的诊断过程,让系统管理员和开发人员能更有效率地解决各种 AWS 服务相关的技术问题。其中,SAW 新增 AWSSupport-TroubleshootEbsCsiDriversForEks
1 这个自动化诊断工具用于检查 EBS CSI Driver 相关的错误,并且诊断 Amazon EKS 集群中的 EBS 磁盘卷挂载问题,同时简化处理 EBS CSI 驱动程序的各种配置疑难:
- 存储相关问题需要跨多个 AWS 服务(EKS、EBS、EC2)和 Kubernetes 资源进行调查
- 诊断 CSI 驱动程序问题需要同时具备 Kubernetes 和 AWS 存储服务的专业知识
- 手动故障排除需要执行大量命令,并对复杂的输出结果进行解读
- 存储系统故障会直接影响应用程序的可用性和数据持久性
技术概述
核心架构组件
AWSSupport-TroubleshootEbsCsiDriversForEks
整合了数个 AWS 服务:
- AWS System Manager (SSM):运行该诊断工具的执行引擎
- Amazon EKS:EBS CSI 驱动程序运作的托管 Kubernetes 服务
- Amazon EBS:提供存储服务
- AWS Lambda:用于运行诊断时创建能够调用 Kubernetes API 的简易程序
- AWS CloudFormation:管理诊断工具资源的创建与清理
- Amazon S3:疑难排解日志和报告的可选存储空间
诊断工具运作机制
AWSSupport-TroubleshootEbsCsiDriversForEks
诊断工具会执行以下步骤:
- 验证集群状态:确认目标 EKS 集群存在
- 部署临时性诊断 AWS 资源:设置执行 Kubernetes API 调用的必要组件
- 执行 EBS CSI 控制器健康检查:评估控制器 pod 状态和配置
- 检查 IAM 权限:验证节点角色和服务账户角色是否具有适当权限
- 诊断持久卷创建问题:分析指定 pod 的 PVC/PV 问题
- 检查 pod 调度:检查节点及 Pod 调度设置,并分析 Pod 事件
- 收集相关日志:收集 Kubernetes 和应用程序日志
- 执行节点健康检查:验证 EC2 实例的健康状况以及与所需端点的连接性
- 检查磁盘卷附件:检查挂载状态
- 清理资源:移除运行诊断工具期间创建的临时性 AWS 资源
- 生成报告:生成包含所有诊断结果的全面疑难排解报告
开始使用 SAW 自动诊断 EBS CSI Driver 问题
-
为 SSM 自动化创建 IAM 角色:
创建具有以下 IAM 信任关系 (Trust Relationship) 的角色,命名为
TroubleshootEbsCsiDriversForEks-SSM-Role
:{ "Version": "2012-10-17", "Statement": [ { "Sid": "", "Effect": "Allow", "Principal": { "Service": "ssm.amazonaws.com" }, "Action": "sts:AssumeRole" } ] }
-
添加 IAM 权限策略:
诊断工具需要特定的 IAM 权限才能正常运作。请注意,如果您不打算将 SAW 诊断报告存储到 Amazon S3 存储桶,可以移除
OptionalRestrictPutObjects
权限。 以下是必要权限的策略示例:{ "Version": "2012-10-17", "Statement": [ { "Sid": "OptionalRestrictPutObjects", "Effect": "Allow", "Action": ["s3:PutObject"], "Resource": ["arn:{partition}:s3:::BUCKET_NAME/*"] }, { "Effect": "Allow", "Action": [ "ec2:DescribeIamInstanceProfileAssociations", "ec2:DescribeInstanceStatus", "ec2:GetEbsEncryptionByDefault", "eks:DescribeAddon", "eks:DescribeAddonVersions", "eks:DescribeCluster", "iam:GetInstanceProfile", "iam:GetOpenIDConnectProvider", "iam:GetRole", "iam:ListOpenIDConnectProviders", "iam:SimulatePrincipalPolicy", "s3:GetBucketLocation", "s3:GetBucketPolicyStatus", "s3:GetBucketPublicAccessBlock", "s3:GetBucketVersioning", "s3:ListBucket", "s3:ListBucketVersions", "ssm:DescribeInstanceInformation", "ssm:GetAutomationExecution", "ssm:GetDocument", "ssm:ListCommandInvocations", "ssm:ListCommands", "ssm:SendCommand", "ssm:StartAutomationExecution" ], "Resource": "*" }, { "Sid": "SetupK8sApiProxyForEKSActions", "Effect": "Allow", "Action": [ "cloudformation:CreateStack", "cloudformation:DeleteStack", "cloudformation:DescribeStacks", "cloudformation:UpdateStack", "ec2:CreateNetworkInterface", "ec2:DeleteNetworkInterface", "ec2:DescribeNetworkInterfaces", "ec2:DescribeRouteTables", "ec2:DescribeSecurityGroups", "ec2:DescribeSubnets", "ec2:DescribeVpcs", "eks:DescribeCluster", "iam:CreateRole", "iam:DeleteRole", "iam:GetRole", "iam:TagRole", "iam:UntagRole", "lambda:CreateFunction", "lambda:DeleteFunction", "lambda:GetFunction", "lambda:InvokeFunction", "lambda:ListTags", "lambda:TagResource", "lambda:UntagResource", "lambda:UpdateFunctionCode", "logs:CreateLogGroup", "logs:CreateLogStream", "logs:DescribeLogGroups", "logs:DescribeLogStreams", "logs:ListTagsForResource", "logs:PutLogEvents", "logs:PutRetentionPolicy", "logs:TagResource", "logs:UntagResource", "ssm:DescribeAutomationExecutions", "tag:GetResources", "tag:TagResources" ], "Resource": "*" }, { "Sid": "PassRoleToAutomation", "Effect": "Allow", "Action": "iam:PassRole", "Resource": [ "arn:*:iam::*:role/TroubleshootEbsCsiDriversForEks-SSM-Role", "arn:*:iam::*:role/Automation-K8sProxy-Role-*" ], "Condition": { "StringLikeIfExists": { "iam:PassedToService": [ "lambda.amazonaws.com", "ssm.amazonaws.com" ] } } }, { "Sid": "AttachRolePolicy", "Effect": "Allow", "Action": [ "iam:AttachRolePolicy", "iam:DetachRolePolicy" ], "Resource": "*", "Condition": { "StringLikeIfExists": { "iam:ResourceTag/AWSSupport-SetupK8sApiProxyForEKS": "true" } } } ] }
-
设置 EKS 访问权限:
为了让 SAW 诊断工具在运行时有权限可以查看 EKS 中的资源,需要适当的 Kubernetes 角色访问控制 (RBAC) 权限,才能在诊断过程执行 Kubernetes API 调用。建议的方法是在 EKS 集群中直接将前面添加的 IAM Role (
TroubleshootEbsCsiDriversForEks-SSM-Role
) 加入到 EKS Access Entry 的设置中:- 在 Amazon EKS 控制台中点击要诊断的 EKS 资源
- 确认 Authentication mode 已设置为
API_AND_CONFIG_MAP
或API
才可以使用 Access Entry - 选择 “Create access entry”
- 针对 IAM principal ARN,选择您创建的 SSM 自动化角色 (
TroubleshootEbsCsiDriversForEks-SSM-Role
) - 针对 Type,选择「Standard」
- 添加具有「Cluster」范围和
AmazonEKSAdminViewPolicy
的访问策略
-
准备一个 S3 存储桶 (可选):
如果您打算存储诊断过程的相关日志,请在 EKS 集群相同区域中创建一个 Amazon S3 Bucket。
执行 AWSSupport-TroubleshootEbsCsiDriversForEks 诊断工具
- 使用链接快速启动诊断工具:Run this Automation (console) 2
- 使用以下参数执行自动化诊断:
- AutomationAssumeRole(可选):您创建的 IAM 角色的 ARN,例如:
arn:aws:iam::123456789012:role/TroubleshootEbsCsiDriversForEks-SSM-Role
- EksClusterName:遇到问题的 EKS 集群名称
- ApplicationPodName:遇到 EBS CSI 驱动程序问题的 Kubernetes pod 的名称
- ApplicationNamespace:出现问题的应用程序 Pod 的命名空间
- EbsCsiControllerDeploymentName(可选):EBS CSI 控制器 pod 的部署名称 (默认:
ebs-csi-controller
) - EbsCsiControllerNamespace (可选):EBS CSI 控制器的命名空间 (默认:
kube-system
) - S3BucketName (可选):上传故障诊断日志的 S3 存储桶名称
- LambdaRoleArn (可选):运行手册创建的 Lambda 函数的 IAM 角色 ARN
- AutomationAssumeRole(可选):您创建的 IAM 角色的 ARN,例如:
-
如果您习惯使用命令行工具,也可以通过 AWS CLI 执行自动化诊断工具:
aws ssm start-automation-execution \ --document-name "AWSSupport-TroubleshootEbsCsiDriversForEks" \ --parameters "EksClusterName=my-production-cluster,ApplicationPodName=my-stateful-app,ApplicationNamespace=default,AutomationAssumeRole=arn:aws:iam::123456789012:role/TroubleshootEbsCsiDriversForEks-SSM-Role"
-
在 AWS Systems Manager 控制台或通过 CLI 可以监控执行状态:
aws ssm get-automation-execution \ --automation-execution-id "execution-id-from-previous-step"
使用示例
诊断 Persistent Volume Claim (PVC) 以及 Pod 处在 Pending 状态
问题情境:一个在 EKS 上运行应用的开发团队遇到了一个难题,新创建的 Pod 使用到持久性存储 Persistent Volume Claim(PVC)一直卡在 Pending 状态。由于无法成功配置所需的存储空间,导致应用程序无法正常启动。这类问题通常需要团队花费数小时的时间,在多个组件之间来回检查与排除,包括:
- 检查 PVC 和 StorageClass 配置
- 检查 EBS CSI Driver 和相关的 Pod 日志
- 验证服务账户的 IAM 角色权限
为了重现问题情境,我创建一个简单的 Shell Script (scenario1.sh),模拟一个故障情境,以展示 AWS 支持自动化工作流程如何识别和解决 EBS CSI 驱动程序相关问题:
export AWS_REGION=eu-west-1
./scenario1.sh
测试情境准备就绪后,我执行重现问题的脚本来创建需要持久性磁盘卷(PV)的 Pod。不出所料,由于磁盘卷挂载的问题,Pod 仍然维持在 Pending 状态无法正常启动。
$ kubectl get pod -n default
NAME READY STATUS RESTARTS AGE
app 0/1 Pending 0 48m
使用 AWS 支持自动化工作流程 (SAW)
在这种情况下,我可以为 EKS 集群添加一个 Access Entry,并且赋予 SAW 诊断工具会使用到 IAM 角色访问 EKS 资源的权限,然后执行AWSSupport-TroubleshootEbsCsiDriversForEks
runbook 来启动疑难排解工作流程。自动化作业将系统性地检查常见问题,包括 IAM 权限、pod 调度问题和磁盘卷附加状态。这种全面的诊断方法可以帮助在调查过程快速找出并解决常见的 EBS CSI 驱动程序相关问题。
添加好 EKS Access Entry 后,执行 AWSSupport-TroubleshootEbsCsiDriversForEks
,启动过程只需提供 EKS Cluster 名称、受影响的 Pod 名称和命名空间。自动化诊断工具可以:
- 验证 EBS CSI 控制器部署的健康状况和配置
- 确认 EBS CSI 驱动程序服务账户的 IAM 角色配置错误
- 确认 StorageClass 参数正确
- 确认节点 IAM 角色缺少所需的 EBS 权限
- 生成一份全面的报告,指出确实遗失的权限
自动诊短结果:
故障排除时间从数小时大幅缩短至仅需 15 分钟。诊断工具生成的输出报告快速指出了根本原因 - 缺少必要的 IAM 权限,并提供了修复 IAM 角色的步骤说明。
示例输出:
==================================================
1. IAM and Service Account permissions checks
==================================================
Checked service account role AmazonEKSEBSCSIDriverRoleLab1 and there is no trust policy for federated
arn:aws:iam::123456789:oidc-provider/oidc.eks.eu-west-1.amazonaws.com/id/C746A744DA16B63394A03370F964F05A
with condition
{
'StringEquals': {
'oidc.eks.eu-west-1.amazonaws.com/id/C746A744DA16B63394A03370F964F05A:aud': 'sts.amazonaws.com'
}
}.
Check AWS documentation https://docs.aws.amazon.com/eks/latest/userguide/ebs-csi.html
报告指出 IAM 权限中的条件设置不正确。在我的示例中,我使用的是 www.sts.amazonaws.com
,而不是 sts.amazonaws.com
。这个细小但关键的配置错误让 EBS CSI 驱动程序无法正确使用关联的 IAM 角色,导致磁盘卷配置失败。更正 IAM 设置后,PVC 成功创建,应用程序 Pod 也正常启动。
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Federated": "arn:aws:iam::123456789:oidc-provider/oidc.eks.eu-west-1.amazonaws.com/id/C746A744DA16B63394A03370F964F05A"
},
"Action": "sts:AssumeRoleWithWebIdentity",
"Condition": {
"StringEquals": {
"oidc.eks.eu-west-1.amazonaws.com/id/C746A744DA16B63394A03370F964F05A:aud": "www.sts.amazonaws.com", <-- Incorrect setting
"oidc.eks.eu-west-1.amazonaws.com/id/C746A744DA16B63394A03370F964F05A:sub": "system:serviceaccount:kube-system:ebs-csi-controller-sa"
}
}
}
]
}
高级技巧:简化 EBS CSI 疑难排解工作流程
为了让 AWS 支持自动化工作流程在处理 EBS CSI 驱动程序问题时发挥最大效益,您也可以整合自动化诊断工具,针对常见的错误模式设置自动响应机制。例如:整合 EventBridge 规则,在监控系统检测到应用程序健康检查失败等问题时自动触发对应动作。这种自动化机制可以帮助团队减少人工介入的需求,并且更快速地解决问题。
下面的流程图展示了自动化工作流程如何处理 EBS CSI 驱动程序问题 - 从最初触发开始,经过全面的诊断步骤,最后生成完整的报告并与外部系统集成。
- 确保系统已准备好进行自动化:
虽然自动化诊断可以与标准 EKS 设置一起使用,但某些高级诊断功能需要工作节点是由 AWS Systems Manager 所管理的实例。EKS-optimized Amazon Linux AMI 默认已包含 SSM 代理程序,因此通常能够正常使用。然而,如果您的工作节点并非使用 EKS-optimized AMI,则需要将它们注册为受管理的实例,才能启用所有诊断功能。
- 创建特定的 CloudWatch 警报以及早发现 EBS CSI 问题:
创建监控机制来追踪有状态系统的健康状况。这可以包括反映有状态应用程序健康状况的自定义 CloudWatch 指标。设置具有适当阈值的 CloudWatch 警报,以便及早发现潜在问题。
- 创建 EventBridge 规则,在检测到问题时触发自动化:
使用 CloudWatch 告警状态的变化,您可以创建特定的 EventBridge 规则来监控应用程序事件,并在发生问题时通过 AWS Lambda 触发自动化工作流程。
aws events put-rule \
--name "EBSCSITroubleshootingTrigger" \
--event-pattern '{
"source": ["aws.cloudwatch"],
"detail-type": ["CloudWatch Alarm State Change"],
"resources": ["arn:aws:cloudwatch:us-east-1:123456789012:alarm:EBSVolumeProvisioningFailures"],
"detail": {
"state": {
"value": ["ALARM"]
}
}
}'
如果您有自己的警报系统,您也可以直接使用StartAutomationExecution
API 直接调用 SSM执行
手册:
aws ssm start-automation-execution \
--document-name "AWSSupport-TroubleshootEbsCsiDriversForEks" \
--parameters \
"EksClusterName=my-production-cluster,\
ApplicationPodName=my-stateful-app,\
ApplicationNamespace=default,\
AutomationAssumeRole=arn:aws:iam::123456789012:role/TroubleshootEbsCsiDriversForEks-SSM-Role"
与监控和通知系统整合
-
将自动化结果反馈至事件管理平台:
您可以设置一个 Lambda 函数来处理自动化输出,并将发现和建议的动作更新至您的事件管理系统:
import boto3 import json import requests def lambda_handler(event, context): ssm_client = boto3.client('ssm') execution_id = event['detail']['automation-execution-id'] # Get automation execution output response = ssm_client.get_automation_execution( AutomationExecutionId=execution_id ) outputs = response['AutomationExecution']['Outputs'] diagnosis_report = json.loads(outputs['DiagnosisReport'][0]) # Update PagerDuty incident headers = { 'Content-Type': 'application/json', 'Authorization': 'Token token=YOUR_API_KEY' } payload = { 'incident': { 'id': event['incident_id'], 'type': 'incident', 'status': 'acknowledged', 'notes': [{ 'content': f"EBS CSI Diagnosis Results:\\n{json.dumps(diagnosis_report, indent=2)}" }] } } requests.put( f"<https://api.pagerduty.com/incidents/{event['incident_id']}>", headers=headers, data=json.dumps(payload) ) return { 'statusCode': 200, 'body': 'PagerDuty updated with diagnosis results' }
-
为存储故障排除结果创建集中式存储库:
以可搜索的格式 (例如 Elasticsearch) 存储每次自动化执行的结果,以便识别模式并随时间改善存储配置。
结论
AWSSupport-TroubleshootEbsCsiDriversForEks
执行手册为诊断和解决 EKS 环境中的 EBS CSI 驱动程序问题提供了一个便捷的解决方案。借由在 AWS 服务和 Kubernetes 组件之间自动化疑难排解流程,大幅缩短了识别和修复问题所需的时间。
本文展示了自动化如何在提供全面性诊断的同时,显著减少故障排除时间。通过将这个工作流程与监控系统和事件管理平台整合,团队可以在 Kubernetes 环境中建立一个更有效的问题排查机制。
参考资料