Daoleno

利用 IPFS-Cluster 构建私有 IPFS 网络

April 1, 2020 • ☕️☕️☕️ 13 min read

原文:https://labs.eleks.com/2019/03/ipfs-network-data-replication.html

本文将展示如何构建私有 IPFS 网络,以安全的共享、复制和存储数据。

IFPS 网络有两种类型:公有和私有。公有 IPFS 网络上的所有文件对每个人来说都是可访问的。因为大多数商业应用,尤其是企业级的应用,需要对他们的数据拥有完全的控制权,网络可以被公众访问是不可接受的。IPFS 隐私功能可以帮助关闭对应特定实体的网络。

在这篇 IPFS 教程中,我们将创建私有 IPFS 网络,并在私有 IPFS 网络之上配置 IPFS-Cluster 以进行数据复制。

尽管 IPFS 自身不提供在网络中所有节点上进行数据复制,但仍然有两种方式可以在 IPFS 中复制数据。使用 Filecoin 或 IPFS-Cluster。我们通过 IPFS-Cluster 来使用这个功能。我们会使用三台虚拟机来部署我们的私有网络。

下面是我们用到的工具的相关链接:

IPFS:一种协议和网络,用于在分布式文件系统中创建可寻址的点对点内容存储和共享超媒体的方法

Private IPFS:允许 IPFS 只连接到拥有共享密钥的其他对等点。对于IPFS私有网络,每个节点指定它将连接到哪些其他节点。网络中的节点不响应来自网络外部节点的通信。

IPFS-Cluster:IPFS-cluster 是一个独立的应用和命令行客户端,它在一组 IPFS 守护进程之间分配、复制和跟踪 pins。IPFS-Cluster 使用基于 leader 的共识算法 Raft 来协调 pinset 的存储,将数据集分布到参与节点。

值得注意的是,私有网络是在核心 IPFS 功能中实现的默认特性,IPFS-Cluster 是其单独的应用程序。IPFS 和 IPFS-Cluster 应用程序以不同的包安装,以各自的进程运行,它们具有不同的节点 IP 以及 API 入口和端口。IPFS-Cluster 守护进程依赖于 IPFS 守护进程,应该在 IPFS 之后启动。

创建 IPFS 私有网络的详细教程

默认情况夏,IPFS 和 IPFS-Cluster 使用以下端口:

IPFS

4001 - 与其他节点通信 5001 - API 服务 8080 - 网关服务

IPFS-CLUSTER

9094 - HTTP API 端点 9095 - IPFS 代理端点 9096 - Cluster swarm,用来在集群节点间通信

我们将使用最近创建的三个虚拟机,操作系统为 Ubuntu 16.04.根据您的云提供商(AWS、Azure、谷歌等)的不同,您可能需要查看一些额外的设置,比如防火墙或安全组配置,以便让您的节点能够看到彼此。

假设我们有三台虚拟机,IP分别为:

Node1: 192.168.10.1 Node2: 192.168.10.2 Node3: 192.168.10.3

让我们从1节点(Node1)开始,它是我们的引导节点。

Step 1: 安装 Go

sudo add-apt-repository ppa:longsleep/golang-backports
sudo apt-get update
sudo apt-get install golang-go

在 .bashrc 中添加

export GOROOT=/usr/lib/go
export GOPATH=$HOME/go
export PATH=$PATH:$GOROOT/bin:$GOPATH/bin
source ~/.bashrc
go version

Step 2: 安装 IPFS

wget <https://github.com/ipfs/go-ipfs/releases/download/v0.4.21/go-ipfs_v0.4.21_linux-amd64.tar.gz> -O go-ipfs.tar.gz
tar xvfz go-ipfs.tar.gz
cd go-ipfs
./install.sh
ipfs init
ipfs version

在每台 VM 上重复步骤 1 和 2

Step 3: 创建私有网络

一旦你的结点上安装了 Go 和 IPFS,运行下面命令安装 swarm key 生成工具。Swarm key 允许我们创建私有网络并告诉网络结点只与共享这个密钥的结点进行通讯。

下面命令应该只在 Node1 上运行。我们在启动结点上生成 swarm.key,然后将其拷贝到其余结点。

go get -u github.com/Kubuxu/go-ipfs-swarm-key-gen/ipfs-swarm-key-gen

运行工具在 .ipfs 目录生成 swarm.key

ipfs-swarm-key-gen &> ~/.ipfs/swarm.key

拷贝生成的 swarm.key 到私有网络中每个结点的 IPFS 目录。首先,需要从创建的所有节点中删除引导节点的默认条目。

Step 4: 启动 IPFS 结点

ipfs bootstrap rm all

将引导结点的哈希地址添加到包括引导结点在内的每个节点。

ipfs bootstrap add /ip4/192.168.10.1/tcp/4001/ipfs/QmQVvZEmvjhYgsyEC7NvMn8EWf131EcgTXFFJQYGSz4Y83

IP(192.168.10.1) 需要改为你的 Node1 的机器 IP。最后一部分是当你初始化结点(ipfs init)时生成的结点 ID。你可以上面在初始化时打印出来的 peer identity 部分找到对应的 ID。

QmQVvZEmvjhYgsyEC7NvMn8EWf131EcgTXFFJQYGSz4Y83

另外你也可以通过 ipfs id 命令来查看。所以你需要根据 Node1 更改 IP 和结点 ID。 对所有结点都做这个操作。

我们还需要设置环境变量 LIBP2P_FORCE_PNET 来强制网络使用私有模式:

export LIBP2P_FORCE_PNET=1

配置 IP 来进行通信

.ipfs 目录,又一个 config 文件。它包含许多配置,包括我们的 IPFS 结点的网络细节。打开这个配置文件,找到 Addresses。它看起来是这样的:

"Addresses": {
"API": "/ip4/192.168.10.1/tcp/5001",
"Announce": [],
"Gateway": "/ip4/192.168.10.1/tcp/8080",
"NoAnnounce": [],
"Swarm": [
"/ip4/0.0.0.0/tcp/4001",
"/ip6/::/tcp/4001"
]
},

API 部分的 IP 是 IPFS 用来通信所绑定的 IP。默认情况下,是 localhost(127.0.0.1)。因此,为了使我们的节点能够“看到”彼此,我们需要相应地将这个参数设置为每个节点的IP。网关参数用于从浏览器访问。

Step 5: 启动结点并测试

我们已经完成了所有配置,现在是时候启动所有节点来看看一切是否正常,以及它们是否为私有网络。在所有节点上运行IPFS守护进程。

ipfs daemon

现在从一个结点添加文件,然后尝试从另一个结点访问

mkdir test-files
echo hi IPFS &> file.txt
ipfs add file.txt

尝试从另一个结点通过打印出来的 hash 访问文件

ipfs cat QmZULkCELmmk5XNfCgTnCyFgAVxBRBXyDHGGMVoLFLiXEN

你应该可以看到第一个结点添加文件的内容。为了检查并确保我们有一个私有网络,我们可以尝试通过它的CID从公共IPFS网关访问我们的文件。你可以从这个列表中选择一个公共网关:https://ipfs.github.io/publicgateway-checker。

Step 6: 在后台以服务的形式运行IPFS守护进程

为了让 IPFS 守护进程可以在我们退出控制台会话后继续运行,我们将会创建 systemd 服务。在我们做这个之前,先停止你的 ipfs 守护进程。为新服务创建一个文件。

sudo vim /etc/systemd/system/ipfs.service

然后添加如下配置:

[Unit]
 Description=IPFS Daemon
 After=syslog.target network.target remote-fs.target nss-lookup.target
 [Service]
 Type=simple
 ExecStart=/usr/local/bin/ipfs daemon --enable-namesys-pubsub
 User=root
 [Install]
 WantedBy=multi-user.target

保存文件 添加新服务

sudo systemctl daemon-reload
sudo systemctl enable ipfs
sudo systemctl start ipfs
sudo systemctl status ipfs

重新启动系统,检查IPFS守护进程是否处于活动状态并正在运行,然后可以再次尝试从一个节点添加文件并从另一个节点访问它。

我们已经完成了创建私有 IPFS 网络并将其守护进程作为服务运行的工作。在这个阶段,你应该已经有了三个私有网络结点。现在,让我们创建用于数据复制的 IPFS-CLUSTER。

部署 IPFS-Cluster

在创建私有 IPFS 网络之后,我们可以开始在 IPFS 之上部署 IPFS-Cluster,以实现数据的自动复制和更好的数据管理。

有两种方法来组织 IPFS 集群,第一种是设置一个固定的 peerset(所以在创建集群后,你不能增加更多的结点),另一个是通过引导节点(你可以在集群创建后添加新的结点)。

IPFS-Cluster 包活两个组件:

  • ipfs-cluster-service 主要用来初始化集群结点并运行守护进程
  • ipfs-cluster-ctl 用来管理集群间的结点和数据

Step 1: 安装 IPFS-Cluster

IPFS-Cluster 提供了多种安装方式,此处我们直接安

git clone <https://github.com/ipfs/ipfs-cluster.git>
export GO111MODULE=on # optional, if checking out the repository in $GOPATH.
go install ./cmd/ipfs-cluster-service
go install ./cmd/ipfs-cluster-ctl

运行一下命令检查是否成功安装

ipfs-cluster-service --version
ipfs-cluster-ctl --version

在所有结点上重复这一步

Step 2: 生成并配置 CLUSTER_SECRET 变量

现在我们需要生成 CLUSTER_SECRET 并为集群中的所有结点配置该环境变量。共享 CLUSTER_SECRET 允许结点理解它们是 IPFS 集群的一部分。我们将会在第一个结点上生成这个 key 然后拷贝到其余结点。在你的第一个结点上运行以下命令:

export CLUSTER_SECRET=$(od -vN 32 -An -tx1 /dev/urandom | tr -d ' \\n')  echo $CLUSTER_SECRET

你应该看到类似于如下的字符串:

1ef9470ba20ca19472f545d2358a521f6eb935c23dc94b7dc3595037828457ae

为了你退出会话后 CLUSTER_SECRET 不消失,你必须在 .bashrc 中将其添加为常量环境变量。将打印出来的 key 拷贝到集群所有结点的 .bashrc 文件中

它应该看来像下面这样

export CLUSTER_SECRET=1ef9470ba20ca19472f545d2358a521f6eb935c23dc94b7dc3595037828457ae

别忘记更新 .bashrc

source ~/.bashrc

Step3: 初始化并启动集群

我们安装 IPFS-Cluster 服务并设置 CLUSTER_SECRET 环境变量后,我们准备初始化和启动第一个集群集群几点(Node1)

注意:确保你的 ipfs 守护进程在你启动 ipfs-cluster-service 守护进程前是正常运行的。

运行下面命令初始化集群结点

ipfs-cluster-service init

启动集群结点,运行:

ipfs-cluster-service daemon

PS: 需要更改 .ipfs-cluster 目录下的 service.json 中的 API 地址(端口为 5001)为相应机器的 IP 地址

启动后,你会看到如下的日志

INFO    cluster: ** IPFS Cluster is READY ** cluster.go:460

在其他结点上通过引导结点启动 ipfs-cluster

ipfs-cluster-service init
ipfs-cluster-service daemon --bootstrap
/ip4/192.168.10.1/tcp/9096/ipfs/QmZjSoXUQgJ9tutP1rXjjNYwTrRM9QPhmD9GHVjbtgWxEn

IP 部分(192.168.10.1)应该是你 Node1 的机器 IP。最后一部分是初始化集群结点时候生成的 ID(ipfs-cluster-service init)。注意这里是 IPFS-Cluster 结点 ID,不是 IPFS 结点 ID。

你可以通过 ipfs-cluster-ctl id 命令来获取ID。

验证集群结点

ipfs-cluster-ctl peers ls

结果应该类似下面这样

node1 & > ipfs-cluster-ctl peers ls
QmYFYwnFUkjFhJcSJJGN72wwedZnpQQ4aNpAtPZt8g5fCd | Sees 1 other peers
Addresses:
- /ip4/127.0.0.1/tcp/10096/ipfs/QmYFYwnFUkjFhJcSJJGN72wwedZnpQQ4aNpAtPZt8g5fCd
- /ip4/192.168.1.3/tcp/10096/ipfs/QmYFYwnFUkjFhJcSJJGN72wwedZnpQQ4aNpAtPZt8g5fCd
IPFS: Qmaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
- /ip4/127.0.0.1/tcp/4001/ipfs/Qmaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
- /ip4/192.168.1.3/tcp/4001/ipfs/Qmaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
QmZjSoXUQgJ9tutP1rXjjNYwTrRM9QPhmD9GHVjbtgWxEn | Sees 1 other peers
Addresses:
- /ip4/127.0.0.1/tcp/9096/ipfs/QmZjSoXUQgJ9tutP1rXjjNYwTrRM9QPhmD9GHVjbtgWxEn
- /ip4/192.168.1.2/tcp/9096/ipfs/QmZjSoXUQgJ9tutP1rXjjNYwTrRM9QPhmD9GHVjbtgWxEn
IPFS: Qmbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
- /ip4/127.0.0.1/tcp/4001/ipfs/Qmbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
- /ip4/192.168.1.2/tcp/4001/ipfs/Qmbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb

重复这一步在其余你想加入集群的结点上。

Step 4: 作为服务运行 IPFS-Cluster 守护进程

为了 IPFS-Cluster 可以在我们退出终端后继续运行,我们将为它创建 systemd 服务。运行以下命令创建 IPFS-Cluster 系统服务

sudo vim /etc/systemd/system/ipfs-cluster.service

写入以下配置

[Unit]
Description=IPFS-Cluster Daemon
Requires=ipfs
After=syslog.target network.target remote-fs.target nss-lookup.target ipfs
[Service]
Type=simple
ExecStart=~/go/bin/ipfs-cluster-service daemon
User=root
[Install]
WantedBy=multi-user.target

添加新服务并运行

sudo systemctl daemon-reload
sudo systemctl enable ipfs-cluster
sudo systemctl start ipfs-cluster
sudo systemctl status ipfs-cluster

重启机器检查 IPFS 和 IPFS-Cluster 服务是否正在运行

Step 5: 测试 IPFS-Cluster 和数据复制

为了测试数据复制,创建文件然后将其添加到集群:

ipfs-cluster-ctl add myfile.txt

通过刚刚所添加文件的 CID 来检查文件的状态

ipfs-cluster-ctl status CID

你应该看到这个文件已经被 PINNED 到所有的集群结点