NVIDIA 初创加速计划,免费加速您的创业启动 了解详情
写点什么

AWS 系列:S3 不仅仅是存储

  • 2015-12-21
  • 本文字数:5195 字

    阅读完需:约 17 分钟

编者按:本文系 InfoQ 中文站向陈天的约稿,这是 AWS 系列文章的第二篇。以后会有更多文章刊出,但并无前后依赖的关系,每篇都自成一体。读者若要跟随文章来学习 AWS,应该至少注册了一个 AWS 账号,事先阅读过当期所介绍服务的简介,并在 AWS management console 中尝试使用过该服务。否则,阅读的效果不会太好。在这篇文章里,介绍了尝试用 S3 创建公司内部的文件服务器,保存员工私人 / 共享文件,并以类似 Dropbox 的方式双向同步。

S3 介绍

S3 是 AWS 最早发布的诸多服务之一,用作可信存储。所谓可信,AWS 给出的概念是:「在指定年度内为对象提供 99.999999999% 的持久性和高达 99.99% 的可用性」,换句话说就是任何存储于 S3 的数据基本不可能丢失,在一个年度内,不超过 1 小时(3153.6s)的宕机时间。除此之外,S3 还提供如下特性:

  • 跨区域复制:只需要简单的配置,存储于 S3 中的数据会自动复制到选定的不同区域中。当你的数据对象的收集分散在不同的区域,而处理集中在某些区域时非常有用。
  • 事件通知:当数据对象上传到 Amazon S3 中或从中删除的时候会发送事件通知。事件通知可使用 SQS 或 SNS 进行传送,也可以直接发送到 AWS Lambda 进行处理。比如说,上传到 S3 的图片的 resize。
  • 版本控制:数据对象可以启用版本控制,这样你就可以很方便地进行回滚。对于应用开发者来说,这是个特别有用的特性。
  • 加密:S3 的访问本身是支持 SSL(HTTPS)的,保证传输的安全,对于数据本身,你可以通过 Server side encryption(AES256)来加密存储在 S3 的数据。
  • 访问管理:通过 IAM/VPC 可以控制 S3 的访问粒度,你甚至可以控制一个 bucket(S3 对数据的管理单元,一个 bucket 类似于一组数据的根目录)里面的每个 folder,甚至每个文件的访问权限。
  • 可编程:可以使用 AWS SDK 进行客户端或者服务端的开发。
  • 成本监控和控制:S3 有几项管理和控制成本的功能,包括管理成本分配的添加存储桶标签和接收账单警报的 Amazon Cloud Watch 集成。
  • 灵活的存储选项:除了 S3 Standard,还有低成本的 Standard – Infrequent Access 选项可用于非频繁访问数据,存储的价格大概是 Standard 的 2/5。至于那些访问不了多少次的冷数据(如 1 年前的 Log),可以存储在 Glacier 中,价格在 Standard 的 1/4(1T $7/ 月),缺点是需要几个小时来恢复数据(估计是存放于离线的磁带中)。

基本用法

S3 的用户可以使用 AWS management console 来创建 bucket(类比文件系统的根目录),以及 bucket 内部的目录树,并上传文件,但这不是使用 S3 的最佳方式。日常的主要操作应该使用 AWS CLI 和 AWS SDK 完成。

AWS CLI

安装 AWS CLI 可以使用 pip / brew 等安装工具,不再详述。AWS CLI 是 AWS 官方提供的 CLI 工具,简单好用,我会另行撰文深度介绍 AWS CLI。AWS CLI 目前不支持命令和参数的自动补全,从 AWS re:invent 2015 透露出来的信息,其团队在做一些自动补全的尝试,未来会变得更加人性化。如果你想现在就用得更舒服一些,可以使用 sAws

使用 AWS CLI 操作 S3 非常简单,创建 / 删除 bucket 可以使用 aws s3api

复制代码
$ aws s3api create-bucket --bucket <name>
$ aws s3api delete-bucket --bucket <name>

如果要像一般的文件系统一样操作 S3,可以使用 aws s3 命令:

复制代码
$ aws s3 ls
$ aws s3 cp
$ aws s3 rm

此外,aws s3 还提供了 sync,方便本地文件和 S3 上的文件互相 sync,比如我本地用 pandoc 编译出了 markdown 撰写的 reveal.js 的 slides,可以这样同步到 S3:

$ aws s3 sync ./output s3://eng-assets/slides### AWS SDK

AWS SDK 提供了对几乎所有主流语言的支持,在程序里使用 S3,一般的流程是:

  • 创建 AWS connection(这一步需要用到你的 access key)。
  • 使用 connection 创建 S3 对象。
  • 使用 S3 API 进行各种 API 操作,比如创建 bucket,上传文件等。

这里列一个 JavaScript 的例子:

复制代码
const aws = require('aws-sdk');
const Promise = require("bluebird");
const s3 = Promise.promisifyAll(new aws.S3());
s3.createBucketAsync({Bucket: 'test-myBucket'}).then(function() {
var params = {Bucket: 'test-myBucket', Key: 'myKey', Body: 'Hello!'};
s3.putObjectAsync(params).then(function(data) {
console.log('successfully uploaded data');
}).error(function(err) {
console.log(err);
})
});

使用 S3 的典型场景

S3 的一些典型使用场景如下:

  • 存储用户上传的文件,如头像,照片,视频等静态内容。
  • 当作一个的 key value store,承担简单的数据库服务功能。
  • 数据备份。
  • 静态网站的托管:你可以对一个 bucket 使能 Web Hosting。

我们简单介绍一下 S3 实现静态网站托管,然后以一个例子讲述如何使用 S3 实现一个能最大程度保证数据安全同时又价格低廉的团队内部的文件服务器。

使用 S3 实现安全的静态网站托管

经常使用 GitHub 的朋友对 GitHub pages 服务一定不会陌生,你只要把各种静态网站生成工具的生成的目标放入 gh-pages 的 branch,GitHub pages 就会帮你做静态网站的托管。得益于如今越来越强大的 JavaScript 和各种 API,静态网站其实早已脱离了展示 HTML 的基本范畴。

GitHub pages 有一个缺点就是,只要你使用,它就是开放的,无法变成一个私有网站,存放公司内部的私密文件。公司内部的一些私有内容,比如:

  • 使用 reveal.js 生成的 slides。
  • 使用 new relic 生成的各种嵌入式报表和图表。
  • 使用 JavaScript + AWS SDK 做的各种内部工具(由于 AWS SDK 提供了 JavaScript SDK,所以你可以用静态网站的方式访问数据库等服务,实现 server less 的效果)。

你无论如何都不会想将其暴露给外界。这个时候,GitHub pages 就不适用,我们可以使用 S3 Web Hosting + IAM policy 来完成。

使能 S3 Web Hosting 是件很简单的事情,只需在 AWS console 中,为对应的 bucket 打开这个选项即可,然后添加如下 IAM policy:

复制代码
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "PublicReadGetObject",
"Effect": "Allow",
"Principal": "*",
"Action": "s3:GetObject",
"Resource": "arn:AWS:s3:::team-assets/*"
}
]
}

S3 Web Hosting 会告诉你一个用于访问的域名,你也可将你自己的私有域名指定一个 CNAME 指向该域。这样配置下来,只要域名和要访问的文件夹没有暴露,文件内容就是安全的。适用于安全等级不高的内容。

如果需要更高的安全级别,可以配合 VPC + IAM policy。一般而言,使用 VPC 的用户,都会将 VPC 设置成私有网络(比如 10.0.0.x 的网络),然后在网络边界配置一台 VPN 服务器,用于内外网的交互。任何用户要访问内网,必须先接入 VPN。我们可以设置用于 Web Hosting 的 S3 的 bucket 的 IAM 仅允许 VPN 服务器的 IP 访问,如下:

复制代码
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "PublicReadGetObject",
"Effect": "Allow",
"Principal": "*",
"Action": "s3:GetObject",
"Resource": "arn:AWS:s3:::team-assets/*",
"Condition" : {
"IpAddress" : {
"aws:SourceIp" : ["5.5.5.5/32"]
}
}
}
]
}

那么,只用当用户接入 VPN 之后,才能访问 Web Hosting 的域名下的文件,进一步提高了安全性。当然,由于不是在路由层面控制访问,所以没办法防止 ip spoofing,还是有一些潜在风险的,不过风险不大(攻击者需要知道要访问的文件所在的域名和路径,并且知道仅允许哪个源 IP 访问,进而进行 IP spoofing,而公网上 IP spoofing 的难度很大,基本上所有的路由器都会做 reverse route check)。

使用 S3 实现文件服务器

很多公司都会为员工提供私人和共享的文件存储。比如作为一个用户,我可以把我的私人文件存放在:fileserver://home/tyrchen/* 下,把一些共享文件存放在 fileserver://public/tyrchen/* 下。为了能够安全的存储这些文件,公司的 IT 部门一般会使用昂贵的 SAN(Storage Area Network)来保证一定程度的 SLA(Service Level Agreement),同时,还要做各种各样的备份(和恢复)。如果我们使用 S3 来实现类似的文件服务器,其代价和未来的维护成本会小得多。此外,我们还可以做一些额外的开发,使得文件服务器的使用体验类似于 Dropbox。

大致的想法是这样的:

  • 新员工入职后会为其在 S3 上建立 home folder,用来保存重要的私人文件和共享文件。
  • 员工电脑的本地文件中会有一个目录 corp-fs-box,里面包含三个子目录:
    • private:存放任意文件,私有,会自动 sync 到私人目录,别人无法访问。
    • photos:存放各种媒体文件,公开,会自动 sync 到共享目录,并生成合适的尺寸放在供 Web 访问的 S3 bucket 中。
  • 员工只要在本地目录中存放文件,就会按照上述规则自动同步,类似 Dropbox。

解决思路:

  • 创建两个 S3 bucket:corp-fs-team 和 corp-fs-web。corp-fs-web 打开 Web Hosting 功能。
  • 使用 IAM policy 来设置 home folder 的权限。
  • 使用 aws s3sync 来同步文件夹:
    • 对本地 corp-fs-box/private 里的文件,同步到 S3://corp-fs-team/home/{AWS:username}/ 中。这个目录只有当前用户可以访问,其他用户不能访问。
    • 对本地 corp-fs-box/pub/photos 里的文件,同步到 S3:web//corp-fs-team/pub/photos 中。这个目录任何用户都可以访问并修改。
  • S3 配置 Events,使得对于 S3://corp-fs-team/pub/photos/{AWS:username}/ 的任何更新行为(添加 / 删除)都会触发 lambda 函数。
  • lambda 函数扫描上传的文件,如果是 *.jpg 或者 *.mp4 / *.mov,则将其进行 resize / transcoding 等处理,并将编译的结果放在 S3://corp-fs-web/pub/photos/{AWS:username}/* 下,供内网的用户浏览。

涉及的 IAM policy 如下:

复制代码
{
"Version": "2012-10-17",
"Statement": [{
"Sid": "AllowGroupToSeeBucketList",
"Action": ["s3:ListAllMyBuckets", "s3:GetBucketLocation"],
"Effect": "Allow",
"Resource": ["arn:AWS:s3:::*"]
}, {
"Sid": "AllowRootLevelList",
"Action": ["s3:ListBucket"],
"Effect": "Allow",
"Resource": ["arn:AWS:s3:::corp-fs-team"],
"Condition": {
"StringEquals": {
"s3:prefix": ["", "home/"],
"s3:delimiter": ["/"]
}
}
}, {
"Sid": "AllowListForUserPrefix",
"Action": ["s3:ListBucket"],
"Effect": "Allow",
"Resource": ["arn:AWS:s3:::corp-fs-team"],
"Condition": {
"StringLike": {
"s3:prefix": ["home/${AWS:username}/*"]
}
}
}, {
"Sid": "AllowUserFullAccessToUserPrefix",
"Action": ["s3:*"],
"Effect": "Allow",
"Resource": [
"arn:AWS:s3:::corp-fs-team/home/${AWS:username}",
"arn:AWS:s3:::corp-fs-team/home/${AWS:username}/*"
]
}
]
}

以及访问 pub 目录的 IAM policy:

复制代码
{
"Version": "2012-10-17",
"Statement": [{
"Sid": "AllowPublicLevelList",
"Action": ["s3:ListBucket"],
"Effect": "Allow",
"Resource": ["arn:AWS:s3:::corp-fs-team-bucket"],
"Condition": {
"StringLike": {
"s3:prefix": ["pub/*"]
}
}
}, {
"Sid": "AllowUserFullAccessToPublicPrefix",
"Action": ["s3:*"],
"Effect": "Allow",
"Resource": [
"arn:AWS:s3:::corp-fs-team-bucket/pub",
"arn:AWS:s3:::corp-fs-team-bucket/pub/*"
]
}
]
}

具体的 lambda 函数不在本文讨论的范围之内。

除此之外,我们还需要一个类似于 Dropbox 的客户端软件来监控本地目录(S3 目录)的更改,以便在合适的时候进行同步。思路如下:

  • 客户端软件做成一个开机启动的 daemon。
  • 随时监控本地目录 corp-fs-box/* 和 S3 bucket 的修改,并按上述规则同步。

由于涉及的目录都是个人目录,不太会产生冲突(除非同一用户在多个 device 下载没有 sync 的前提下修改同一文件。所以在这里,为简单起见,我们可以不涉及到 diff / merge,简单遵循 last writer wins 进行处理就可以了。另外 S3 自带 versioning,也可以使能这一功能,保存历史版本,在冲突发生的时候,让用户选择。

小结

S3 是一个非常强大的文件服务,如果使用得当,可以带来非常大的收益,建议大家多多深入研究。AWS 的很多服务,如 Elastic Beanstalk,Elastic Transcoder,CloudFormation 实际上都在使用 S3 作为服务的关键一环。


感谢魏星对本文的审校。

给InfoQ 中文站投稿或者参与内容翻译工作,请邮件至 editors@cn.infoq.com 。也欢迎大家通过新浪微博( @InfoQ @丁晓昀),微信(微信号: InfoQChina )关注我们,并与我们的编辑和其他读者朋友交流(欢迎加入 InfoQ 读者交流群(已满),InfoQ 读者交流群(#2))。

2015-12-21 17:1718165

评论

发布
暂无评论
发现更多内容

数据库周刊32丨Oracle自治数据库大动作;腾讯云MySQL 8.0上线;华为数据库工程师认证发布;update引起业务卡顿;PostgreSQL安全加固;openGauss单机安装;中国DBA联盟"ACDU"邀您加入……

墨天轮

MySQL 数据库 oracle postgresql

统一物品编码 破解追溯“断链”困局

CECBC

三大 OSS 缓存加速系统巅峰对决

苏锐

hadoop cache JuiceFS JindoFS Performance

《中国区块链产业园15强名录》

CECBC

MySql的Dockerfile编写

玏佾

一口气讲透一致性哈希(Hash),助力「码农变身」

码农神说

一致性算法 一致性哈希 一致性hash 一致性Hash算法

抢滩新基建,百度还会输给阿里和腾讯吗?

ToB行业头条

【融云分析】融云实时音视频 SDK 对智能硬件的视频适配

Geek_116789

我的程序跑了60多小时,就是为了让你看一眼JDK的BUG导致的内存泄漏。

why技术

Java 源码 jdk 并发 bug

腾讯的ToB梦想

ToB行业头条

为什么单元测试不是持续交付的唯一答案

禅道项目管理

持续集成 单元测试

​中国SaaS处在什么阶段?

ToB行业头条

Redis基础:redis特点

古月木易

redis

2020,是中国SaaS行业的机遇之年?

ToB行业头条

讲烂了的mysql,今天再给大家重温一下

爱嘤嘤嘤斯坦

Java MySQL 数据库 编程 mysql事务

女员工被阿里录取工资二万六,辞职时被领导挽留:给你4万留下

程序员生活志

程序员 阿里

Worktile完成新一轮融资,将发力研发管理赛道

Worktile

融资

微信小程序使用GoEasy实现websocket实时通讯

GoEasy消息推送

小程序 websocket 即时通讯

啃碎并发(10):内存模型之内部原理

猿灯塔

阿里拍卖,能不能拍到点儿上?

ToB行业头条

猿灯塔:spring Boot Starter开发及源码刨析(四)

猿灯塔

Java 猿灯塔 spring Boot Starter

你有认真了解过自己的“Java对象”吗

大头星

Java JVM

Redis基础:redis特点

奈学教育

redis

架构师是怎样炼成的 6-1

闷骚程序员

解读:新基建为区块链带来的新机遇

CECBC

火焰图:全局视野的Linux性能剖析

Marionxue

话题讨论|在编程中,有哪些好习惯是应该一直坚持下去的?

InfoQ写作社区官方

写作平台 话题讨论 话题

企业的数字化转型探索

松子(李博源)

企业架构 数字化 企业数字化转型

将设计模式应用到日常的curd中—分离关联查询

LSJ

Java 设计

Spring Boot 2.3.0正式发布:优雅停机、配置文件位置通配符新特性一览

YourBatman

spring springboot

吴恩达推荐笔记:22张图总结深度学习全部知识

程序员生活志

学习 吴恩达

AWS系列:S3不仅仅是存储_服务革新_陈天_InfoQ精选文章