点赞
评论
收藏
分享
举报
使用 NGINX 作为对象存储网关
发表于2022-06-29 11:14

浏览 1.1k

原文作者:Elijah Zupancic of F5
原文链接:使用 NGINX 作为对象存储网关 - NGINX
转载来源:NGINX 官方网站



您是否曾经不小心发错了链接,它不是链接到您的 CDN 中的文件,而是链接到了像是 Amazon S3 这样的对象存储中的文件,而且这个链接还被大量传播使用?您是否被随之而来的飙升的云服务成本吓了一跳,或者您的云提供商甚至切断了链接?如果答案是“是”,那么本文正适合您。本文将介绍如何将 NGINX 作为缓存网关前置于 S3 私有存储桶,从而在您的私有存储桶和公共互联网之间建立一层保护。这种做法有两个优点:NGINX 会缓存对您的对象存储的请求,同时还能防止对象存储中的内容暴露给公网。


关于 Amazon S3 和兼容的存储产品

虽然 Amazon S3 是亚马逊云科技(AWS)的专有产品,但在事实层面,它已然成为对象存储系统的标准接口,许多厂商都提供了与之兼容的存储产品,例如 BackblazeDigital OceanGoogle StorageMinioNetAppNutanixTencent CloudVMware 和 Wasabi 等。尽管 S3 API 被大范围支持,但 S3 API 的具体实现通常不太适合非存储操作,比如不适合支持大量的公共互联网流量。于是人们就产生了这样一个共同的需求:在 S3 API 的前面加设一层,以将存储接口桥接到另一个应用或特定用户接口。NGINX 可以充当此桥梁,并通过它的模块生态系统和可配置性创造额外的价值。

本文将通过探索一个托管在 GitHub 上功能完整的 Docker 实现(我们也提供了一个独立的 Ubuntu 安装实例),展示如何将 NGINX 开源版和 NGINX Plus 配置为一个与 S3 兼容的对象存储的只读网关。虽然本文只介绍如何将 NGINX 设置为与 S3 兼容的服务的网关,但您可以将这种方法延伸应用到任何 AWS API 请求的签署


用例

您可能会纳闷,“我的对象存储已经在大规模为文件提供服务了,何必在前面又多加一层呢?

答案很简单:S3 等对象存储只擅长一件事情 —— 存储和检索对象。而 NGINX 是一个高度可配置的反向代理,能够在作为基础对象存储网关的前提下提供更多功能。因此,它可以很好地支持多种用例,其中包括以下这些典型用例。

高速缓存

安全控制

虽然 S3 有自己的身份验证和基于策略的访问系统,但不一定能满足您特定的身份验证需求。NGINX 支持多种不同的安全控制因此作为网关的它可以提供符合这些需求的身份验证和访问控制。您甚至可以使用安全链路模块创建带签名的链接!

访问内部应用

基于 AWS 签名的身份验证并不好实现,许多应用和平台都没有支持与 S3 轻松通信的客户端库。通过将 NGINX 用作访问 S3 的内部服务的网关,这些应用无需生成 AWS 签名便可轻松访问 S3 资源。

压缩和内容优化

您可能希望压缩对象存储中的数据以节省存储成本,但仍然能够为不支持压缩的客户端提供内容。在这种情况下,您可以配置 NGINX 使其在数据发送之前对其进行实时解压缩处理

又或者,您可能会在对象存储中存储未压缩的内容,然后希望通过在传输之前压缩数据来缩短传输时间。在这种情况下,您可以配置内置的 Gzip 模块或 Brotli 动态模块,以缩短到终端用户的传输时间。

NGINX 还支持其他类型的实时内容修改,例如 Image-Filter 动态模块可以转换 GIF、JPEG 和 PNG 图像,PageSpeed 等工具能够将 Web 性能的最佳实践自动应用到页面和相关多媒体资源,从而缩短页面加载时间。(在撰写本文时,Pagespeed 网站表示 Pagespeed“正处于 Apache 软件基金会孵化阶段”。实际上,谷歌也开发了同样成熟的代码,请参阅我们博客上的《使用 NGINX Plus 的 Google PageSpeed 动态模块优化您的网站》文章。)

安全性

NGINX 允许您在 S3 API 前面构建另一个安全层,从而可以对发出过多下载请求的用户进行速率限制、限制存储桶内可以访问的对象路径等。您还可以使用 F5 NGINX App Protect WAF 或 NGINX ModSecurity WAF 等集成式 Web 应用防火墙 (WAF) 保护 S3 API。

应用网关

从站点提供内容时,对所有资源使用同一域名来满足安全、品牌、一致性和可移植性的要求十分常见。因此,从同一主机同时提供静态和动态内容也是常有的需求。当被用作 S3 API 网关时,NGINX 不仅可以从对象存储中提供静态文件,而且还可以针对来自应用服务器的动态内容请求提供代理和负载均衡功能。


特性和限制

本文探讨的 NGINX S3 网关实现具有以下特性和限制:

  • 支持 AWS 签名版本 2 和 版本 4
  • 仅支持 GET 和 HEAD 请求
  • 支持 NGINX 开源版和 NGINX Plus
  • 支持单个存储桶
  • 缓存时长:1 小时
  • 未配置 SSL/TLS
  • 默认情况下未安装 WAF
  • 默认情况下未启用压缩(例如 GZIP 或 Brotli)
  • 代理缓冲设置为默认值(您可以根据您的工作负载和对象大小修改这些设置)

在 Docker 中配置和运行 NGINX 网关

NGINX 开源版和 NGINX Plus 均可用作 S3 的网关或与 S3 兼容的对象存储的网关。

如需使用 NGINX 开源版,请先从 Docker Hub 下载 NGINX 官方镜像,并从 GitHub 上获取我们提供的 Dockerfile,然后创建 NGINX 配置文件

使用 NGINX Plus 作为 S3 API 网关则具有一些额外吸引人的优势:

  • 使用 NGINX Plus API 以进行动态上游 DNS 解析 —— 无论何时,只要 S3 API 域更改对应的 IP 地址,NGINX 就会自动重新配置以使用新的地址。这个功能很重要,因为 Amazon S3 和其他与 S3 兼容的 API 有时会为了更好地扩展系统而添加或删除负载均衡器。如果 DNS 更改后未重新加载上游的 NGINX 配置,那么一旦所有对应 IP 地址记录不再有效,就会导致服务中断。
  • 使用键值存储减少时间和资源消耗 —— 当生成 AWS 版本 4 的认证签名时,部分加密签名(签署密钥)有效且可缓存长达 24 小时。通过将这一部分签名存储在键值存储中,计算身份验证请求所需的总体时间和 CPU 资源就会有所减少。这对具有大量请求的用例来说是一项非常实用的性能增强特性。有关相关用例的配置示例,请参阅《为 SSL 存储配置 NGINX Plus 键值存储》一文。

我们不提供 NGINX Plus 的 Docker 镜像,因为镜像需包含您的 NGINX Plus 使用凭证。请使用我们提供的 Dockerfile(其中包含下载 NGINX Plus 二进制文件的相关设置),按照下一节的说明构建 NGINX Plus Docker 镜像。

构建 NGINX Plus 网关 Docker 镜像

如需构建 NGINX Plus Docker 镜像,请执行以下步骤:

  1. 从我们的 GitHub 仓库中克隆 NGINX S3 网关项目
git clone https://github.com/nginxinc/nginx-s3-gateway.git

2. 进入目录 nginx-s3-gateway

cd nginx-s3-gateway

3. 将 NGINX Plus 证书和密钥(nginx-repo.crt 和 nginx-repo.key)复制到 plus/etc/ssl/nginx 子路径。关于证书和密钥,NGINX Plus 客户请前往 F5 客户门户下载,NGINX Plus 免费试用版用户可从试用包中找到。

4. 构建容器镜像。我们建议使用 Docker BuildKit,因为它能让您将 NGINX Plus 的使用许可文件传递到 Docker 以构建上下文,同时避免数据暴露的风险以及 Docker 构建层之间的数据持久化问题。

  • 如使用 BuildKit 构建,请运行以下命令:
DOCKER_BUILDKIT=1 docker build -f Dockerfile.buildkit.plus -t nginx-plus-s3-gateway --secret id=nginx-crt,src=plus/etc/ssl/nginx/nginx-repo.crt --secret id=nginx-key,src=plus/etc/ssl/nginx/nginx-repo.key --squash .
  • 如不使用 BuildKit 构建,请运行以下命令:
docker build -f Dockerfile.plus -t nginx-plus-s3-gateway .

5. 继续创建 NGINX 配置文件

创建 NGINX 配置文件

如要启动和运行 NGINX 网关(NGINX 开源版或 NGINX Plus),首先需要创建一个配置文件,其中包含连接 NGINX 和 S3 API 上游的设置。相关配置文件示例请参见我们的 GitHub 仓库。我们来看看一些面向不同的 S3 API 后端的配置示例。

Amazon S3

以下是使用 Amazon S3 作为后端时的配置。由于 AWS 正逐渐弃用 AWS 签名版本 2,故在此我们使用的是版本 4。

S3_BUCKET_NAME=my-bucket-name
S3_ACCESS_KEY_ID=PUBLICACCESSKEY4TEXT
S3_SECRET_KEY=ProtectThisPrivateKeyBecauseItIsASecret!
S3_SERVER=s3-us-west-2.amazonaws.com 
S3_SERVER_PORT=443 
S3_SERVER_PROTO=https 
S3_REGION=us-west-2
AWS_SIGS_VERSION=4
ALLOW_DIRECTORY_LIST=true

Wasabi

以下是将 Wasabi 作为与 S3 兼容的后端的配置。此处我们使用的是 AWS 签名版本 2,因为 Wasabi 一直支持该身份验证方法,并且性能通常更好。

S3_BUCKET_NAME=my-bucket-name
S3_ACCESS_KEY_ID=PUBLICACCESSKEY4TEXT
S3_SECRET_KEY=ProtectThisPrivateKeyBecauseItIsASecret!
S3_SERVER=s3.us-west-1.wasabisys.com
S3_SERVER_PORT=443
S3_SERVER_PROTO=https
S3_REGION=us-west-1
AWS_SIGS_VERSION=2
ALLOW_DIRECTORY_LIST=true

启动网关

将配置保存到文件(此处为当前目录下的 s3-settings.env)后,就可以使用 Docker 启动网关了。

  • 如需在前台启动 NGINX 开源版网关,请运行:
docker run -it --env-file ./s3-settings.env -p8080:80 nginxinc/nginx-s3-gateway
  • 如需在前台启动 NGINX Plus 网关,请运行:
docker run -it --env-file ./s3-settings.env -p8080:80 nginx-plus-s3-gateway

在确认镜像运行正常后,您可以把它推送到企业的私有 Docker 仓库,以供更大规模地使用。但是:

切勿将 NGINX Plus 镜像上传到像是 Docker Hub 这样的公共仓库,否则就违反了许可协议要求。

NGINX 启动后,您可以通过 http://localhost:8080 访问网关。

自定义网关

在熟悉了以默认配置运行 NGINX S3 网关的方法后,您可以尝试根据自己的特定需求扩展其配置。基础 NGINX Docker 镜像被配置为自动加载在 /etc/nginx/conf.d 目录中发现的任何 *.conf 文件,这让用户能够相对轻松地添加其他功能的配置。

例如,您可以将 Gzip 压缩 模块的配置存储在本地目录的 etc/nginx/conf.d/gzip_compression.conf。在我们的 GitHub 仓库中有一个运行良好的例子,展示了如何自定义 NGINX S3 网关从而搭配使用 Gzip 压缩模块。

如需添加其他功能的配置,请执行以下操作:

  1. 为您想支持的功能创建一个配置文件,例如在本地目录 etc/nginx/conf.d/ 中创建 gzip_compression.conf 文件。
  2. 将以下几行代码添加到 Dockerfile 中,以便自动从本地目录 etc/nginx/conf.d 中加载扩展名为 .conf 的任何文件。
FROM nginxinc/nginx-s3-gateway
COPY etc/nginx/conf.d /etc/nginx/conf.d


结语

本文介绍了如何将 NGINX 作为缓存网关,置于 Amazon S3 私有存储桶或其他与之兼容的对象存储之前。这不仅可以减少对象存储的流量,而且还在对象存储与公共互联网之间添加了一层保护,能够防止内容意外暴露到公网。

如欲使用 NGINX 开源版,请从 Docker Hub 下载 NGINX 官方镜像,并从 GitHub 上获取我们提供的 Dockerfile




更多资源

想要更及时全面地获取NGINX相关的技术干货、互动问答、系列课程、活动资源?

请前往NGINX开源社区:


已修改于2023-03-06 23:55
本作品系原创
创作不易,留下一份鼓励
NGINX官方账号

暂无个人介绍

关注



写下您的评论
发表评论
全部评论(0)

按点赞数排序

按时间排序

关于作者
NGINX官方账号
这家伙很懒还未留下介绍~
232
文章
21
问答
198
粉丝
相关文章
Nginx是企业内网的对外入口,它常常同时对接许多应用,因此,Nginx上会同时监听多个端口、为多个域名提供服务。然而,匹配多级域名并不简单,Nginx为此准备了字符串精确匹配、前缀通配符、后缀通配符、正则表达式,当它们同时出现时,弄清楚HTTP请求会被哪个server{}下的指令处理,就成了一件困难的事。这是因为基于域名规范,请求匹配server{}配置块时,并不会按照它们在nginx.conf文件中的出现顺序作为选择依据。而且对于不支持Host头部、没有域名的HTTP/1.0请求和无法匹配到合适server{}的异常请求,我们都要区别对待。另外,为了加快匹配速度,Nginx将字符串域名、前缀通配符、后缀通配符都放在了哈希表中,该设计充分使用了CPU的批量载入主存功能。如果不了解这些流程,既有可能导致请求没有被正确的server{}块处理,也有可能降低了原本非常高效地哈希表查询性能。本文将沿着Nginx处理HTTP请求的流程,介绍一个请求是如何根据listen、server_name等配置关联到server{}块的。我们将从TCP连接的建立、Nginx从哪些字段取出域名、域
点赞 14
浏览 4.1k
一、创建日志切分脚本文件vi/data/aikube/scripts/cut_nginx_log.sh内容为:        #/bin/bash        # 取前一天:要求计划任务应该在0点之后执行        yesterday=`date-d'-1day'+%Y-%m-%d`        # 分割后的日志保存路径(结尾不加斜杠)        log_bak_path='/data/aikube/nginx-logs'        #nginx日志文件路径(结尾不加斜杠)        ng_log_path='/usr/local/openresty/nginx/logs'        # 判断分割日志保存目录是否存在不存在则创建        if[!-d${log_bak_path}]        then          mkdir-p${log_bak_path}        fi        # 将日志移动到备份路径        mv${ng_log_path}/access.log  ${log_bak_path}
点赞 4
浏览 1.7k
当上游出错时,作为负载均衡的Nginx可以实时更换Server,在客户端无感知的情况下重新转发HTTP请求。这一功能在Nginx指令中称为nextupstream,本文将详细介绍其用法及实现原理。在OSI网络模型中,传输层的TCP协议通过内核提供的系统调用向Nginx反馈错误,表示层的TLS/SSL协议通过openssl库向Nginx返回错误,而应用层的HTTP协议(或者uwsgi、gRPC、CGI、memcached等协议)通过Response的Decode解码流程返回错误。当Nginx能够通过重试解决这些错误时,我们可以使用nextupstream机制对客户端隐藏个别上游Server由于宕机、网络异常产生的错误,这可以极大的提升整个分布式系统的可用性。如果我们不清楚它处理协议错误及重试转发的原理,就很容易在实际场景中发现next upstream没有发挥作用,比如:l
点赞 2
浏览 2.3k