Cloudreve 是一款使用 Golang 实现的开源网盘系统,支持多样化的外部存储、跨平台访问和 WebDAV 协议。

Cloudreve 官网截图

前言

大家好,因为我要存储一些重要文件和照片,要求安全、高速读取且隐私保护,所以我希望在家能够有一个自己的网盘,并且能自由读取和开发。

由于 NAS 太贵且过于封闭,没钱的我决定自己搭建,毕竟自建的才是最便宜的,而且还能利用开源特性自由开发。

最便宜的 NAS 都仿佛 GTA 抢钱

经过一段时间的实践,这是我利用目前云原生技术搭建起来的网盘系统架构设计。

架构图

有的大佬应该能看出来这仿佛杀鸡用牛刀,请允许我狡辩一下。

这是目前上机的效果,大文件上行有 40Mb/s+,下行能达到 60Mb/s+,小文件基本秒传。

上传下文件

下载大文件

至于在线浏览和看剧?那简直是太小儿科了,随便拖动都不带加载的。

看视频洒洒水啦

机器配置

机器选用的是一台淘汰下来的 i7-8700 主机,由于原本内存只有 16G,个人感觉还是不太够的,所以我花重金购置了两根 32G 的内存,一共 64G 内存(主板限制 64G 内存)。

尽管 CPU 是 i7-8700,实际上比一般的 E5 服务器 CPU 强太多了,实测下来装完这么多东西,CPU 占用日常都不到 20%,核心再多就就是溢出了。

值得注意的是,划分虚拟机时,CPU 可以随便超,但内存需要精细化划分,因为内存不能超,超了就 OOM 了。

物理机系统安装的是 PVE,即 Proxmox Virtual Environment,开源的虚拟服务器系统,再通过 PVE 划分出多台 Centos 虚拟机,这样能够损失最少的资源来换取资源的高利用率。

PVE 控制台

由于需要存储重要文件,所以机器上安装了 2 个固态硬盘 1.2TB 提供高速存储,2 个机械硬盘作冗余备份和提供 3T 的大容量存储。

PVE 硬盘可视化操作

平台架构 - Kubernetes

由于我需要部署容器,所以我直接划分出 3 个虚拟机作为 Kubernetes 节点,它们挂载的磁盘各不相同,每个节点都挂载了 SSD + 机械。

我对 Kubernetes 的调优不感兴趣,所以搭建 Kubernetes 使用的是能够一条命令安装的 K3s,它虽然精简了 Kubernetes,但足以满足我的需求。

K3s 官方图

安装完 Kubernetes 之后就拥有了调度容器的能力,这时候就能开始实现业务需求了。

平台架构 - Istio

因为我的配置足以支持更厉害的网关,所以安装 K3s 时我特别排除了 Traefik 网关,选用了 Istio 作为网关。

利用 Istio 可以实现自动的负载均衡,同时相比 Traefik 使用注释的方式新增路由,Istio 配置 CRD 会比较方便。

平台架构 - Longhorn 块存储

Longhorn 是 K3s 推荐的一种云原生开源分布式块存储系统。

它提供了高可用、快照、备份和 ReadWriteMany 访问模式的能力,其中 ReadWriteMany(RWM)访问能力非常重要。

Longhorn 官方图

在 Kubernetes 上安装 Longhorn 的过程大致分为三步。

  1. 部署 DaemonSets 给每个节点安装 NFS 和 iscsi。其中 NFS 用于提供 RWM 能力,iscsi 用于给 Longhorn 提供文件系统访问接口。
  2. 通过 Helm 将 Longhorn 安装。
  3. 配置 Node 磁盘,打标签并新增 StorageClass。

需要注意的是配置 Node 节点磁盘,默认情况下 Longhorn 会使用系统盘,但我们额外挂载了机械硬盘到节点上,所以需要配置一下(用 Disk Tag 标签标记挂载的路径是 SSD 还是机械)。

这部分操作可以通过 Longhorn 提供的可视化界面实现,所以操作起来非常简单。

Longhorn 控制台新增硬盘

等待 Longhorn 完成初始化之后就能新增对应的 StorageClass 给 Workload 挂载了。

查看 Storageclass

平台架构 - 服务监控 + 日志采集

  • Prometheus 提供指标采集和集群可观测能力。
  • Loki 提供日志聚合查询和持久化能力。
  • Grafana 提供可视化界面查询 Prometheus 采集的指标和 Loki 采集的 日志。

以上三个组件都是通过 Longhorn 实现数据持久化。

Grafana 查看集群节点信息

网盘服务 - Cloudreve

Cloudreve 是一款使用 Golang 实现的开源网盘系统,支持多样化的外部存储、跨平台访问和 WebDAV 协议。

Cloudreve 官网截图

我选用 Cloudreve 最大的理由就是它是 Golang 编写的,同时支持跨平台访问,界面 UI 甩同类产品几条街。

搭建 Cloudreve 需要依赖 MySQL 和 Redis。其中 MySQL 用于存储用户和文件数据,Redis 用于共享 Session 会话,不然无法实现分布式。

存储架构 - TiDB

TiDB 是一款兼容 MySQL 5.7 协议的开源分布式关系型数据库。

选用 TiDB 的原因是工作项目使用的就是 TiDB,所以在自建服务中选用 TiDB 能更好锻炼自己分析和解决问题的能力。

TiDB 官方架构图

TiDB 的架构简单描述有三个部分。

  1. TiDB Server:SQL 层,对外暴露 MySQL 协议的连接 endpoint,负责接受客户端的连接,执行 SQL 解析和优化,最终生成分布式执行计划。
  2. PD (Placement Driver) Server:整个 TiDB 集群的元信息管理模块,负责存储每个 TiKV 节点实时的数据分布情况和集群的整体拓扑结构,提供 TiDB Dashboard 管控界面,并为分布式事务分配事务 ID。
  3. TiKV Server:负责存储数据,从外部看 TiKV 是一个分布式的提供事务的 Key-Value 存储引擎。

安装 TiDB 只需要通过 PVE 划分出 4 台 Centos 虚拟机实现最小拓扑。

  1. TiDB 和 PD 共用 - 4C8G + 200G 机械硬盘用于存储日志和监控指标。
  2. 3 台 TiKV - 2C4G + 100G SSD 数据持久化。

接下来是配置环境,按照官方文档使用 TiUP 工具安装即可。

TiUP 查看状态

最后在集群新增一个 ServiceEntry 将 TiDB 纳入服务网格,这样就能看到 Istio 上报的指标。

Grafana 查看 TiDB 指标数据

存储架构 - Redis

Redis 是比较常用的 KV 数据库了,搭建它只需要 Helm 安装一下就能快速获取一个主从模式的 Redis 服务。

在集群内部通过 Service 就能直接访问,无需额外的配置。

Redis 服务

值得注意的是,Redis 的数据持久化同样使用的是 Longhorn 存储,所以需要先安装 Longhorn。

Cloudreve 缺点与解决方案

Cloudreve 原本设计为 Docker 部署的有状态单体应用,读写文件会首先从本机文件系统读取,加载到内存再通过接口传输数据。

对应 Kubernetes 集群部署,Cloudreve 存储是挂载单节点本地磁盘,那么存储瓶颈会出现在节点磁盘读写和网络传输上,实测下来单实例大文件读写大概在 10-15 Mb/s,而大量小文件读写速度更慢。

这种读写速度是无法满足我的需求,毕竟某度网盘开会员之后下载多个文件的基本在 35Mb/s 左右(上传只有可怜的 5Mb/s)。

Cloudreve 提出的是加入从节点来实现分布式,这样确实能在一定程度缓解读取问题,不过这是部署在 Docker 的解决方案。

对此,我采用更加奢侈的方案,直接将存储数据同步到三个节点上,启用 Longhorn 提供的 Data Locality 数据本地化特性 best-effort。

既然单机不行, 那就上集群

通过这种方式可以让 Pod 优先读取到所在 Node 的副本数据,同时能将数据冗余到其他节点上,避免单节点故障的问题。

只是这种方式缺点是写入速度会有明显的损耗,因为要进行三个副本的同步。

接着就是在创建 PVC 时将 AccessModes 设置为 RWM,即 Volume 可以被多个节点以读写方式挂载。

PVC 需要设置为 RWM 访问模式

这样多个 Cloudreve 实例就能挂载同一个 Volume,每个实例读写的内容是一样的。

接下来将 Cloudreve 的 Session 存储方式从本地改为 Redis 共享,这样我们访问过程中就不会因为流量平衡到多个 Pod 导致登录状态消失。

Cloudreve 文档 - Redis 用途

最后我们只需要增加实例的数量就能大幅度提升存储读写速度,直至触碰到现有方案的读写瓶颈。

单机不行就集群


网上相关的资料还是挺少的,写出来分享一方面是帮助自己整理知识,另一方面是希望能有大佬提出更牛逼的方案。

最后感兴趣的朋友可以关注一下这个号,之后会不定期分享一些有趣的内容。