发布于 2026-01-06 0 阅读
0

将 S3 对象挂载到 Kubernetes Pod

将 S3 对象挂载到 Kubernetes Pod

本文介绍如何将 S3 存储桶挂载到 EKS 集群中的所有节点,并使其作为hostPath 卷可供 Pod 访问。我们当然知道 hostPath 卷存在安全隐患,但在此情况下,这并非主要问题——因为实际访问权限授予的是 S3 存储桶(而非主机文件系统),并且访问权限是按服务帐户分配的。

高飞

我们使用goofys作为挂载工具。它是一个“用 Go 语言编写的高性能、类 POSIX 的 Amazon S3 文件系统”,基于FUSE(用户空间文件系统)技术。

守护进程集

为了透明地提供挂载点,我们需要运行一个守护进程集——这样就可以在集群中的所有节点上创建挂载点。

Dockerfile 和 Helm Chart

我们基于Alpine Linux和 Helm chart 构建了自己的 goofys Docker 镜像,该镜像安装了 DaemonSet。

该镜像文件位于我们的 Docker Hub 仓库中,地址为:https://hub.docker.com/r/otomato/goofys

Dockerfile 和 Helm chart 文件可以在这里找到:https://github.com/otomato-gh/s3-mounter

每个服务帐户的 S3 访问权限

目前,Helm Chart 假定 S3 访问权限是通过附加到 Kubernetes 服务帐户的 IAM 角色提供的。如有需要,我们将来可能会添加对 API 访问密钥的支持。

操作方法:

以下是具体设置方法:

1. EKS 的 OIDC 提供商

请确保您的集群拥有 IAM OIDC 身份提供程序。如果没有,您可以使用以下命令(需要先eksctl安装):

aws eks describe-cluster --name cluster_name --query "cluster.identity.oidc.issuer" --output text`
Enter fullscreen mode Exit fullscreen mode

示例输出:

https://oidc.eks.region-code.amazonaws.com/id/EXAMPLED539D4633E53DE1B716D3041E

列出您帐户中的 IAM OIDC 提供程序。将“EXAMPLED539D4633E53DE1B716D3041E提供程序”替换为上一个命令返回的值。

aws iam list-open-id-connect-providers | grep EXAMPLED539D4633E53DE1B716D3041E
Enter fullscreen mode Exit fullscreen mode

示例输出

"Arn": "arn:aws:iam::111122223333:oidc-provider/oidc.eks.region-code.amazonaws.com/id/EXAMPLED539D4633E53DE1B716D3041E"

如果上一个命令返回了输出,则说明您的集群已经存在提供程序。如果没有返回输出,则必须使用以下命令创建 IAM OIDC 提供程序。请将 `<provider>` 替换cluster_name为您自己的值。

eksctl utils associate-iam-oidc-provider --cluster cluster_name --approve
Enter fullscreen mode Exit fullscreen mode

2. 创建存储桶访问的托管策略

创建一个名为 `<pucket_name>` 的 JSON 文件,policy.json其中包含相应的策略定义。例如,以下代码片段创建一个 JSON 文件,允许对名为 `<bucket_name>` 的存储桶进行完全访问my-kubernetes-bucket

read -r -d '' MY_POLICY <<EOF
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "s3:*",
            ],
            "Resource": [
                "arn:aws:s3:::my-kubernetes-bucket"
            ]
        }
    ]
}
EOF
echo "${MY_POLICY}" > policy.json
Enter fullscreen mode Exit fullscreen mode

运行以下命令创建托管策略:

aws iam create-policy --policy-name kubernetes-s3-access --policy-document file://policy.json
Enter fullscreen mode Exit fullscreen mode

示例输出:

{
"策略": {
"策略名称": "kubernetes-s3-access",
"策略 ID": "ANPAS3DOMWSIX73USJOHK",
"Arn": "arn:aws:iam::04968064045764:policy/kubernetes-s3-access",

记下保单 ARN,以便进行下一步操作。

3. 创建 S3 访问权限角色

使用以下命令将您的 AWS 账户 ID 设置为环境变量:

ACCOUNT_ID=$(aws sts get-caller-identity --query "Account" --output text)
Enter fullscreen mode Exit fullscreen mode

使用以下命令将 OIDC 身份提供程序设置为环境变量。请将示例值替换为您自己的值:

OIDC_PROVIDER=$(aws eks describe-cluster --name cluster-name --query "cluster.identity.oidc.issuer" --output text | sed -e "s/^https:\/\///")
Enter fullscreen mode Exit fullscreen mode

将以下代码块复制到您的计算机,并将示例值替换为您自己的值。

read -r -d '' TRUST_RELATIONSHIP <<EOF
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "Federated": "arn:aws:iam::${ACCOUNT_ID}:oidc-provider/${OIDC_PROVIDER}"
      },
      "Action": "sts:AssumeRoleWithWebIdentity",
      "Condition": {
        "StringEquals": {
          "${OIDC_PROVIDER}:sub": "system:serviceaccount:my-namespace:my-service-account"
        }
      }
    }
  ]
}
EOF
echo "${TRUST_RELATIONSHIP}" > trust.json
Enter fullscreen mode Exit fullscreen mode

运行上一步修改后的代码块,创建一个名为 . 的文件trust.json

运行以下 AWS CLI 命令创建角色:

aws iam create-role --role-name eks-otomounter-role --assume-role-policy-document file://trust.json --description "Mount s3 bucket to EKS"
Enter fullscreen mode Exit fullscreen mode

运行以下命令,将上一节中创建的 ARN 对应的 IAM 策略附加到您的角色:

aws iam attach-role-policy --role-name eks-otomounter-role --policy-arn=IAM_POLICY_ARN
Enter fullscreen mode Exit fullscreen mode

4. 最后——安装 S3 挂载器!

  • 将 Helm 仓库添加到您的仓库列表中:
helm repo add otomount https://otomato-gh.github.io/s3-mounter
Enter fullscreen mode Exit fullscreen mode
  • 检查其参数values.yaml
helm show values otomount/s3-otomount
Enter fullscreen mode Exit fullscreen mode

最后要设置的值是:

bucketName: my-bucket
iamRoleARN: my-role
mountPath: /var/s3
hostPath: /mnt/s3data
Enter fullscreen mode Exit fullscreen mode
  • 通过提供您自己的值来安装图表:
helm upgrade --install s3-mounter otomount/s3-otomount   \ 
--namespace otomount --set bucketName=<your-bucket-name> \
--set iamRoleARN=<your-role-arn> --create-namespace
Enter fullscreen mode Exit fullscreen mode

这将使用挂载的默认主机路径,即/mnt/s3data

5. 在部署中使用已挂载的 S3 存储桶。

以下是一个示例 Pod 定义,它为容器提供对已挂载存储桶的访问权限:

apiVersion: v1
kind: Pod
metadata:
  name: sleeper
spec:
  containers:
  - command:
    - sleep
    - infinity
    image: ubuntu
    name: ubuntu
    volumeMounts:
    - mountPath: /mydata:shared
      name: s3data
  volumes:
  - hostPath:
      path: /mnt/s3data
    name: s3data
Enter fullscreen mode Exit fullscreen mode

注意:shared- 这是字段中的挂载传播mountPath修饰符,允许同一节点上的多个 pod/容器共享此卷。

好了!现在你可以访问你的存储桶了。如果你已经按照我们的示例创建了 Pod,你可以执行以下命令进行验证:

kubectl exec sleeper -- ls /mydata
Enter fullscreen mode Exit fullscreen mode

注意:在集群上运行此程序会产生一些额外的费用,因为 goofys 会调用 S3 API 来维护挂载点。所以请务必监控您的云费用。不过,无论如何您都应该这样做,对吧?

送货愉快!

文章来源:https://dev.to/otomato_io/mount-s3-objects-to-kubernetes-pods-12f5