Please enable Javascript to view the contents

容器化部署 DeepSeek 3FS 存储系统

 ·  ☕ 7 分钟

1. 部署方案

在开始容器化部署之前,先提几点要求:

  • 为了简化交付,只需要一个镜像
  • 为了可靠性,尽可能多副本部署
  • 通过不同的参数启动不同的服务
  • 通过环境变量注入配置,渲染到配置文件中

下面是 DeepSeek 3FS 的部署方案:

需要部署:

  • 一个 Monitor 用来收集监控数据,数据存储在 ClickHouse 中
  • 一个 Admin CLI 提供集群管理的终端,每个组件都需要通过 Admin CLI 提交配置
  • 三个 MgmtD 用来管理集群,将组件、心跳等信息存储在 FoundationDB 中
  • 三个 Meta 用来提供 Chain 和文件信息,数据存储在 FoundationDB 中
  • 尽可能多的 Storage 用来存储数据, 文件以 Chunk 的形式存储在磁盘目录中
  • 若干 Fuse 用来提供 POSIX 文件系统接口,将数据存储在应用层,如果能基于 USRBIO 用户态的接口调用存储服务,相较于 Fuse 会有 3-5 倍的性能提升。

这些服务部署的主机全都需要 RDMA 网络(不仅是支持 RDMA 的网卡,还要交换机支持 RDMA)连接起来。消费 3FS 存储服务的应用程序也需要运行在支持 RDMA 的主机上。

默认情况下 MgmtD 和 Storage 服务有端口冲突,需要部署在不同的主机上。可能大部分团队并没有规划专用的 RDMA 存储集群,使用 3FS 时要和训练、推理任务部署在一起,以充分利用资源。本着尽可能节约资源的原则,将 Monitor 与 Mgmd 部署在一起;为了方便管理集群部署地 Admin CLI 也与 Mgmd 部署在一起。

2. 编译 3FS 镜像

  • 启动编译容器
1
nerdctl run -it --rm -v $(pwd):/app shaowenchen/demo-3fsbuilder:latest bash

基础镜像使用的是 Ubuntu 22.04,我也制作了基于 Ubuntu 20.04 的镜像 shaowenchen/demo-3fsbuilder:latest.2004

  • 创建 Dockerfile
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
ARG BASE_IMAGE=shaowenchen/demo-3fsbuilder:latest
FROM ${BASE_IMAGE} as builder
RUN git clone https://github.com/deepseek-ai/3FS && \
    cd 3FS && \
    git submodule update --init --recursive && \
    ./patches/apply.sh && \
    cmake -S . -B build -DCMAKE_CXX_COMPILER=clang++-14 -DCMAKE_C_COMPILER=clang-14 -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_EXPORT_COMPILE_COMMANDS=ON && \
    cmake --build build -j 100
FROM ${BASE_IMAGE}
COPY --from=builder /app/3FS/build/bin /opt/3fs/bin
COPY --from=builder /app/3FS/configs /opt/3fs/etc
COPY --from=builder /app/3FS/deploy /opt/3fs/deploy
COPY --from=builder /app/3FS/build/third_party/jemalloc/lib/libjemalloc.so.2 /lib/x86_64-linux-gnu/
RUN mkdir -p /var/log/3fs/ && \
    wget -O /opt/3fs/bin/3fs-entrypoint.sh https://raw.githubusercontent.com/shaowenchen/demo/master/3fs-deploy/3fs-entrypoint.sh && \
    chmod +x /opt/3fs/bin/3fs-entrypoint.sh
WORKDIR /opt/3fs/bin
  • 编译镜像

默认是 Ubuntu 22.04

1
nerdctl build --build-arg BASE_IMAGE=shaowenchen/demo-3fsbuilder -t shaowenchen/demo-3fs .

也可以使用 Ubuntu 20.04

1
nerdctl build --build-arg BASE_IMAGE=shaowenchen/demo-3fsbuilder:latest.2004 -t shaowenchen/demo-3fs:latest.2004 .

不方便编译的同学,可以直接去镜像中拿二进制和依赖包,如果访问 Dockerhub 网络不通,可以使用 registry.cn-beijing.aliyuncs.com/shaowenchen/demo-3fs 镜像地址。

3. 部署依赖的中间件

3.1 ClickHouse

  • 部署 Operator
1
kubectl apply -f https://raw.githubusercontent.com/shaowenchen/hubimage/refs/heads/main/storage/clickhouse-operator-0.24.5/crd.install-bundle.yaml
1
kubectl apply -f https://raw.githubusercontent.com/shaowenchen/hubimage/refs/heads/main/storage/clickhouse-operator-0.24.5/deploy.install-bundle.yaml
  • 创建 ClickHouse 集群
1
kubectl apply -f https://raw.githubusercontent.com/shaowenchen/hubimage/refs/heads/main/storage/clickhouse-operator-0.24.5/cluster.yaml

在 yaml 中设置有 clickhouse 的访问凭证信息。

  • 等待就绪
1
2
3
4
5
6
7
kubectl get pod -l clickhouse.altinity.com/cluster=test-cluster

NAME                                  READY   STATUS    RESTARTS   AGE
chi-test-cluster-test-cluster-0-0-0   1/1     Running   0          7m53s
chi-test-cluster-test-cluster-0-1-0   1/1     Running   0          3m9s
chi-test-cluster-test-cluster-1-0-0   1/1     Running   0          7m55s
chi-test-cluster-test-cluster-1-1-0   1/1     Running   0          3m14s
  • 暴露服务
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
kubectl apply -f - <<EOF
apiVersion: v1
kind: Service
metadata:
  name: chi-test-cluster-exposed
  namespace: default
  labels:
    clickhouse.altinity.com/cluster: test-cluster
spec:
  type: NodePort
  selector:
    clickhouse.altinity.com/cluster: test-cluster
  ports:
    - name: tcp
      port: 9000
      protocol: TCP
      targetPort: 9000
      nodePort: 30000
    - name: http
      port: 8123
      protocol: TCP
      targetPort: 8123
    - name: interserver
      port: 9009
      protocol: TCP
      targetPort: 9009
EOF

这样在 http://node-ip:30000 就可以访问 ClickHouse 了。

  • 创建数据库

进入任意一个 ClickHouse 的 Pod

1
kubectl exec -it chi-test-cluster-test-cluster-0-0-0 bash

下载数据库脚本

1
wget https://raw.githubusercontent.com/deepseek-ai/3FS/refs/heads/main/deploy/sql/3fs-monitor.sql

创建数据库

1
clickhouse-client -n < 3fs-monitor.sql

3.2 FoundationDB

  • 部署 Operator
1
kubectl apply -f https://raw.githubusercontent.com/shaowenchen/hubimage/refs/heads/main/storage/fdb-kubernetes-operator-2.0.0/apps.foundationdb.org_foundationdbbackups.yaml
1
kubectl apply -f https://raw.githubusercontent.com/shaowenchen/hubimage/refs/heads/main/storage/fdb-kubernetes-operator-2.0.0/apps.foundationdb.org_foundationdbclusters.yaml
1
kubectl apply -f https://raw.githubusercontent.com/shaowenchen/hubimage/refs/heads/main/storage/fdb-kubernetes-operator-2.0.0/apps.foundationdb.org_foundationdbrestores.yaml
1
kubectl apply -f https://raw.githubusercontent.com/shaowenchen/hubimage/refs/heads/main/storage/fdb-kubernetes-operator-2.0.0/deployment.yaml
  • 创建 FoundationDB 集群
1
kubectl apply -f https://raw.githubusercontent.com/shaowenchen/hubimage/refs/heads/main/storage/fdb-kubernetes-operator-2.0.0/cluster.yaml

这里的实例名字已经改为 fdb-a800。

  • 等待就绪
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
kubectl get pod -l foundationdb.org/fdb-cluster-name=fdb-a800

NAME                                READY   STATUS    RESTARTS   AGE
fdb-a800-cluster-controller-49248   2/2     Running   0          4h21m
fdb-a800-log-19564                  2/2     Running   0          4h21m
fdb-a800-log-30929                  2/2     Running   0          4h21m
fdb-a800-log-98017                  2/2     Running   0          4h21m
fdb-a800-log-9876                   2/2     Running   0          4h21m
fdb-a800-storage-16687              2/2     Running   0          4h21m
fdb-a800-storage-31181              2/2     Running   0          4h21m
fdb-a800-storage-90277              2/2     Running   0          4h21m
  • 获取 FDB 集群的连接信息
1
2
3
kubectl exec -it fdb-a800-cluster-controller-49248  cat /var/dynamic-conf/fdb.cluster

fdb_a800:[email protected]:4501,fdb-a800-log-30929.fdb-a800.default.svc.cluster.local:4501,fdb-a800-log-98017.fdb-a800.default.svc.cluster.local:4501

但在 Containerd 启动的容器中无法解析上面的域名,需要使用 Service 的 IP。

  • 暴露服务
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
kubectl apply -f - <<EOF
apiVersion: v1
kind: Service
metadata:
  name: fdb-a800-exposed
spec:
  ports:
  - port: 4501
    protocol: TCP
    targetPort: 4501
  selector:
    foundationdb.org/fdb-cluster-name: fdb-a800
    foundationdb.org/fdb-process-class: log
  type: ClusterIP
EOF

下面才是容器需要的连接信息:

1
fdb_a800:[email protected]:4501

这里有一个细节是,在 K8s 集群的节点上使用 nerdctl 启动的容器可以访问集群的 Service\Pod IP。

没有使用 NodePort 的原因在于,会出现下面的错误,端口不一致断言。

1
Assertion pkt.canonicalRemotePort == peerAddress.port failed @ /home/foundationdb_ci/src/oOoOoOoOoOoOoOoOoOoOoOoOoOoOoOoOoOoOoOoOo/foundationdb/fdbrpc/FlowTransport.actor.cpp 1545:

在集群外访问 FoundationDB,建议使用二进制部署 FoundationDB,使用物理机 IP 作为连接地址。

1
2
3
4
wget https://ghfast.top/https://github.com/apple/foundationdb/releases/download/7.1.26/foundationdb-clients_7.1.26-1_amd64.deb
wget https://ghfast.top/https://github.com/apple/foundationdb/releases/download/7.1.26/foundationdb-server_7.1.26-1_amd64.deb
dpkg -i foundationdb-clients_7.1.26-1_amd64.deb
dpkg -i foundationdb-server_7.1.26-1_amd64.deb

/etc/foundationdb/fdb.cluster 中的 IP 替换为主机的 IP,重启之后,即可从任意连通的来源访问 FoundationDB 服务。

1
systemctl restart foundationdb.service

4. 容器启动 3FS 服务

4.1 公共环境变量

这里主要设置一些公共的变量,每次启动服务之前都需要设置。

1
2
export FDB_CLUSTER="xxx:[email protected]:4500"
export IMAGE=shaowenchen/demo-3fs:latest

4.2 一个 Monitor

  • 设置环境变量

CLUSTER_ID 是 3FS 的集群 ID,需要保持集群组件中一致。

在设置 DEVICE_FILTER 之前可以先运行 ibdev2netdev 查看有哪些可用的设备,这里需要注意不要将 IB 和 RoCE 设备混用。

1
2
3
4
5
6
7
export CLUSTER_ID=stage
export CLICKHOUSE_DB=3fs
export CLICKHOUSE_HOST=x.x.x.x
export CLICKHOUSE_PASSWD=xxxx
export CLICKHOUSE_PORT=30000
export CLICKHOUSE_USER=app
export DEVICE_FILTER="mlx5_0,mlx5_1,mlx5_4,mlx5_5"
  • 启动 Monitor

Monitor 会占用端口 10000

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
nerdctl run --name 3fs_monitor \
               --privileged \
               --network host \
               -d --restart always \
               --env CLUSTER_ID=${CLUSTER_ID} \
               --env CLICKHOUSE_DB=${CLICKHOUSE_DB} \
               --env CLICKHOUSE_HOST=${CLICKHOUSE_HOST} \
               --env CLICKHOUSE_PASSWD=${CLICKHOUSE_PASSWD} \
               --env CLICKHOUSE_PORT=${CLICKHOUSE_PORT} \
               --env CLICKHOUSE_USER=${CLICKHOUSE_USER} \
               --env FDB_CLUSTER=${FDB_CLUSTER} \
               --env DEVICE_FILTER=${DEVICE_FILTER} \
               ${IMAGE} \
               ./3fs-entrypoint.sh monitor

4.3 一个 Admin CLI

Admin CLI 是一个管理终端,不占用端口,可以和其他服务公用一个节点部署。

  • 设置环境变量

这里的 MGMTD_SERVER_ADDRESSES 需要提前规划出来,不用先启动服务,可以直接设置;REMOTE_IP 是 Monitor 服务暴露的地址。

1
2
export MGMTD_SERVER_ADDRESSES="RDMA://x.x.x.x:8000,RDMA://x.x.x.x:8000,RDMA://x.x.x.x:8000"
export REMOTE_IP=x.x.x.x:10000
  • 启动 Admin CLI
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
nerdctl run --name 3fs_admin_cli \
            --privileged \
            --network host \
            -d --restart always \
            --env FDB_CLUSTER=${FDB_CLUSTER} \
            --env MGMTD_SERVER_ADDRESSES=${MGMTD_SERVER_ADDRESSES} \
            --env DEVICE_FILTER=${DEVICE_FILTER} \
            --env CLUSTER_ID=${CLUSTER_ID} \
            --env REMOTE_IP=${REMOTE_IP} \
            ${IMAGE} \
            ./3fs-entrypoint.sh admin_cli
  • 进入 Admin CLI 容器
1
nerdctl exec -it 3fs_admin_cli bash
  • 初始化集群
1
/opt/3fs/bin/admin_cli -cfg /opt/3fs/etc/admin_cli.toml "init-cluster --mgmtd /opt/3fs/etc/mgmtd_main.toml 1 1048576 6"

1 表示链表 ID;1048576 表示块大小(以字节为单位),也就是 1M;6 表示文件条带化大小。

4.4 多个 MgmtD

  • 设置环境变量

每个 Mgmtd 设置的 MGMTD_NODE_ID 应该不一样。

1
2
3
export MGMTD_NODE_ID="1"
export DEVICE_FILTER="mlx5_0,mlx5_1,mlx5_4,mlx5_5"
export REMOTE_IP=x.x.x.x:10000
  • 启动 Mgmtd

Mgmtd 服务监听端口 8000、9000

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
nerdctl run --name 3fs_mgmtd \
            --privileged \
            --network host \
            -d --restart always \
            --env CLUSTER_ID=${CLUSTER_ID} \
            --env FDB_CLUSTER=${FDB_CLUSTER} \
            --env MGMTD_NODE_ID=${MGMTD_NODE_ID} \
            --env DEVICE_FILTER=${DEVICE_FILTER} \
            --env REMOTE_IP=${REMOTE_IP} \
            ${IMAGE} \
            ./3fs-entrypoint.sh mgmtd

4.5 多个 Meta

Meta 和 Mgmtd 监听的端口不一样,可以部署在同一台机器上。

  • 设置环境变量

每个 Meta 设置的 META_NODE_ID 应该不一样。

1
2
3
4
export MGMTD_SERVER_ADDRESSES="RDMA://x.x.x.x:8000,RDMA://x.x.x.x:8000,RDMA://x.x.x.x:8000"
export META_NODE_ID="101"
export DEVICE_FILTER="mlx5_0,mlx5_1,mlx5_4,mlx5_5"
export REMOTE_IP=x.x.x.x:10000
  • 启动 Meta

Meta 服务监听端口 8001、9001

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
nerdctl run  --name 3fs_meta \
               --privileged \
               -d --restart always \
               --network host \
               --env CLUSTER_ID=${CLUSTER_ID} \
               --env FDB_CLUSTER=${FDB_CLUSTER} \
               --env MGMTD_SERVER_ADDRESSES=${MGMTD_SERVER_ADDRESSES} \
               --env META_NODE_ID=${META_NODE_ID} \
               --env DEVICE_FILTER=${DEVICE_FILTER} \
               --env REMOTE_IP=${REMOTE_IP} \
               ${IMAGE} \
               ./3fs-entrypoint.sh meta

4.6 多个 Storage

Storage 服务需要与 Mgmtd 服务分开,它们使用了相同的端口。

  • 设置环境变量

每个 Storage 设置的 STORAGE_NODE_ID 应该不一样;TARGET_PATHS 是存储的目录,由于这里是容器化部署可以保持固定值,通过修改挂载参数设置存储目录。

1
2
3
4
5
export MGMTD_SERVER_ADDRESSES="RDMA://x.x.x.x:8000,RDMA://x.x.x.x:8000,RDMA://x.x.x.x:8000"
export STORAGE_NODE_ID="1001"
export TARGET_PATHS="/3fs/data"
export DEVICE_FILTER="mlx5_0,mlx5_1,mlx5_4,mlx5_5"
export REMOTE_IP=x.x.x.x:10000
  • 修改系统参数
1
sysctl -w fs.aio-max-nr=67108864
  • 启动 Storage

Storage 服务监听端口 8000、9000

mkdir -p /data/3fs
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
nerdctl run --name 3fs_storage \
            --privileged \
            -d --restart always \
            --network host \
            -v /data/3fs:/3fs/data \
            --env CLUSTER_ID=${CLUSTER_ID} \
            --env FDB_CLUSTER=${FDB_CLUSTER} \
            --env MGMTD_SERVER_ADDRESSES=${MGMTD_SERVER_ADDRESSES} \
            --env STORAGE_NODE_ID=${STORAGE_NODE_ID} \
            --env TARGET_PATHS=${TARGET_PATHS} \
            --env DEVICE_FILTER=${DEVICE_FILTER} \
            --env REMOTE_IP=${REMOTE_IP} \
            ${IMAGE} \
            ./3fs-entrypoint.sh storage

4.7 Admin Cli 查看节点

  • 进入 Admin CLI 容器
1
nerdctl exec -it 3fs_admin_cli bash
  • 查看节点
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
/opt/3fs/bin/admin_cli  -cfg /opt/3fs/etc/admin_cli.toml list-nodes

Id    Type     Status               Hostname      Pid  Tags  LastHeartbeatTime    ConfigVersion  ReleaseVersion
1     MGMTD    PRIMARY_MGMTD        58ca52320c3b  16   []    N/A                  1(UPTODATE)    250228-dev-1-999999-8c9883c2
2     MGMTD    HEARTBEAT_CONNECTED  391173a5a978  16   []    2025-03-15 13:45:48  1(UPTODATE)    250228-dev-1-999999-8c9883c2
3     MGMTD    HEARTBEAT_CONNECTED  8c05a1fbdf97  16   []    2025-03-15 13:45:50  1(UPTODATE)    250228-dev-1-999999-8c9883c2
101   META     HEARTBEAT_CONNECTED  b3fea43900e6  202  []    2025-03-15 13:45:48  4(UPTODATE)    250228-dev-1-999999-8c9883c2
102   META     HEARTBEAT_CONNECTED  fcebcb6ca5c3  192  []    2025-03-15 13:45:52  4(UPTODATE)    250228-dev-1-999999-8c9883c2
103   META     HEARTBEAT_CONNECTED  fea159ba0bd6  194  []    2025-03-15 13:45:49  4(UPTODATE)    250228-dev-1-999999-8c9883c2
1001  STORAGE  HEARTBEAT_CONNECTED  919404e2891f  188  []    2025-03-15 13:45:51  7(UPTODATE)    250228-dev-1-999999-8c9883c2
1002  STORAGE  HEARTBEAT_CONNECTED  e19b012d073c  180  []    2025-03-15 13:45:51  7(UPTODATE)    250228-dev-1-999999-8c9883c2
1003  STORAGE  HEARTBEAT_CONNECTED  fd2423d5e695  173  []    2025-03-15 13:45:52  7(UPTODATE)    250228-dev-1-999999-8c9883c2
1004  STORAGE  HEARTBEAT_CONNECTED  e8b6fbb9a774  184  []    2025-03-15 13:45:52  7(UPTODATE)    250228-dev-1-999999-8c9883c2
1005  STORAGE  HEARTBEAT_CONNECTED  283ae64fb9c4  168  []    2025-03-15 13:45:53  7(UPTODATE)    250228-dev-1-999999-8c9883c2

5. 创建 3FS 存储实例

  • 进入 Admin CLI
1
nerdctl exec -it 3fs_admin_cli bash
  • 创建用户
1
/opt/3fs/bin/admin_cli -cfg /opt/3fs/etc/admin_cli.toml "user-add --root --admin 0 root"
1
2
3
4
5
6
7
Uid                0
Name               root
Token              AAA1+B5D8QCAeUKZ2wCBx/b5(Expired at N/A)
IsRootUser         true
IsAdmin            true
Gid                0
SupplementaryGids

这里的 AAA1+B5D8QCAeUKZ2wCBx/b5 就是 root 用户的 token。

  • 安装依赖
1
2
3
apt update
apt install -y python3-pip
pip install -r /opt/3fs/deploy/data_placement/requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple
  • 执行 data_placement 计算命令
1
2
python3 /opt/3fs/deploy/data_placement/src/model/data_placement.py \
   -ql -relax -type CR --num_nodes 5 --replication_factor 3 --min_targets_per_disk 6

这里的 replication_factor 不能大于 num_nodes,需要记录一下输出的结果,下一步会用到。

1
2025-03-15 16:21:45.429 | SUCCESS  | __main__:run:148 - saved solution to: output/DataPlacementModel-v_5-b_10-r_6-k_3-λ_2-lb_1-ub_1
  • 生成 chainTable

这里的 node_id_beginnode_id_end 需要和上面的 storage 节点的 STORAGE_NODE_ID 一致。

1
2
3
4
5
python3 /opt/3fs/deploy/data_placement/src/setup/gen_chain_table.py \
   --chain_table_type CR --node_id_begin 1001 --node_id_end 1005 \
   --num_disks_per_node 1 --num_targets_per_disk 6 \
   --target_id_prefix 1 --chain_id_prefix 9 \
   --incidence_matrix_path output/DataPlacementModel-v_5-b_10-r_6-k_3-λ_2-lb_1-ub_1/incidence_matrix.pickle
  • 创建 Storage Target
1
/opt/3fs/bin/admin_cli --cfg /opt/3fs/etc/admin_cli.toml --config.user_info.token $(<"/opt/3fs/etc/token.txt") < output/create_target_cmd.txt

这里会输出一个 target 在每个节点上的分布情况。

  • 上传 chainTable
1
/opt/3fs/bin/admin_cli --cfg /opt/3fs/etc/admin_cli.toml --config.user_info.token $(<"/opt/3fs/etc/token.txt") "upload-chains output/generated_chains.csv"
1
/opt/3fs/bin/admin_cli --cfg /opt/3fs/etc/admin_cli.toml --config.user_info.token $(<"/opt/3fs/etc/token.txt") "upload-chain-table --desc stage 1 output/generated_chain_table.csv"

6. Fuse 挂载

  • 设置环境变量

这里的 TOKEN 就是上面创建的 root 用户的 token。

1
2
3
4
5
6
7
export CLUSTER_ID=stage
export FDB_CLUSTER="x:[email protected]:4500"
export MGMTD_SERVER_ADDRESSES="RDMA://x.x.x.x:8000,RDMA://x.x.x.x:8000,RDMA://x.x.x.x:8000"
export REMOTE_IP=x.x.x.x:x
export DEVICE_FILTER="mlx5_0,mlx5_1,mlx5_4,mlx5_5"
export TOKEN=xxx
export IMAGE=shaowenchen/demo-3fs:latest
  • 创建主机挂载点
1
mkdir -p /mnt/3fs
  • 启动 Fuse
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
nerdctl run --name 3fs_fuse_container \
            --privileged \
            -d --restart always \
            --network host \
            --mount type=bind,source=/mnt/3fs,target=/mnt/3fs,bind-propagation=shared \
            --env CLUSTER_ID=${CLUSTER_ID} \
            --env FDB_CLUSTER=${FDB_CLUSTER} \
            --env MGMTD_SERVER_ADDRESSES=${MGMTD_SERVER_ADDRESSES} \
            --env REMOTE_IP=${REMOTE_IP} \
            --env DEVICE_FILTER=${DEVICE_FILTER} \
            --env TOKEN=${TOKEN} \
            ${IMAGE} \
            ./3fs-entrypoint.sh fuse

-v 只能将主机的目录挂载到容器中,而这里需要的是将容器中的目录挂载到主机上,所以使用 --mount 参数配合 bind-propagation=shared 进行挂载。

  • 在主机上查看挂载点
1
2
3
4
df -h /mnt/3fs/

Filesystem      Size  Used Avail Use% Mounted on
hf3fs.stage      57T  2.5T   55T   5% /mnt/3fs
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
tree  /mnt/3fs

/mnt/3fs
└── 3fs-virt
    ├── get-conf
    │   ├── sys.io_job_deq_timeout -> '1ms'
    │   ├── sys.io_worker_coros.hi -> 8
    │   ├── sys.io_worker_coros.lo -> 8
    │   ├── sys.max_jobs_per_ioring -> 32
    │   ├── sys.periodic_sync.enable -> true
    │   ├── sys.periodic_sync.flush_write_buf -> true
    │   ├── sys.periodic_sync.interval -> '30s'
    │   ├── sys.storage.net_client.rdma_control.max_concurrent_transmission -> 64
    │   ├── usr.attr_timeout -> 30.0
    │   ├── usr.dryrun_bench_mode -> false
    │   ├── usr.enable_read_cache -> true
    │   ├── usr.entry_timeout -> 30.0
    │   ├── usr.flush_on_stat -> true
    │   ├── usr.negative_timeout -> 5.0
    │   ├── usr.readonly -> false
    │   ├── usr.symlink_timeout -> 5.0
    │   └── usr.sync_on_stat -> true
    ├── iovs
    │   ├── submit-ios -> /dev/shm/sem.hf3fs-submit-ios.c52d4079-b1c0-4684-9d08-6f2ee18d8a6e
    │   ├── submit-ios.ph -> /dev/shm/sem.hf3fs-submit-ios.dd3eac7c-3802-422d-93a7-efaf56c6e2af
    │   └── submit-ios.pl -> /dev/shm/sem.hf3fs-submit-ios.e8cf7b88-e65a-4cb5-a3ba-de71351bccee
    ├── rm-rf
    └── set-conf

5 directories, 20 files

7. 总结

本篇主要介绍了如何使用容器化部署 DeepSeek 3FS 存储系统,主要包括以下几个步骤:

  • 编译 3FS 镜像
  • 部署 ClickHouse 和 FoundationDB 中间件
  • 启动 Monitor、Admin CLI、MgmtD、Meta、Storage 服务

根据启动参数的不同,可以启动不同的服务,3fs-entrypoint.sh 脚本内容已经提交到 https://github.com/shaowenchen/demo/blob/master/3fs-deploy/3fs-entrypoint.sh 以供参考。


微信公众号
作者
微信公众号