如何使用 Nginx、LetsEncrypt 和 Certbot 安全访问 MinIO

在设置任何基础设施时,您都希望以可扩展且安全的方式进行。您的 MinIO 数据基础设施也是如此。您需要确保
- MinIO 集群的流量得到均匀分配
- MinIO 集群中没有单点故障
- 与 MinIO 集群的通信是安全的
- 在将 MinIO 节点离线时易于维护
我们将介绍如何使用 Nginx 和 LetsEncrypt/Certbot 为 MinIO 设置负载均衡和 TLS。我们将使用容器,但它不会完全自动化,例如 Kubernetes 中的 cert-manager,这样我们就可以了解各个组件如何工作以及如何集成在一起。如果您稍后希望自动化它,我实际上建议这样做,因为随着应用程序数量的增加,手动从负载均衡器中添加/删除 MinIO 节点或每 3 个月更新一次证书可能会变得很麻烦。
让我们看一下即将设置的架构图
MinIO
我们将启动 3 个相同的 MinIO 节点,每个节点有 4 个磁盘。MinIO 可以在任何地方运行 - 物理机、虚拟机或容器 - 并且在本概述中,我们将使用 Docker 创建的容器。
节点设置
让我们将这 3 个节点命名为
minio1
minio2
minio3
我们将逐步介绍 minio1
的部署,然后您可以对 minio2
和 minio3
使用相同的流程
对于这 4 个磁盘,在 minio1
的主机上创建目录
将 <id>
替换为 1
。对 minio2
和 minio3
也重复上述操作。
启动节点
使用以下规范启动 3 个 Docker 容器,类似地将 <id>
替换为 MinIO 节点的 1、2 和 3
-p <主机>:<容器>
: 用于将 MinIO 控制台 UI 端口暴露到主机上,方便我们查看存储桶、对象和管理 MinIO。
-v <主机>:<容器>
: 用于将之前创建的本地目录作为磁盘挂载到容器中。
--name
和 --hostname
: 将这两个参数设置为相同的值,以便在配置容器时保持一致性。
quay.io/minio/minio server http://minio{1...3}/mnt/disk{1...4}/minio --console-address ":9001"
: minio{1...3}
和 disk{1...4}
在应用于服务器配置之前会被扩展。
当所有 3 个节点都成功启动并相互通信后,运行 docker logs minio1
如果看到 12 在线
,则表示您已成功设置了包含 3 个 MinIO 节点(每个节点 4 个磁盘)的集群,总共有 12 个磁盘在线。
测试新的 MinIO 集群
在浏览器中访问 3 个容器中的一个的 MinIO 控制台,其端口为 http://localhost:2009<id>
,将 <id>
替换为 1、2 或 3 以访问相应的 MinIO 节点。点击 创建存储桶
按钮并创建 testbucket123
。
如果我们访问另一个 MinIO 容器的控制台,我们将看到相同的存储桶。
Nginx
负载均衡
Nginx 最初是一个 Web 服务器,后来发展成为 Kubernetes 中的入口控制器。它在各个方面都有发展,但它 arguably 做得很好的一件事是将请求分发到一组后端节点,这个过程被称为反向代理。
TLS 终止
使用反向代理时,我们应该在代理层终止 TLS 连接。这样,当证书过期时,您就不必担心在每个节点上更新证书。如果您已实施配置管理流程,则可以简化和自动化此过程。
配置
我们的 MinIO 集群中有两个端口,服务器运行在端口 9000 上,控制台运行在端口 9001 上,我们需要通过 Nginx 代理这两个端口。
为这两个端口(9000 和 9001)分别创建两个上游服务器,并列出我们的后端 MinIO 服务器。
minio_server
用于端口 9000
,minio_console
用于 9001
。
为每个上游服务器创建两个 Nginx 服务器指令。
编写完配置后,将其保存为 default.conf
,并将其保存到稍后可以挂载到 Nginx 容器中的位置,在本例中,我使用了 /home/aj/nginx/conf.d
目录。
使用自定义配置,启动一个 Nginx 镜像并进行端口映射。在本例中,我们将主机端口 39000
和 39001
分别映射到 nginx
容器端口 9000 和 9001。
测试反向代理
3 个 MinIO 容器现在由 Nginx 反向代理提供服务。我们可以通过访问 http://localhost:39001
来确认这一点,我们应该看到相同的 testbucket123
。
Nginx 将确保请求得到均匀分配,因此我们无需访问各个容器即可访问控制台。服务器也是如此,您可以在 localhost:39000
上访问它,Nginx 将负责负载均衡。
Let's Encrypt
如今,使用 Let's Encrypt 证书创建和管理 TLS 证书的事实标准方法是通过 Certbot。我们将使用 Certbot 以自动化方式帮助管理证书的生命周期。它将帮助您完成以下一些操作:
- 创建证书
- 续订证书
- 吊销证书
在本例中,我们将使用 Certbot 创建一个证书,并在上一步的 Nginx 中使用它。
创建证书
在本教程中,我们不会像在 Kubernetes 中使用 cert-manager 一样使用完全自动化,但我们将使用 Certbot 使证书的生成和续订更容易一些——让我们不要使其过于复杂 :)
在各种平台上安装 Certbot 的方法有很多,这里提供了 说明。在为您的特定平台安装 Certbot 后,可以使用他们所谓的“挑战”通过两种方式来验证您与 Let's Encrypt API 的证书。
挑战
例如,假设您尝试为其创建证书的域名是 minio.example.com
HTTP
- HTTP 挑战会在端口 80 上查找 URL 路径
/.well-known/acme-challenge/:id
,在本例中为http://minio.example.com/.well-known/acme-challenge/:id
是否可访问。
然后,Certbot 将在证书生成过程中将文件写入 /.well-known/acme-challenge/:id
的 root
目录,并进行验证。例如,以下是挑战的 Nginx 配置示例:
然后,certbot --webroot-path
的值为 /var/html/certbot
。
与其手动设置以上内容,最简单的方法是
- 启动一台具有公网 IP 的虚拟机,并确保端口 80 开放。
- 将
minio.example.com
的 DNS A 记录更新为虚拟机的公网 IP。 - 运行以下命令,该命令将启动一个临时服务器,设置验证并生成证书
sudo certbot certonly --standalone
DNS 验证
- 在我看来,DNS 验证稍微简单一些,因为您只需在 minio.example.com 的 DNS 区域设置一条记录即可。无需创建额外的基础设施或服务器。
- 运行以下命令开始设置基于 DNS 的验证过程
certbot -d minio.example.com --manual --preferred-challenges dns certonly
- 以上命令将在提示符处停止,提示您将
_acme-challenge.minio.example.com
的TXT
记录设置为特定值。一旦该记录能够成功解析,验证将通过,您将获得 minio.example.com 的新证书。
DNS 验证方法的缺点之一是 DNS 传播不是即时的。即使您可以在本地笔记本电脑上解析它,Let's Encrypt 的 DNS 服务器可能无法解析,因此您需要等待。通常这很快,但不能保证。
配置 Nginx
无论您使用哪种方法,一旦证书生成,应该会有两个文件 fullchain.pem
和 privkey.pem
。将这些文件保存到一个目录中,以便稍后挂载到 Nginx 容器的 /etc/nginx/certs
目录中。在本例中,我们将它们放在 /home/aj/nginx/certs
目录中。
修改 Nginx default.conf
文件中的 2 个 server { … }
块,如下所示
- 将
server_name localhost
更改为server_name minio.example.com
。
创建以下 2 个指令
ssl_certificate /etc/nginx/certs/fullchain.pem
ssl_certificate_key /etc/nginx/certs/privkey.pem
两个 server { … }
块应该看起来像这样
不要忘记在 Nginx 的 docker run
命令中添加一个额外的 -v
参数,以便在下一步中 Nginx 可以访问证书。
执行以上命令以启动 Nginx 容器。
测试 TLS
好的,我们已经配置了所有内容,但我们没有可以为 minio.example.com 的 A 记录设置的 Nginx Docker 容器的公网 IP,那么我们如何测试 TLS 呢?
一种测试方法是
- 在本地笔记本电脑的
/etc/hosts
文件中添加新行 - 如果 Docker 主机与您的本地笔记本电脑相同,您可以添加行
127.0.0.1 minio.example.com
。 - 如果 Docker 主机在另一台具有私网 IP 的虚拟机上运行,您可以添加行
<vm_private_ip> minio.example.com
。 - 在浏览器中访问
https://minio.example.com:39001
,您应该能够看到安全连接。
进一步改进
- 也许 Nginx 可以运行在一个端口上,并在同一端口上使用 2 个
location /…
指令分别用于/server
和/console
。 - 按照我们的配置,Nginx 是单点故障。一个可能的选项是使用多个 Nginx 节点,并结合 DNS 轮询来分发流量,以防其中一个 Nginx 实例需要离线维护等。
最终想法
当人们谈论 TLS 证书时,Let's Encrypt/Certbot 是首先想到的;当谈论反向代理和 Kubernetes Ingress 时,Nginx 是首先想到的。同样,每个人都知道 MinIO 是最好的对象存储。这些的共同点是什么?它们共享了编写良好的云原生软件的简单性,每个软件都提供核心基础设施服务。
我们不可能使用其他对象存储来编写这个简短的教程。其他类似的对象存储极其复杂,设置起来非常耗时,但我们只需使用几个容器就设置了一个负载均衡且 TLS 安全的多节点 MinIO 集群。