排查 EKS 中的 EFS 挂载失败:IAM 挂载选项之谜
Source: Dev.to
TL;DR
如果在 EKS 中挂载 EFS 卷时看到 mount.nfs4: access denied by server while mounting 127.0.0.1:/,且安全组配置正确,那么很可能是在使用 EFS 文件系统策略时,PersistentVolume 定义中缺少 iam 挂载选项。
问题
在将一个需要将报告写入共享 EFS 文件系统的新报告服务集成到我们的 EKS 集群时,Pod 一直因以下神秘错误而挂载失败:
MountVolume.SetUp failed for volume "efs-pv": rpc error: code = Internal desc = Could not mount "{efs_id}:/"
Output: mount.nfs4: access denied by server while mounting 127.0.0.1:/
调查之旅
初始怀疑(全错)
理论 1:安全组问题
- 已验证工作节点与 EFS 挂载目标之间的 NFS 流量(TCP 2049)已放行。
- 挂载目标在所有可用区均已创建。
结果: 安全组配置完美。不是问题所在。
理论 2:EFS 文件系统策略
- 最近添加了基于 IAM 的文件系统策略以限制访问。
- 策略中包含
aws:PrincipalArn等条件,用于白名单特定 IAM 角色。
突破口: 删除该策略后即可正常工作!
灵光一现
阅读 AWS EFS 故障排除文档 时发现:
如果未在带有限制性文件系统策略的情况下添加
iam挂载选项,则 pod 会出现以下错误信息:
mount.nfs4: access denied by server while mounting 127.0.0.1:/
根本原因分析
1. EFS 文件系统策略条件
我们在策略条件中使用了 aws:PrincipalArn:
{
"Condition": {
"ArnLike": {
"aws:PrincipalArn": [
"arn:aws:iam::123456789012:role/worker-node-role",
"arn:aws:iam::123456789012:role/efs-csi-driver-role"
]
}
}
}
问题: 根据 AWS 文档,aws:PrincipalArn 和大多数 IAM 条件键 不对 NFS 客户端挂载到 EFS 强制执行。只有以下条件键有效:
aws:SecureTransport(Boolean)aws:SourceIp(String – 仅公共 IP)elasticfilesystem:AccessPointArn(String)elasticfilesystem:AccessedViaMountTarget(Boolean)
2. 缺少 IAM 挂载选项
我们的 PersistentVolume 定义遗漏了 iam 挂载选项:
# BEFORE – Missing iam mount option
apiVersion: v1
kind: PersistentVolume
metadata:
name: efs-pv
spec:
storageClassName: aws-efs-csi-sc
csi:
driver: efs.csi.aws.com
volumeHandle: "{efs_id}"
如果没有 iam,EFS CSI 驱动程序将不会使用 IAM 角色进行身份验证,因此任何带有 IAM 限制的文件系统策略都会失效。
3. EFS 挂载流程
使用带有 tls 挂载选项的 EFS CSI 驱动程序时:
- 节点级挂载 首先发生(通过工作节点的 IAM 角色)。
- 没有
iam→ 匿名 NFS 挂载。 - 有
iam→ 使用 IAM 角色凭证进行身份验证的挂载。
解决方案
修复 1:在 mountOptions 中添加 iam
# AFTER – With iam mount option
apiVersion: v1
kind: PersistentVolume
metadata:
name: efs-pv
spec:
storageClassName: aws-efs-csi-sc
mountOptions:
- tls # Encryption in transit
- iam # Enable IAM authentication
csi:
driver: efs.csi.aws.com
volumeHandle: "{efs_id}"
修复 2:仅使用受支持的 EFS 条件键
如果需要文件系统策略,请将其限制在受支持的条件范围内:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": { "AWS": "*" },
"Action": [
"elasticfilesystem:ClientMount",
"elasticfilesystem:ClientWrite",
"elasticfilesystem:ClientRootAccess"
],
"Resource": "arn:aws:elasticfilesystem:us-east-1:123456789012:file-system/{efs_id}",
"Condition": {
"Bool": {
"elasticfilesystem:AccessedViaMountTarget": "true",
"aws:SecureTransport": "true"
}
}
}
]
}
此策略:
- 要求 TLS 加密(
aws:SecureTransport)。 - 要求通过挂载目标访问(
elasticfilesystem:AccessedViaMountTarget)。 - 仅使用受支持的条件键。
- 依赖安全组进行网络层访问控制。
关键要点
-
IAM 挂载选项是 IAM 授权的必需条件
没有-o iam,EFS 挂载是匿名的。任何基于 IAM 的文件系统策略都会拒绝访问。 -
并非所有 IAM 条件都适用于 EFS
对于 NFS 挂载,仅强制执行四个条件键。使用其他条件会产生错误的安全感。 -
正确分层您的安全
- 网络层: 安全组(谁可以访问挂载目标)。
- IAM 层: 角色上的 IAM 策略(允许哪些操作)。
- 文件系统层: EFS 策略(额外的限制)。
-
仔细阅读错误日志
错误中提到127.0.0.1是因为 EFS 挂载助手会为 TLS 创建本地 stunnel 代理。实际的失败发生在 IAM 授权层,而不是网络层。 -
手动测试挂载操作
SSH 到工作节点并使用 EFS 挂载助手测试挂载:sudo mount -t efs -o tls,iam {efs_id}:/ /mnt/test这可以在 Kubernetes 之外验证配置。
结论
看似复杂的 IAM 策略问题实际上是缺少挂载选项。关键的洞察是,EFS 文件系统策略 需要显式的 IAM 认证,通过 iam 挂载选项实现,并且大多数 IAM 条件键不适用于 NFS 挂载。