自建MinIo代替腾讯云COS

随着国内云计算厂商的政策缩紧,国内云计算厂商之前各种小羊毛慢慢都在“温暖升级”,比如腾讯云的COS就从一开始的新老用户免费50G到后面的新用户50G免费6个月,免费期过后2022年9月1日起老用户“对象存储服务 COS 存储容量、请求及数据取回计费项将由按月结算升级为按日结算”,官方的功能升级目的为“便于您通过日结账单做更精细的费用管理”,我放在腾讯云COS的文件不多,就是网站的图片文件,也就200MB不到,如果是之前的按月结算,可能一个月也就不到1分钱,但是新政策之后,腾讯云每天至少从我账户扣除1分钱,钱虽然不多,但是这一天天的每天都在扣费有点肉疼,薅了这么久腾讯云的羊毛,也不能说人家不好,正好最近接触到了MinIO这个替代品,服务器资源也足够,干脆将这部分功能自建好了,于是有了这篇折腾记录。

为什么需要MinIO

包括我手上的几个网站,以及偶尔写文档时,需要有个地方用来保存图片及文件。之前本站的网站图片我都是使用uPic传到腾讯云COS,配合腾讯云每个月的10G免费CDN流量,再通过CDN加速COS分发到浏览器,因为我本身放在COS的文件比较少,每个月COS即使没有购买套餐也花不了几个钱,但是现在腾讯云COS政策更改,出于长远考虑,我还是选择将这部分功能自建好了,恰好MinIO就是我了解之后觉得各方面都比较符合我这个需求的软件之一。

MinIO简介

MinIO官网:https://minio.io/

根据MinIO官网的介绍,MinIO是一个使用Go语言编写的提供高性能S3协议兼容的对象存储服务,免费且开源。

我选择MinIO也是看中这几点,第一,S3协议兼容,可以利用现有众多的S3协议客户端;第二,对象存储,可以直接无缝从COS迁移;第三,免费开源,可以在现有服务器上部署,无需额外成本。

MinIO安装

MinIO支持众多平台,我现在网站服务器系统是Debian,选择AMD64系统类型的即可,下载:

wget https://dl.min.io/server/minio/release/linux-amd64/minio

赋予可执行权限及移动到bin目录:

chmod +x minio
mv minio /usr/local/bin/

为MinIO单独创建一个不可登录的用于用来运行MinIO服务:

useradd -r minio -s /sbin/nologin

chown minio:minio /usr/local/bin/minio

如果上述过程无意外,执行如下命令即可查看MinIO的版本信息:

minio --version

为MinIO创建文件保存目录,我是选择保存在/data/minio,如果跟我不一样的话,下述配置文件记得一并更改:

mkdir /data/minio -p
chown minio:minio /data/minio

创建配置文件:

vim /etc/default/minio

MINIO_ACCESS_KEY="cloudbool_minio_access"
MINIO_SECRET_KEY="cloudbool_minio_secret"
MINIO_VOLUMES="/data/minio"
MINIO_OPTS="--address :9001 --console-address :9000"

这里说几点需要留意的。

MINIO_ACCESS_KEYMINIO_SECRET_KEY为后续登录控制面板及API的凭证,如果是放到公网的话,一定要注意设置复杂一点。

MINIO_VOLUMES为MinIO保存对象文件及基础文件的目录,我上面设置的是/data/minio,如果跟我不一样,需要注意MinIO运行的用户对这个目录具有写入权限。

MINIO_OPTS后面的两个参数信息分别是API的端口号及控制面板端口号,如果只需要其中之一,选择对应的一个也可以,留意设定的端口号没有被占用以及跟别的服务不冲突即可。

进程管理服务:

vim /etc/systemd/system/minio.service

[Unit]
Description=MinIO
Documentation=https://docs.min.io
Wants=network-online.target
After=network-online.target
AssertFileIsExecutable=/usr/local/bin/minio

[Service]
WorkingDirectory=/usr/local/

User=minio
Group=minio
ProtectProc=invisible

EnvironmentFile=/etc/default/minio
ExecStartPre=/bin/bash -c "if [ -z \"${MINIO_VOLUMES}\" ]; then echo \"Variable MINIO_VOLUMES not set in /etc/default/minio\"; exit 1; fi"
ExecStart=/usr/local/bin/minio server $MINIO_OPTS $MINIO_VOLUMES

# Let systemd restart this service always
Restart=always

# Specifies the maximum file descriptor number that can be opened by this process
LimitNOFILE=1048576

# Specifies the maximum number of threads this process can create
TasksMax=infinity

# Disable timeout logic and wait until process is stopped
TimeoutStopSec=infinity
SendSIGKILL=no

[Install]
WantedBy=multi-user.target

# Built for ${project.name}-${project.version} (${project.name})

注意上述指定的User及Group对应的用户名及分组名存在及有相应的权限。

进程控制:

systemctl daemon-reload
systemctl start minio
systemctl restart minio
systemctl status minio

到这一步如果没有错误已经可以访问MinIO了,访问服务器IP:console-address例如192.168.1.10:9000即可访问MinIO的控制面板并进行创建bucket、上传对象文件等操作了。

Nginx反代MinIO

就我实际使用情况来说,MinIO不会放在内网,肯定是在公网方便访问的,所以我选择使用Nginx来反代MinIO顺带加上HTTPS确保链路安全。

如果跟我上面配置一样,MinIO其实是提供两个入口的,分别是控制面板及API节课,经过我的实际测试,这两个入口没法放在同一个域名下面,所以我最终使用了两个域名来反代MinIO服务,分别是控制面板及API端口,两个域名的配置分别如下。

首先是MinIO控制面板,也就是9000端口:

# cat minio.conf 
server{
        listen 443 ssl http2;
        listen [::]:443 ssl http2;
        server_name  minio.cloudbool.com;
        ssl_certificate /ssl/cloudbool.crt;
        ssl_certificate_key /ssl/cloudbool.key;

        client_max_body_size 100M;

        location / {
                proxy_set_header Host $host;
                proxy_set_header X-Real-IP $remote_addr;
                proxy_set_header X-Forwarded-Proto $scheme;
                proxy_pass http://localhost:9000;
        }

        access_log /var/log/nginx/minio.log;
        error_log /var/log/nginx/minio-error.log;
}


server
{
        listen          80;
        server_name minio.cloudbool.com;
        location / {
                rewrite ^/(.*)$ https://minio.cloudbool.com/$1 permanent;
        }
}

然后是API及桶文件相关配置:

# cat minio-api.conf 
server{
        listen 443 ssl http2;
        listen [::]:443 ssl http2;
        server_name  minio-api.cloudbool.com;
        ssl_certificate /ssl/cloudbool.crt;
        ssl_certificate_key /ssl/cloudbool.key;

        client_max_body_size 100M;

        location / {
                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 Host $http_host;

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

                proxy_pass http://localhost:9001;
        }

        location /imgs/ {
                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 Host $http_host;

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

                proxy_pass http://localhost:9001;
        }

        access_log /var/log/nginx/minio-api.log;
        error_log /var/log/nginx/minio-api-error.log;
}


server
{
        listen          80;
        server_name minio-api.cloudbool.com;
        location / {
                rewrite ^/(.*)$ https://minio-api.cloudbool.com/$1 permanent;
        }
}

如果一切正常,可以访问两个域名登录控制面板及上传图片了,如图:

minio 控制面板

MinIO创建存储桶及权限设置

在上传文件之前,还需要创建存储桶,这点跟腾讯云COS逻辑是一样的。

打开MinIO的控制面板,例如我上面设置的minio.cloudbool.com,即可看到上面截图的样子,账号密码是之前在/etc/default/minio文件设置的。

登录之后,点击页面上的Create Bucket,如图:

minio create bucket

然后输入合适的名字作为存储桶名称,如图:

minio bucket name

如果需要公开访问,还需要将存储桶的Access Policy设置为Public,否则无法公开访问,可能需要带上相关签名信息才允许访问。

创建完成之后,回到存储桶列表,点击对应存储桶后面的Manage按钮,如图:

minio bucket manage
minio access policy
minio access policy public

如图,将Access Policy从下拉选项中设置成Public。

uPic上传文件到MinIO

因为我上面已经准备好了使用uPic上传文件到MinIO,所以我其实只需要登录一次MinIO的控制面板创建存储桶及设置存储桶的权限,后续就可以完全通过uPic上传文件及获取文件的URL,不需要每次都登录MinIO控制面板进行图片上传操作。

我的uPic设置如下:

minio upic setting

其中,uPic中的Access Key及Secret Key分别是/etc/default/minio中的MINIO_ACCESS_KEYMINIO_SECRET_KEY

如果一切正常,使用uPic上传图片之后应该能正确返回图片的URL,直接就能在浏览器访问:

minio upic image show

MinIO使用体验

总体来说,MinIO对我来说,完全可以代替之前的MinIO,免费且功能还能满足我的需要,最重要的是文件在自己手里可控。

我上面只是最基础的MinIO配置过程,MinIO配合Nginx还能做一些别的事情,例如使用CDN加速分发,还能利用Nginx的模块给图片打水印,或者利用第三方对图片进行压缩、裁切等操作。