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

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

当您设置任何基础设施时,您都希望以可扩展且安全的方式进行。您的 MinIO 数据基础设施也是如此。您要确保:

  • 到 MinIO 集群的流量均匀分布

  • MinIO集群没有单点故障

  • 与 MinIO 集群的通信是安全的

  • 使 MinIO 节点脱机时易于维护

我们将讨论如何使用 Nginx 和 LetsEncrypt/Certbot 通过 MinIO 设置负载平衡和 TLS。我们将使用容器,但它不会完全自动化,例如 Kubernetes 中的 cert-manager,以便我们了解各种组件如何工作和集成在一起的内部结构。如果以后你更喜欢自动化,我实际上推荐它,因为当你扩展应用程序的数量时,从负载平衡器手动添加/删除 MinIO 节点或每 3 个月更新一次证书会变得很麻烦。

让我们看一下我们将要设置的图表:


MinIO + Nginx + LetsEncrypt.jpeg


最小IO

我们将启动 3 个相同的 MinIO 节点,每个节点有 4 个磁盘。MinIO 可以在任何地方运行——物理、虚拟或容器——在本概述中,我们将使用使用 Docker 创建的容器。

节点设置

让我们命名这 3 个节点:

  • minio1

  • minio2

  • minio3

我们将逐步完成部署minio1,然后您可以对minio2和使用相同的过程minio3

对于 4 个磁盘,在主机上创建目录minio1

mkdir -p /home/aj/minio-<id>/disk-1 \
mkdir -p /home/aj/minio-<id>/disk-2 \
mkdir -p /home/aj/minio-<id>/disk-3 \
mkdir -p /home/aj/minio-<id>/disk-4

替换1minio2对和minio3重复上述操作。

启动节点

启动 3 个具有以下规格的 Docker 容器,同样用 1、2 和 3 替换 MinIO 节点:

docker run -d \
  -p 2009<id>:9001 \
  -v /home/aj/minio-<id>/disk-1:/mnt/disk1 \
  -v /home/aj/minio-<id>/disk-2:/mnt/disk2 \
  -v /home/aj/minio-<id>/disk-3:/mnt/disk3 \
  -v /home/aj/minio-<id>/disk-4:/mnt/disk4 \
  --name minio<id> \
  --hostname minio<id> \
  quay.io/minio/minio server http://minio{1...3}/mnt/disk{1...4}/minio --console-address ":9001"

-p::这是在主机上公开的控制台 UI 端口,我们可以使用它来查看存储桶和对象以及管理 MinIO。

-v::这是为了将您之前创建的本地目录挂载为容器上的磁盘。

--nameand --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

Status:         12 Online, 0 Offline.
API: http://172.20.0.2:9000  http://127.0.0.1:9000

Console: http://172.20.0.2:9001 http://127.0.0.1:9001

Documentation: https://docs.min.io


如果你看到12 Online这意味着你已经成功地设置了 3 个 MinIO 节点的集群,每个节点有 4 个驱动器,总共有 12 个驱动器在线。

测试你的新 MinIO 集群

转到浏览器,为 3 个容器中的 1 个在各自的端口上加载 MinIO 控制台http://localhost:2009,替换为 1、2 或 3 用于 MinIO 节点。单击按钮Create Bucket并创建testbucket123.


pasted image 0 (58).png


如果我们访问另一个 MinIO 容器上的控制台,我们将看到相同的桶。


pasted image 0 (59).png


Nginx

负载均衡

Nginx 最初是一个 Web 服务器,后来发展到今天它被用作 Kubernetes 中的入口控制器。它在各个方面都得到了发展,但可以说它做得很好的一件事是将请求分发到一组后端节点,这个过程称为反向代理。

TLS 终止

使用反向代理时,我们应该在代理层终止 TLS 连接。这样您就不必担心在每个单独的节点上更新过期的证书。如果您有适当的配置管理流程,那么这可以简化和自动化。

配置

我们的 MinIO 集群中有 2 个端口,服务器运行在端口 9000 上,控制台运行在端口 9001 上,我们需要通过 Nginx 代理这两个端口。

为 2 个端口(9000 和 9001)中的每一个创建 2 个上游并列出我们的后端 MinIO 服务器:

upstream minio_server {
   server minio1:9000;
   server minio2:9000;
   server minio3:9000;
}

upstream minio_console {
    ip_hash;
   server minio1:9001;
   server minio2:9001;
   server minio3:9001;
}


用于minio_server端口9000minio_console用于9001.

为每个上游创建 2 个 Nginx 服务器指令以配合它:

server {
    listen       9000;
    listen  [::]:9000;
    server_name  localhost;

    ignore_invalid_headers off;
    client_max_body_size 0;
    proxy_buffering off;
    proxy_request_buffering off;

    location / {
        proxy_set_header Host $http_host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;

        proxy_connect_timeout 300;
        proxy_http_version 1.1;
        proxy_set_header Connection "";
        chunked_transfer_encoding off;

        proxy_pass http://minio_server;
    }
}

server {
    listen       9001;
    listen  [::]:9001;
    server_name  localhost;

    ignore_invalid_headers off;
    client_max_body_size 0;
    proxy_buffering off;
    proxy_request_buffering off;

    location / {
        proxy_set_header Host $http_host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header X-NginX-Proxy true;

        real_ip_header X-Real-IP;

        proxy_connect_timeout 300;
       
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
       
        chunked_transfer_encoding off;

        proxy_pass http://minio_console;
    }
}


编写配置后,将其保存default.conf在稍后可以挂载到 Nginx 容器中的位置,在本例中我使用了该/home/aj/nginx/conf.d目录。

使用自定义配置,启动带有端口映射的 Nginx 映像。在此示例中,我们分别将主机端口39000和映射39001nginx容器端口 9000 和 9001。

docker run -d \
  -p 39000:9000 \
  -p 39001:9001 \
  -v /home/aj/nginx/conf.d:/etc/nginx/conf.d \
  --name nginx \
  --hostname nginx \
  nginx:latest

测试反向代理

3 个 MinIO 容器现在由 Nginx 反向代理提供服务。我们可以通过去确认这一点http://localhost:39001,我们应该看到相同的testbucket123


pasted image 0 (60).png



Nginx 将确保请求得到均匀分布,因此我们无需转到各个容器来访问控制台。服务器也一样,你可以访问它localhost:39000,Nginx 会负责负载均衡。

让加密

如今,使用LetsEncrypt证书创建和管理 TLS 证书的实际方法是通过Certbot我们将使用 Certbot 以自动化方式帮助管理证书的生命周期。它可以帮助您的一些事情是:

  • 创建证书

  • 更新证书

  • 吊销证书

在我们的例子中,我们将使用 Certbot 创建一个证书,我们将在上一步中将其与 Nginx 一起使用。

创建证书

虽然我们不会在本教程中使用像 cert-manager 和 Kubernetes 这样的完全自动化,但我们将使用 Certbot 来使我们的证书的生成和更新更容易一些——我们也不要让它变得那么困难:)

有多种方法可以在各种平台上安装 Certbot,这里是说明一旦你为你的特定平台安装了 Certbot,有两种方法可以通过 LetsEncrypt API 使用他们所谓的“挑战”来验证你的证书。

挑战

例如,假设您尝试为其创建证书的域是minio.example.com

HTTP

  • HTTP 质询查找 URL 路径/.well-known/acme-challenge/:id,在本例中http://minio.example.com/.well-known/acme-challenge/:id可在端口 80 上访问。

然后 Certbot 将在证书生成过程中将文件写入目录root/.well-known/acme-challenge/:id进行验证。例如,挑战的 Nginx 配置如下所示:

location /.well-known/acme-challenge/ {
    root /var/html/certbot;
}


然后certbot --webroot-path将是/var/html/certbot

与其手动设置以上内容,最简单的方法是:

  • 使用公共 IP 启动 VM,您需要打开端口 80。

  • 将您的 DNS A 记录更新为minio.example.comVM 的公共 IP。

  • 运行以下命令将启动一个临时服务器,设置挑战并生成证书

  • sudo certbot certonly --standalone

域名系统

  • 在我看来,DNS 挑战稍微简单一些,因为您所要做的就是在 minio.example.com 的 DNS 区域中设置一个记录。没有创建额外基础设施或服务器的开销。

  • 运行以下命令开始设置基于 DNS 的挑战的过程

  • certbot -d minio.example.com --manual --preferred-challenges dns certonly

  • TXT上述命令将在要求您将记录设置_acme-challenge.minio.example.com为特定值的提示处停止。一旦能够成功解决,挑战就会通过,您将获得 minio.example.com 的新证书。

DNS 质询方法的缺点之一是 DNS 传播不是瞬时的。即使您可以在笔记本电脑上本地解析它,LetsEncrypt DNS 服务器也可能无法解析,因此您必须等待。通常这很快,但不能保证。  

配置 Nginx

无论您使用哪种方法,一旦生成证书,都应该有两个文件fullchain.pemprivkey.pem将它们保存在一个目录中,以便稍后装入 Nginx 容器中/etc/nginx/certs在这种情况下,让我们将它们放在/home/aj/nginx/certs目录中。

server { … }修改Nginx文件中的2块default.conf如下:

  • 改为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 { … }块应该是这个样子:

server {
    ..
    server_name  minio.example.com;
    ssl_certificate /etc/nginx/certs/fullchain.pem;
    ssl_certificate_key /etc/nginx/certs/privkey.pem;
    ..
}

不要忘记使用docker run附加更新 Nginx 命令-v,以便证书在下一步中可用于 Nginx:

docker run -d \
  -p 39000:9000 \
  -p 39001:9001 \
  -v /home/aj/nginx/conf.d:/etc/nginx/conf.d \
  -v /home/aj/nginx/certs:/etc/nginx/certs \
  --name nginx \
  --hostname nginx \
  nginx:latest

执行上面的命令启动 Nginx 容器。

测试 TLS

好了,我们都配置好了,但是我们在Nginx docker容器上没有公网IP可以设置给minio.example.com A记录使用,那我们怎么测试TLS呢?

一种测试方法是:

  • /etc/hosts在本地笔记本电脑的文件中添加新行

  • 如果 docker 主机与本地笔记本电脑相同,则可以添加行127.0.0.1 minio.example.com

  • 如果 docker 主机在另一个具有私有 IP 的 VM 上运行,您可以添加行minio.example.com

  • 在浏览器中转到https://minio.example.com:39001,您应该能够看到安全连接。

进一步改进

  • 也许 Nginx 可以在单个端口上运行,而不是在同一个端口上使用 2指令location /…/server/console

  • 正如我们配置的那样,Nginx 是单点故障。一种可能的选择是让多个 Nginx 节点具有类似 DNS 循环的东西来分配流量,以防其中一个 Nginx 实例需要脱机进行维护等。

最后的想法

LetsEncrypt/Certbot 是每个人在谈论 TLS 证书时想到的,Nginx 是 Reverse Proxy 和 Kubernetes Ingress 想到的。同样,大家都知道 MinIO 是目前最好的对象存储。这些的共同点是什么?它们共享编写良好的云原生软件的直接简单性,每个软件都提供核心基础设施服务。

我们不可能用另一个对象存储来编写这个简短的教程。其他类似的对象存储的设置非常复杂且耗时,但我们仅使用几个容器设置了一个负载平衡和 TLS 保护的多节点 MinIO 集群。

不要相信我们的话——自己动手吧。你可以在这里下载 MinIO ,你可以在这里加入我们的 Slack 频道


上一篇 下一篇