亚马逊AWS官方博客

利用S3fs在Amazon EC2 Linux实例上挂载S3存储桶

背景介绍

Amazon S3是互联网存储解决方案,能让所有开发人员访问同一个具备可扩展性、可靠性、安全性和快速价廉的数据存储基础设施。Amazon S3 提供了一个简单 Web 服务接口,可用于随时在 互联网上的任何位置存储和检索任何数量的数据。开发人员可以利用Amazon提供的REST API接口,命令行接口或者支持不同语言的SDK访问S3服务。

对于原来使用本地目录访问数据的应用程序,比如使用本地磁盘或网络共享盘保存数据的应用系统,如果用户希望把数据放到S3上,则需要修改数据的访问方式,比如修改为使用AWS SDK 或CLI访问S3中存储的数据。为了让用户原来的应用系统能在不做修改的情况下直接使用Amazon S3服务,需要把S3存储桶作为目录挂载到用户服务器的本地操作系统上。常用的挂载工具有S3fs和SubCloud等。本文主要介绍如何利用S3fs将S3存储桶挂载到Amazon EC2 Linux实例上。

S3fs介绍

S3fs是基于FUSE的文件系统,允许Linux和Mac Os X 挂载S3的存储桶在本地文件系统,S3fs能够保持对象原来的格式。关于S3fs的详细介绍,请参见:https://github.com/s3fs-fuse/s3fs-fuse

利用S3fs挂载S3存储桶

一、准备

  1. 使用拥有足够权限的IAM账号登录AWS控制台。
  2. 创建S3存储桶,给存储桶命名如“s3fs-mount-bucket”(如果使用已有存储桶,本步骤可略过)。

     3. 创建具有该S3存储桶访问权限的 IAM 用户,并为该IAM用户创建访问密钥。

a) 关于如何创建IAM用户,请参见:http://docs.aws.amazon.com/zh_cn/IAM/latest/UserGuide/id_users_create.html#id_users_create_console

b) 关于如何为IAM用户创建访问密钥,请参见:http://docs.aws.amazon.com/zh_cn/IAM/latest/UserGuide/id_credentials_access-keys.html

c) 关于如何为IAM用户设置权限策略,请参见:http://docs.aws.amazon.com/zh_cn/IAM/latest/UserGuide/access_policies_create.html

https://aws.amazon.com/cn/blogs/security/writing-iam-policies-how-to-grant-access-to-an-amazon-s3-bucket/

4. 创建并启动Amazon EC2 Linux实例

具体过程请参见:http://docs.aws.amazon.com/zh_cn/AWSEC2/latest/UserGuide/launching-instance.html

二、安装和配置S3fs

  1. 安装s3fs

a) 使用Amazon EC2默认用户“ec2-user”和对应的私钥文件登录启动的Linux实例(请注意将下边例子中的私钥文件和ec2实例域名替换为用户自己的值)

ssh -i /path/my-key-pair.pem ec2-user@ec2-198-51-100-1.compute-1.amazonaws.com

b) 安装必要的软件包

sudo yum install automake fuse fuse-devel gcc-c++ git libcurl-devel libxml2-devel make openssl-devel

c) 下载,编译并安装s3fs

git clone https://github.com/s3fs-fuse/s3fs-fuse.git

cd s3fs-fuse

./autogen.sh

./configure

make

sudo make install

d) 检查s3fs是否安装成功

[ec2-user@ip-172-31-23-148 s3fs-fuse]$ s3fs

s3fs: missing BUCKET argument.

Usage: s3fs BUCKET:[PATH] MOUNTPOINT [OPTION]...

 

[ec2-user@ip-172-31-23-148 ~]$ which s3fs

/usr/local/bin/s3fs

2. 创建IAM用户访问密钥文件

  • IAM用户访问密钥内容可以写入当前用户默认密钥文件比如“/home/ec2-user/.passwd-s3fs”或者用户自己创建的文件。
  • 命令格式:echo [IAM用户访问密钥ID]:[ IAM用户访问密钥] >[密钥文件名]
  • 命令举例:下面的例子将在当前用户默认路径创建密钥文件

echo AKIAIOEO4E2VOHLxxxxx:2LXBboddEpRLmWl48i3+b4ziwPL3bJ4vxxxxxxxx > /home/ec2-user/.passwd-s3fs

请注意:访问海外AWS S3服务和中国 S3服务使用的是不同的IAM账号,对应不同的密钥。

3. 设置密钥文件只能够被当前用户访问

  • 命令格式:chmod 600  [密钥文件名]
  • 命令举例:下面的例子将设置密钥文件只能被当前用户访问

chmod 600 /home/ec2-user/.passwd-s3fs

三、手动挂载S3存储桶

S3fs挂载存储桶使用的命令是s3fs

s3fs的命令格式是:

  • s3fs BUCKET MOUNTPOINT [OPTION]…
  • s3fs [S3存储桶名] [本地目录名] [OPTION]
  • OPTION是可选项,格式是 –o <option_name>=<option_value>,常用的options有:
     名称 含义 缺省值
    passwd_file 指定挂载的密钥文件
    connect_timeout 设置超时连接等待的时间,单位秒 300
    url 设置访问s3的url http://s3.amazonaws.com
    endpoint 设置s3存储桶的endpoint us-east-1
    allow_other 设置allow_other允许所有用户访问挂载点目录,设置这个选项需要在 /etc/fuse.conf 文件添加user_allow_other选项

手动挂载AWS海外区域S3存储桶

  • 命令格式:s3fs [S3存储桶名] [本地目录名] -o passwd_file=[密钥文件名] -o endpoint=[区域名]

命令举例:下面的例子将名为“s3fs-mount-bucket”的新加坡区域S3存储桶挂载到指定的本地目录“/home/ec2-user/s3mnt”。

s3fs s3fs-mount-bucket /home/ec2-user/s3mnt -o passwd_file=/home/ec2-user/.passwd-s3fs -o endpoint=ap-northeast-1

手动挂载AWS中国北京区域S3存储桶

  • 命令格式:s3fs [S3存储桶名] [本地目录名] -o passwd_file=[密钥文件名] -o url=http://s3.cn-north-1.amazonaws.com.cn -o endpoint=cn-north-1
  • 命令举例:下面的例子将名为“s3fs-mount-bucket”的北京区域S3存储桶挂载到本地目录“/home/ec2-user/s3mnt”。

s3fs s3fs-mount-bucket /home/ec2-user/s3mnt -o passwd_file=/home/ec2-user/.passwd-s3fs -o url=http://s3.cn-north-1.amazonaws.com.cn -o endpoint=cn-north-1

检查挂载结果

  • 挂载操作执行结束后,可以使用Linux “df”命令查看挂载是否成功。出现类似下面256T的s3fs文件系统即表示挂载成功。用户就可以进入本地挂载目录去访问存储在S3存储桶中的对象。

[ec2-user@ip-172-31-23-148 ~]$ df -h

文件系统        容量  已用  可用 已用% 挂载点

devtmpfs        488M   56K  488M    1% /dev

tmpfs           498M     0  498M    0% /dev/shm

/dev/xvda1      7.8G  1.2G  6.6G   15% /

s3fs            256T     0  256T    0% /home/ec2-user/s3mnt

 

[ec2-user@ip-172-31-23-148 ~]$ cd /home/ec2-user/s3mnt

[ec2-user@ip-172-31-23-148 s3mnt]$ ls -l

总用量 1

-rw-rw-r-- 1 ec2-user ec2-user 19 10月 18 07:13 a.txt

[ec2-user@ip-172-31-23-148 s3mnt]$

卸载挂载的S3存储桶

  • 如果不再需要通过挂载方式访问S3存储桶,可以使用Linux “umount”命令卸载。

[ec2-user@ip-172-31-23-148 ~]$ sudo umount /home/ec2-user/s3mnt

[ec2-user@ip-172-31-23-148 ~]$ df -h

文件系统        容量  已用  可用 已用% 挂载点

devtmpfs        488M   56K  488M    1% /dev

tmpfs           498M     0  498M    0% /dev/shm

/dev/xvda1      7.8G  1.2G  6.6G   15% /

调试

如果遇到手动挂载不成功的问题,请尝试在执行的命令后面添加下面的参数,并检查输出日志中的错误提示信息:

  • 命令格式:[完整的s3fs挂载命令] -d -d -f -o f2 -o curldbg
  • 命令举例:下面的例子试图将名为“s3fs-mount-bucket”的S3存储桶挂载到指定的本地目录“/home/ec2-user/s3mnt”下,并输出挂载过程详细调试日志。

[ec2-user@ip-172-31-23-148 ~]$ s3fs s3fs-mount-bucket /home/ec2-user/s3mnt -o passwd_file=/home/ec2-user/.passwd-s3fs -o url=http://s3.cn-north-1.amazonaws.com.cn -o endpoint=cn-north-1 -d -d -f -o f2 -o curldbg

[CRT] s3fs.cpp:set_s3fs_log_level(254): change debug level from [CRT] to [INF]

[CRT] s3fs.cpp:set_s3fs_log_level(254): change debug level from [INF] to [DBG]

[INF]     s3fs.cpp:set_moutpoint_attribute(4196): PROC(uid=500, gid=500) - MountPoint(uid=500, gid=500, mode=40775)

FUSE library version: 2.9.4

nullpath_ok: 0

nopath: 0

utime_omit_ok: 0

四、设置开机自动挂载S3存储桶

A. 创建全局IAM用户访问密钥文件

切换Linux系统用户账号到“root”用户,把IAM用户访问密钥内容写入/etc/passwd-s3fs文件中,并限制该文件的访问权限。“/etc/passwd-s3fs”文件是s3fs保存IAM用户访问密钥的全局默认路径。

请注意:访问海外AWS S3服务和中国 S3服务使用的是不同的IAM账号,对应不同的密钥。

sudo su

echo AKIAIOEO4E2VOHLxxxxx:2LXBboddEpRLmWl48i3+b4ziwPL3bJ4vxxxxxxxx > /etc/passwd-s3fs

chmod 600 /etc/passwd-s3fs

B. 修改/etc/fstab文件

编辑/etc/fstab文件,添加后面的自动挂载命令。

vi /etc/fstab

B.1 自动挂载海外区域S3存储桶

  • 命令格式:s3fs#[S3存储桶名] [本地目录名] fuse _netdev,allow_other,endpoint=[区域名] 0 0
  • 命令举例:添加下面的语句到/etc/fstab后,Linux系统启动后将自动把名为“s3fs-mount-bucket”的新加坡区域S3存储桶挂载到本地目录“/home/ec2-user/s3mnt”,并允许其它操作系统用户(非root用户)访问。

/usr/local/bin/s3fs#s3fs-mount-bucket /home/ec2-user/s3mnt fuse _netdev,allow_other,endpoint=ap-northeast-1 0 0

B.2 自动挂载中国北京区域S3存储桶

  • 命令格式:s3fs#[S3存储桶名] [本地目录名] fuse allow_other,url=http://s3.cn-north-1.amazonaws.com.cn,endpoint=cn-north-1 0  0
  • 命令举例:添加下面的语句到/etc/fstab后,Linux系统启动将自动把名为“s3fs-mount-bucket”的北京区域S3存储桶挂载到本地目录“/home/ec2-user/s3mnt”下,并允许其它操作系统用户(非root用户)访问。

/usr/local/bin/s3fs#s3fs-mount-bucket /home/ec2-user/s3mnt fuse allow_other,url=http://s3.cn-north-1.amazonaws.com.cn,endpoint=cn-north-1 0  0

局限性

利用S3fs可以方便的把S3存储桶挂载在用户本地操作系统目录中,但是由于S3fs实际上是依托于Amazon S3服务提供的目录访问接口,所以不能简单的把S3fs挂载的目录和本地操作系统目录等同使用。用户使用S3f3挂载S3存储桶和直接访问S3服务有类似的使用场景。适用于对不同大小文件对象的一次保存(上传),多次读取(下载)。不适用于对已保存文件经常做随机修改,因为每次在本地修改并保存文件内容都会导致S3fs上传新的文件到Amazon S3去替换原来的文件。从访问性能上来说,通过操作系统目录方式间接访问Amazon S3存储服务的性能不如直接使用SDK或CLI接口访问效率高。以本地配置文件方式保存访问密钥的安全性也不如使用EC2 IAM角色方式高。

关于S3fs使用时候需要注意的更多细节,请参考下面s3fs官网内容:

 

“Generally S3 cannot offer the same performance or semantics as a local file system. More specifically:

  • random writes or appends to files require rewriting the entire file
  • metadata operations such as listing directories have poor performance due to network latency
  • eventual consistency can temporarily yield stale data
  • no atomic renames of files or directories
  • no coordination between multiple clients mounting the same bucket
    no hard links ”

通常S3不能提供与本地文件系统相同的性能或语义。进一步来说:

  • 随机写入或追加到文件需要重写整个文件
  • 元数据操作比如列出目录会因为网络延迟原因导致性能较差
  • 最终一致性设计可能临时导致过期数据
  • 没有对文件或目录的原子重命名功能
  • 挂载相同存储桶的多个客户端之间没有相互协调机制
  • 不支持硬链接

总结

利用S3fs可以把共享的Amazon S3存储桶直接挂载在用户服务器本地目录下,应用不需要做修改就可以直接使用Amazon S3存储服务,这种方式可以作为临时解决方案将传统应用快速迁移到AWS平台。

在已经提供了Amazon EFS(Elastic File System)服务的AWS区域,建议用户优先考虑使用Amazon EFS服务,因为它具有更高的性能。在目前还没有提供EFS服务的AWS区域,用户可以先暂时使用S3fs实现快速业务迁移。然后逐步调整S3数据访问实现方式,最终修改为使用AWS SDK或CLI方式高效并更加安全地访问S3存储服务。

 

作者介绍:

蒙维

亚马逊AWS解决方案架构师,负责基于AWS的云计算方案架构咨询和设计,有超过十年以上电信行业和移动互联网行业复杂应用系统架构和设计经验,主要擅长分布式和高可用软件系统架构设计,移动互联网应用解决方案设计,研发机构DevOps最佳实施过程。