クラスタを作っている所(進行形)なのでそのメモを残していきます。この記事ではおうちARMボードに、SeaweedFSを入れます。
おうちクラスタシリーズ
- 第1弾: ハードウェア編
- 第2弾: Portainer編
- 第3弾: Ceph編(失敗)
- 第4弾: SeaweedFS編
SeaweedFSについて
複数のストレージを使って分散型オブジェクトストレージを作れるGo製のソフトウェアRAID的なやつです。S3、ファイルシステム、FUSEマウント、WebDAV、Hadoop互換ファイルシステム、WebUIなどなど色々対応してるみたいです。2014年頃から開発されていて、もちろんDocker対応、ARMにもたぶん対応している、らしいです。シングルバイナリになっているので、同じDockerイメージを使い、渡すコマンドを変えるだけで各サーバーを建てられるらしいです。READMEによると、アーキテクチャはGlusterFSやCephとほぼ同じものの、小さなサイズのファイルに特化して、高速でシンプルを目指しているとのことです。
なんでCephを使わないの?
Cephは前回入れようとしたのですが、導入が結構複雑だったのと、(ARMv7/ARM64用のDockerImageがないようで?)途中で詰んでしまったので断念しました。更に更に導入済みの友人に、結構要求スペックが高いと言われてしまったので、ちょっとラズパイではきついのかもしれない。
なんでSeaweedFSを使うの?
Redditのラズパイで組んだDockerSwarmで使う分散ストレージのおすすめを訊くスレッドにて、SeaweedFS開発者さんが宣伝してるコメントを見て気になったのでやってみることにしました。あとQiita内にSeaweedFSを紹介している記事がなかったので、検討してる人のための資料を増やします。
SeaweedFSの用語
https://github.com/chrislusf/seaweedfs/wiki/Components
そこまでややこしい仕様はなくかなりシンプルなものになっています。
SeaweedFSで立ち上げられるサーバーについては項目を分けて書きます。
replication
同じデータの冗長化/複製をやって、信頼性を上げることを指す用語っぽいです。
volume
SeaweedFSでは多数の小さなファイルを1つの大きなファイルにまとめてボリュームという単位で保存するようです。デフォルトでは、マスターの起動時に、30GBのボリュームが8つ構成されます。レプリケーションやTTLはボリューム単位で設定します。
collection
SeaweedFSではボリュームの集まりをコレクションと呼ぶようです。S3互換APIでバケットを作った際に、コレクションが作成されます。これによりバケットの削除や管理を簡単にしているようです。コレクションとなっていても、レプリケーションやTTLはボリュームそれぞれに設定します。コレクションの作成時にボリュームをまとめて用意するので、容量が不足してしまう場合はボリュームを小さくすることがおすすめだそうです。
SeaweedFSの各種サーバー
最低限masterとvolumeさえあればCUIからファイルの読み書きができます。実際にはCUI以外からアクセスする手段が必要になるケースが多いため、使いたい手法に合わせて追加でサーバーを用意します。各サーバーはパラメータを渡しさえすれば、1コンテナでまとめて兼ねさせることもできるようですが、あとでメンテしづらそうなのでおすすめしません。
master
項目 | 内容 |
---|---|
依存 | なし |
役割 | ボリューム等クラスタ全体に指示を出す |
要求台数 | 1台以上 |
負荷 | そこまでかからない |
名前通りで、これがないとクラスタ全体が使えなくなります。複数台マスターを用意する場合は、多数派の指示を発生させるために、奇数台用意する必要があります。
volume
項目 | 内容 |
---|---|
依存 | master |
役割 | ストレージに対してファイルを読み書きする |
要求台数 | 1台以上 |
負荷 | そこそこかかる |
複数のファイルを1ファイルのボリュームという概念にまとめて読み書きします。レプリケーションはボリューム単位で行われます。
filer
項目 | 内容 |
---|---|
依存 | master,volume |
役割 | HTTPアクセスを可能にする+FUSEマウントの前提サーバーとなる |
要求台数 | 任意 |
負荷 | 結構重い |
HTTPAPI経由でファイルをPOST/PUT/GET/DELETE等できるようにしたい場合に利用します。一般的なファイルシステムとしてアクセスしたい場合、前提として必要になります。重いので本当に必要な場合のみ使うことが推奨されています。
s3
項目 | 内容 |
---|---|
依存 | master,volume,filer |
役割 | AWSのS3互換のバケットアクセスを可能にする |
要求台数 | 任意 |
負荷 | ? |
S3互換のAPIを使いたい場合に利用します。
webdav
項目 | 内容 |
---|---|
依存 | master,volume,filer |
役割 | webdavでのアクセスを可能にする |
要求台数 | 任意 |
負荷 | ? |
WebDavでマウントできるようにしたい場合は有効化します。認証機能は無いようなので、実際にはあまり使わないほうがいい気がします(個人的意見)
mount
項目 | 内容 |
---|---|
依存 | master,volume,filer |
役割 | FUSEマウントを行う |
要求台数 | 任意 |
負荷 | ? |
LinuxまたはOSXで、FUSEマウントを行いたい場合に使います。Windowsで使いたい場合は、マウントしたLinux上のSambaを経由すると読み書きできます。(あまりにも大きなファイルだと途中でbrokenpipeが発生します)
cronjob
項目 | 内容 |
---|---|
依存 | master |
役割 | 一定時間毎にレプリケーションを再実行および修復する |
要求台数 | 任意 |
負荷 | ? |
ボリュームサーバーが複数ある場合は、一定時間毎にレプリケーションを修復するコマンドを走らせることができるようです。(Dockerfileの中に実行されるコマンドが書かれています)
SeaweedFS導入
このシステムで使われる用語やクイックスタートのガイドはあったのですが、実際デプロイする構成例があまりなかったので少し困りました。ここでは、マスターが3台、ボリュームが3台、ファイラーが3台、S3が3台、マウントが6台、cronjobが1台の構成を目指しました。
DockerSwarmを使う方法(失敗)
起動方法
README.mdによると、seaweed-compose.ymlをDLして docker-compose up
すれば、最小限の構成が動くみたいです。
Build and push a multiarch build
って欄にARMの言及があるので、DockerHubに、ARMイメージが上がってるのかと思ったのですが、ありませんでした。ビルドは各自でやらないとダメみたいです。
ARM用のビルドとRegistryへのPush
ビルドするコマンドはリポジトリに書かれた通りです。私は今後メンテするかわからないイメージをPublicに上げるのは気が引けるので、TreeScaleに上げました。(以前の記事でビルダーの設定はしてあるので省いてます)
git clone https://github.com/chrislusf/seaweedfs
cd seaweedfs/docker
docker buildx build --pull --push --platform linux/amd64,linux/arm64,linux/arm/v7 . -t repo.treescale.com/ユーザー名/seaweedfs:latest
DockerSwarmの定義ファイルで動かそうとした(失敗)
様々な構成を試しましたが、どうあがいても、filerコンテナとmasterコンテナ間の通信がどうしてもうまくいかず、gRPCエラーを吐きます。ボリューム、マスター、ファイラーが1台ずつの例、もしくはdocker-compose内では動作しますが、マスター1、ファイラー1、ボリューム3をswarmで構成しようとすると、gRPCエラーを吐きます。下記は一応やってみようとしたメモを残します(なにか解決策わかる人は教えて下さい!)
DockerSwarmではできない理想(各replicaのIPアドレスが起動前にわからないため設定できない)
version: '3'
services:
master:
image: repo.treescale.com/dosugamea/seaweedfs:latest # Masterサービス
ports:
- 9333:9333
- 19333:19333
command: "master -ip=master"
deploy:
replicas: 3
resources:
limits:
memory: 100M
placement:
max_replicas_per_node: 1
constraints:
- node.labels.seaweed == true
volume:
image: repo.treescale.com/dosugamea/seaweedfs:latest # ボリュームサービス
ports:
- 8080:8080
- 18080:18080
- 9325:9325
command: 'volume -mserver="master:9333" -port=8080 -metricsPort=9325'
deploy:
replicas: 3
resources:
limits:
memory: 1000M
placement:
max_replicas_per_node: 1
constraints:
- node.labels.seaweed == true
filer:
image: repo.treescale.com/dosugamea/seaweedfs:latest # ファイラーサービス
ports:
- 8888:8888
- 18888:18888
- 9326:9326
command: 'filer -master="master:9333" -metricsPort=9326'
tty: true
stdin_open: true
depends_on:
- master
- volume
deploy:
replicas: 3
resources:
limits:
memory: 1000M
placement:
max_replicas_per_node: 1
constraints:
- node.labels.seaweed == true
cronjob:
image: repo.treescale.com/dosugamea/seaweedfs:latest # cronジョブ
command: 'cronjob'
environment:
# Run re-replication every 2 minutes
CRON_SCHEDULE: '*/2 * * * * *' # Default: '*/5 * * * * *'
WEED_MASTER: master:9333 # Default: localhost:9333
depends_on:
- master
- volume
deploy:
replicas: 1
resources:
limits:
memory: 300M
placement:
max_replicas_per_node: 1
constraints:
- node.labels.seaweed == true
s3:
image: repo.treescale.com/dosugamea/seaweedfs:latest # S3サービス
ports:
- 8333:8333
- 9327:9327
command: 's3 -filer="filer:8888" -metricsPort=9327'
depends_on:
- master
- volume
- filer
deploy:
replicas: 3
placement:
max_replicas_per_node: 1
constraints:
- node.labels.seaweed == true
動かない最小構成Swarm(masterからvolumeに接続できずrpcエラー)
version: '3'
services:
master:
image: repo.treescale.com/dosugamea/seaweedfs:latest # use a remote image
ports:
- 9333:9333
- 19333:19333
command: "master -ip.bind='0.0.0.0' -ip=master"
volume:
image: repo.treescale.com/dosugamea/seaweedfs:latest # use a remote image
ports:
- 8080:8080
- 18080:18080
command: 'volume -ip.bind="0.0.0.0" -mserver="master:9333" -port=8080'
depends_on:
- master
filer:
image: repo.treescale.com/dosugamea/seaweedfs:latest # use a remote image
ports:
- 8888:8888
- 18888:18888
command: 'filer -ip.bind="0.0.0.0" -master="master:9333"'
tty: true
stdin_open: true
depends_on:
- master
- volume
masterx3 volumex3 filerx3 s3x3 mountx3 cronx1 prometheusx1のSwarm定義ファイル
version: '3'
services:
master1:
image: repo.treescale.com/dosugamea/seaweedfs:latest # use a remote image
ports:
- 9333:9333 # HTTP endpoint (dashboard)
- 19333:19333 # gRPC endpoint
command: "master -ip=master1 -port=9333 -master.peers=master1:9333,master2:9333,master3:9333 -mdir=/data -defaultReplication=020 -volumeSizeLimitMB=2048"
volumes:
- /mnt/hdd2/seaweedfs/master1:/data
deploy:
replicas: 1
resources:
limits:
memory: 256M
placement:
constraints:
- node.labels.seaweed-master1 == true
master2:
image: repo.treescale.com/dosugamea/seaweedfs:latest # use a remote image
ports:
- 9334:9333 # HTTP endpoint (dashboard)
- 19334:19333 # gRPC endpoint
command: "master -ip=master2 -port=9333 -master.peers=master1:9333,master2:9333,master3:9333 -mdir=/data -defaultReplication=020 -volumeSizeLimitMB=2048"
volumes:
- /mnt/hdd2/seaweedfs/master2:/data
deploy:
replicas: 1
resources:
limits:
memory: 256M
placement:
constraints:
- node.labels.seaweed-master2 == true
master3:
image: repo.treescale.com/dosugamea/seaweedfs:latest # use a remote image
ports:
- 9335:9333 # HTTP endpoint (dashboard)
- 19335:19333 # gRPC endpoint
command: "master -ip=master3 -port=9333 -master.peers=master1:9333,master2:9333,master3:9333 -mdir=/data -defaultReplication=020 -volumeSizeLimitMB=2048"
volumes:
- /mnt/hdd2/seaweedfs/master3:/data
deploy:
replicas: 1
resources:
limits:
memory: 256M
placement:
constraints:
- node.labels.seaweed-master3 == true
volume:
image: repo.treescale.com/dosugamea/seaweedfs:latest # use a remote image
ports:
- 8081:8080 # HTTP endpoint
- 18080:18080 # gRPC endpoint
- 9325:9325 # metrics endpoint
command: 'volume -mserver="master1:9333,master2:9333,master3:9333" -fileSizeLimitMB=16384 -concurrentUploadLimitMB=16384 -max=100 -minFreeSpace=10 -port=8080 -metricsPort=9325 -index=leveldb -dir=./data -dataCenter=home -disk=hdd'
depends_on:
- master1
- master2
- master3
volumes:
- /mnt/hdd2/seaweedfs/volume:/data
deploy:
replicas: 3
resources:
limits:
memory: 1024M
placement:
constraints:
- node.labels.seaweed == true
filer1:
image: repo.treescale.com/dosugamea/seaweedfs:latest # use a remote image
ports:
- 8888:8888 # HTTP endpoint
- 18888:18888 # gRPC endpoint
- 9326:9326 # metrics endpoint
command: 'filer -master="master1:9333,master2:9333,master3:9333" -peers="filer1:8888,filer2:8888,filer3:8888" -metricsPort=9326'
tty: true
stdin_open: true
depends_on:
- master1
- master2
- master3
- volume
deploy:
replicas: 1
resources:
limits:
memory: 1024M
placement:
constraints:
- node.labels.seaweed1 == true
filer2:
image: repo.treescale.com/dosugamea/seaweedfs:latest # use a remote image
ports:
- 8889:8888 # HTTP endpoint
- 18889:18888 # gRPC endpoint
- 9327:9326 # metrics endpoint
command: 'filer -master="master1:9333,master2:9333,master3:9333" -peers="filer1:8888,filer2:8888,filer3:8888" -metricsPort=9326'
tty: true
stdin_open: true
depends_on:
- master1
- master2
- master3
- volume
deploy:
replicas: 1
resources:
limits:
memory: 1024M
placement:
constraints:
- node.labels.seaweed2 == true
filer3:
image: repo.treescale.com/dosugamea/seaweedfs:latest # use a remote image
ports:
- 8890:8888 # HTTP endpoint
- 18890:18888 # gRPC endpoint
- 9328:9326 # metrics endpoint
command: 'filer -master="master1:9333,master2:9333,master3:9333" -peers="filer1:8888,filer2:8888,filer3:8888" -metricsPort=9326'
tty: true
stdin_open: true
depends_on:
- master1
- master2
- master3
- volume
deploy:
replicas: 1
resources:
limits:
memory: 1024M
placement:
constraints:
- node.labels.seaweed3 == true
s3:
image: repo.treescale.com/dosugamea/seaweedfs:latest # use a remote image
ports:
- 8333:8333 # HTTP endpoint
- 9350:9327 # metrics endpoint
command: 's3 -filer="filer1:8888,filer2:8888,filer3:8888" -metricsPort=9327'
depends_on:
- master1
- master2
- master3
- volume
- filer1
- filer2
- filer3
deploy:
replicas: 3
resources:
limits:
memory: 1024M
placement:
constraints:
- node.labels.seaweed == true
mount:
image: repo.treescale.com/dosugamea/seaweedfs:latest # use a remote image
command: 'mount -filer="filer1:8888,filer2:8888,filer3:8888" -dirAutoCreate -dir=/mnt/seaweedfs -cacheCapacityMB=100 -concurrentWriters=64'
depends_on:
- master1
- master2
- master3
- volume
- filer1
- filer2
- filer3
volumes:
- /mnt/seaweedfs:/mnt/seaweedfs
deploy:
replicas: global
resources:
limits:
memory: 256M
placement:
constraints:
- node.labels.seaweed == true
cronjob:
image: repo.treescale.com/dosugamea/seaweedfs:latest # use a remote image
command: 'cronjob'
environment:
# Run re-replication every 2 minutes
CRON_SCHEDULE: '*/2 * * * * *' # Default: '*/5 * * * * *'
WEED_MASTER: master:9333 # Default: localhost:9333
depends_on:
- master1
- master2
- master3
- volume
- filer1
- filer2
- filer3
deploy:
replicas: 1
resources:
limits:
memory: 300M
placement:
constraints:
- node.labels.seaweed == true
prometheus:
image: prom/prometheus:latest
ports:
- 9000:9090
volumes:
- ./prometheus:/etc/prometheus
command: --web.enable-lifecycle --config.file=/etc/prometheus/prometheus.yml
depends_on:
- s3
masterx1 volumex3 filerx1 s3x3 cronx1 prometheusx1のSwarm定義ファイル
version: '3.8'
services:
master:
image: repo.treescale.com/dosugamea/seaweedfs:latest # use a remote image
command: "master -mdir=/data -volumeSizeLimitMB=2048"
networks:
- weed
volumes:
- /mnt/hdd2/master1:/data
deploy:
mode: replicated
replicas: 1
resources:
limits:
memory: 256M
placement:
constraints:
- node.labels.seaweed-master1 == true
volume:
image: repo.treescale.com/dosugamea/seaweedfs:latest # use a remote image
command: 'volume -mserver=master:9333 -fileSizeLimitMB=16384 -concurrentUploadLimitMB=16384 -max=100 -minFreeSpace=10 -dataCenter=home -rack=jet -metricsPort=9325 -dir=./data'
depends_on:
- master
networks:
- weed
volumes:
- /mnt/hdd2/volume:/data
deploy:
replicas: 1
resources:
limits:
memory: 1024M
placement:
constraints:
- node.labels.seaweed1 == true
volume2:
image: repo.treescale.com/dosugamea/seaweedfs:latest # use a remote image
command: 'volume -mserver=master:9333 -fileSizeLimitMB=16384 -concurrentUploadLimitMB=16384 -max=100 -minFreeSpace=10 -dataCenter=home -rack=pie -metricsPort=9325 -dir=./data'
depends_on:
- master
networks:
- weed
volumes:
- /mnt/hdd2/volume:/data
deploy:
replicas: 1
resources:
limits:
memory: 1024M
placement:
constraints:
- node.labels.seaweed2 == true
volume3:
image: repo.treescale.com/dosugamea/seaweedfs:latest # use a remote image
command: 'volume -mserver=master:9333 -fileSizeLimitMB=16384 -concurrentUploadLimitMB=16384 -max=100 -minFreeSpace=10 -dataCenter=home -rack=rock -metricsPort=9325 -dir=./data'
depends_on:
- master
networks:
- weed
volumes:
- /mnt/hdd2/volume:/data
deploy:
replicas: 1
resources:
limits:
memory: 1024M
placement:
constraints:
- node.labels.seaweed3 == true
filer:
image: repo.treescale.com/dosugamea/seaweedfs:latest # use a remote image
ports:
- "8888:8888/tcp"
command: 'filer -master=master:9333 -metricsPort=9326'
depends_on:
- master
- volume
networks:
- weed
deploy:
mode: replicated
replicas: 1
resources:
limits:
memory: 1024M
placement:
constraints:
- node.labels.seaweed-master1 == true
s3:
image: repo.treescale.com/dosugamea/seaweedfs:latest # use a remote image
ports:
- 8333:8333 # HTTP endpoint
- 9350:9327 # metrics endpoint
command: 's3 -filer="filer:8888" -metricsPort=9327'
depends_on:
- master
- volume
- filer
networks:
- weed
deploy:
mode: replicated
replicas: 3
resources:
limits:
memory: 1024M
placement:
constraints:
- node.labels.seaweed == true
cronjob:
image: repo.treescale.com/dosugamea/seaweedfs:latest # use a remote image
command: 'cronjob'
environment:
# Run re-replication every 2 minutes
CRON_SCHEDULE: '*/2 * * * * *' # Default: '*/5 * * * * *'
WEED_MASTER: master:9333 # Default: localhost:9333
depends_on:
- master
- volume
- filer
networks:
- weed
deploy:
mode: replicated
replicas: 1
resources:
limits:
memory: 300M
placement:
constraints:
- node.labels.seaweed-master1 == true
prometheus:
image: prom/prometheus:v2.28.1
ports:
- 9999:9090
volumes:
- /mnt/hdd2/prometheus:/etc/prometheus
command: --web.enable-lifecycle --config.file=/etc/prometheus/prometheus.yml
depends_on:
- s3
networks:
- weed
deploy:
mode: replicated
replicas: 1
resources:
limits:
memory: 256M
placement:
constraints:
- node.labels.seaweed-master1 == true
networks:
weed:
attachable: true
driver: overlay
Dockerを使わない方法(直接サービスを設定)
Docker上でやるのとは違い、LAN内であれば(設定さえ済ませれば)rpcエラーを起こさず接続できました。
注意点として、weed server
コマンドで、master/filer/volumeを丸ごと1サービスで定義することもできると書いてありましたが、volumeの保存先を指定できない(なぜかidxファイルの保存先しか指定できず、dat/vifファイルが/tmpに保存されていきメモリ不足になる)ので、サービスを分けましょう。
前提
192.168.0.11, 192.168.0.12, 192.168.0.13 の3台のノードがあり、それぞれでmasterをポート9333、filerをポート8888、volumeをポート7070、s3をポート8333を使用するように設定します。同一容量のHDDがそれぞれにつながっていて、パーティションを半分で区切って分けてあり、/mnt/hdd2をSeaweedFS専用にするものとします。mountもそれぞれのノードでさせ、/mnt/seaweedfsにマウントさせます。SeaweedFS専用のユーザーとグループを作成し実行させます。
実行ファイルをダウンロードして展開
GithubのReleasesでビルド済みバイナリが配布されているので、それをDLする。Dockerコンテナとは違い、これはARMビルドも完備している。恐らくはどこに置いてもいいと思うが、今回は既存のチュートリアルに合わせて/usr/local/binに配置しました。
wget https://github.com/chrislusf/seaweedfs/releases/download/2.59/linux_arm64.tar.gz
tar xzvf linux_arm64.tar.gz
sudo mv weed /usr/local/bin
wget https://github.com/chrislusf/seaweedfs/releases/download/2.59/linux_arm.tar.gz
tar xzvf linux_arm.tar.gz
sudo mv weed /usr/local/bin
方法1 サービスをそれぞれ分ける場合
1つ1つ書くと ものすごく長くなったので折りたたみました。
ユーザーとフォルダの作成 (クリックで展開)
# 実行グループを作成
sudo groupadd seaweed
# seaweedというユーザーをhome無しでプライマリグループをseaweedとして作成
sudo useradd seaweed -M -g seaweed
# Masterサービスで使用
sudo mkdir /mnt/hdd2/master
# Volumeサービスで使用
sudo mkdir /mnt/hdd2/volume
# S3サービスで使用
sudo mkdir /mnt/hdd2/buckets
# Filerサービスで使用
sudo mkdir /mnt/hdd2/filerldb2
# Mountサービスで使用
sudo mkdir /mnt/seaweedfs
# HDD丸ごとseaweedユーザーのものとする
sudo chown seaweed:seaweed /mnt/hdd2 -R
Masterサービス(クリックで展開)
[Unit]
Description=SeaweedFS Master
After=network.target
[Service]
Type=simple
User=seaweed
Group=seaweed
ExecStart=/usr/local/bin/weed master -mdir="/mnt/hdd2/master" -ip=192.168.0.11 -peers="192.168.0.11:9333,192.168.0.12:9333,192.168.0.13:9333" -volumeSizeLimitMB=2048 -defaultReplication=020 -port=9333
WorkingDirectory=/usr/local/bin/
SyslogIdentifier=seaweedfs-master
[Install]
WantedBy=multi-user.target
Volumeサービス(クリックで展開)
[Unit]
Description=SeaweedFS Volume
After=network.target
[Service]
Type=simple
User=seaweed
Group=seaweed
ExecStart=/usr/local/bin/weed volume -ip=192.168.0.11 -mserver="192.168.0.11:9333,192.168.0.12:9333,192.168.0.13:9333" -fileSizeLimitMB=16384 -concurrentUploadLimitMB=16384 -max=100 -minFreeSpace=10 -port=7070 -metricsPort=9325 -index=leveldb -dir="/mnt/hdd2/volume" -dataCenter=home -rack=rock -disk=hdd -publicUrl=192.168.0.11
WorkingDirectory=/usr/local/bin/
SyslogIdentifier=seaweedfs-volume
[Install]
WantedBy=multi-user.target
Filerサービス(クリックで展開)
[Unit]
Description=SeaweedFS Filer
After=network.target
[Service]
Type=simple
User=seaweed
Group=seaweed
ExecStart=/usr/local/bin/weed filer -ip=192.168.0.11 -master="192.168.0.11:9333,192.168.0.12:9333,192.168.0.13:9333" -peers="192.168.0.11:8888,192.168.0.12:8888,192.168.0.13:8888" -port=8888 -metricsPort=9326
WorkingDirectory=/usr/local/bin/
SyslogIdentifier=seaweedfs-filer
[Install]
WantedBy=multi-user.target
S3サービス(クリックで展開)
[Unit]
Description=SeaweedFS S3
After=network.target
[Service]
Type=simple
User=seaweed
Group=seaweed
ExecStart=/usr/local/bin/weed s3 -port=8333 -filer="192.168.0.11:8888,192.168.0.12:8888,192.168.0.13:8888" -config=s3.json -metricsPort=9327
WorkingDirectory=/usr/local/bin/
SyslogIdentifier=seaweedfs-s3
[Install]
WantedBy=multi-user.target
Mountサービス(クリックで展開)
[Unit]
Description=SeaweedFS Mount
After=network.target
[Service]
Type=simple
User=root
Group=root
ExecStart=/usr/local/bin/weed mount -filer="192.168.0.11:8888,192.168.0.12:8888,192.168.0.13:8888" -dir="/mnt/seaweedfs"
WorkingDirectory=/usr/local/bin/
SyslogIdentifier=seaweedfs-mount
[Install]
WantedBy=multi-user.target
Filerの設定ファイル(クリックで展開)
# A sample TOML config file for SeaweedFS filer store
# Used with "weed filer" or "weed server -filer"
# Put this file to one of the location, with descending priority
# ./filer.toml
# $HOME/.seaweedfs/filer.toml
# /etc/seaweedfs/filer.toml
####################################################
# Customizable filer server options
####################################################
[filer.options]
# with http DELETE, by default the filer would check whether a folder is empty.
# recursive_delete will delete all sub folders and files, similar to "rm -Rf"
recursive_delete = false
# directories under this folder will be automatically creating a separate bucket
buckets_folder = "/mnt/hdd2/buckets"
####################################################
# The following are filer store options
####################################################
[leveldb2]
# local on disk, mostly for simple single-machine setup, fairly scalable
# faster than previous leveldb, recommended.
enabled = true
# ファイラーメタデータの保存先(各自で変えてください)
dir = "/mnt/hdd2/filerldb2" # directory to store level db files
[leveldb3]
# similar to leveldb2.
# each bucket has its own meta store.
enabled = false
dir = "./filerldb3" # directory to store level db files
[rocksdb]
# local on disk, similar to leveldb
# since it is using a C wrapper, you need to install rocksdb and build it by yourself
enabled = false
dir = "./filerrdb" # directory to store rocksdb files
[sqlite]
# local on disk, similar to leveldb
enabled = false
dbFile = "./filer.db" # sqlite db file
[mysql] # or memsql, tidb
# CREATE TABLE IF NOT EXISTS filemeta (
# dirhash BIGINT COMMENT 'first 64 bits of MD5 hash value of directory field',
# name VARCHAR(1000) BINARY COMMENT 'directory or file name',
# directory TEXT COMMENT 'full path to parent directory',
# meta LONGBLOB,
# PRIMARY KEY (dirhash, name)
# ) DEFAULT CHARSET=utf8;
enabled = false
hostname = "localhost"
port = 3306
username = "root"
password = ""
database = "" # create or use an existing database
connection_max_idle = 2
connection_max_open = 100
connection_max_lifetime_seconds = 0
interpolateParams = false
# if insert/upsert failing, you can disable upsert or update query syntax to match your RDBMS syntax:
enableUpsert = true
upsertQuery = """INSERT INTO ` + "`%s`" + ` (dirhash,name,directory,meta) VALUES(?,?,?,?) ON DUPLICATE KEY UPDATE meta = VALUES(meta)"""
[mysql2] # or memsql, tidb
enabled = false
createTable = """
CREATE TABLE IF NOT EXISTS ` + "`%s`" + ` (
dirhash BIGINT,
name VARCHAR(1000) BINARY,
directory TEXT,
meta LONGBLOB,
PRIMARY KEY (dirhash, name)
) DEFAULT CHARSET=utf8;
"""
hostname = "localhost"
port = 3306
username = "root"
password = ""
database = "" # create or use an existing database
connection_max_idle = 2
connection_max_open = 100
connection_max_lifetime_seconds = 0
interpolateParams = false
# if insert/upsert failing, you can disable upsert or update query syntax to match your RDBMS syntax:
enableUpsert = true
upsertQuery = """INSERT INTO ` + "`%s`" + ` (dirhash,name,directory,meta) VALUES(?,?,?,?) ON DUPLICATE KEY UPDATE meta = VALUES(meta)"""
[postgres] # or cockroachdb, YugabyteDB
# CREATE TABLE IF NOT EXISTS filemeta (
# dirhash BIGINT,
# name VARCHAR(65535),
# directory VARCHAR(65535),
# meta bytea,
# PRIMARY KEY (dirhash, name)
# );
enabled = false
hostname = "localhost"
port = 5432
username = "postgres"
password = ""
database = "postgres" # create or use an existing database
schema = ""
sslmode = "disable"
connection_max_idle = 100
connection_max_open = 100
connection_max_lifetime_seconds = 0
# if insert/upsert failing, you can disable upsert or update query syntax to match your RDBMS syntax:
enableUpsert = true
upsertQuery = """INSERT INTO "%[1]s" (dirhash,name,directory,meta) VALUES($1,$2,$3,$4) ON CONFLICT (dirhash,name) DO UPDATE SET meta = EXCLUDED.meta WHERE "%[1]s".meta != EXCLUDED.meta"""
[postgres2]
enabled = false
createTable = """
CREATE TABLE IF NOT EXISTS "%s" (
dirhash BIGINT,
name VARCHAR(65535),
directory VARCHAR(65535),
meta bytea,
PRIMARY KEY (dirhash, name)
);
"""
hostname = "localhost"
port = 5432
username = "postgres"
password = ""
database = "postgres" # create or use an existing database
schema = ""
sslmode = "disable"
connection_max_idle = 100
connection_max_open = 100
connection_max_lifetime_seconds = 0
# if insert/upsert failing, you can disable upsert or update query syntax to match your RDBMS syntax:
enableUpsert = true
upsertQuery = """INSERT INTO "%[1]s" (dirhash,name,directory,meta) VALUES($1,$2,$3,$4) ON CONFLICT (dirhash,name) DO UPDATE SET meta = EXCLUDED.meta WHERE "%[1]s".meta != EXCLUDED.meta"""
[cassandra]
# CREATE TABLE filemeta (
# directory varchar,
# name varchar,
# meta blob,
# PRIMARY KEY (directory, name)
# ) WITH CLUSTERING ORDER BY (name ASC);
enabled = false
keyspace = "seaweedfs"
hosts = [
"localhost:9042",
]
username = ""
password = ""
# This changes the data layout. Only add new directories. Removing/Updating will cause data loss.
superLargeDirectories = []
# Name of the datacenter local to this filer, used as host selection fallback.
localDC = ""
[hbase]
enabled = false
zkquorum = ""
table = "seaweedfs"
[redis2]
enabled = false
address = "localhost:6379"
password = ""
database = 0
# This changes the data layout. Only add new directories. Removing/Updating will cause data loss.
superLargeDirectories = []
[redis_cluster2]
enabled = false
addresses = [
"localhost:30001",
"localhost:30002",
"localhost:30003",
"localhost:30004",
"localhost:30005",
"localhost:30006",
]
password = ""
# allows reads from slave servers or the master, but all writes still go to the master
readOnly = false
# automatically use the closest Redis server for reads
routeByLatency = false
# This changes the data layout. Only add new directories. Removing/Updating will cause data loss.
superLargeDirectories = []
[etcd]
enabled = false
servers = "localhost:2379"
timeout = "3s"
[mongodb]
enabled = false
uri = "mongodb://localhost:27017"
option_pool_size = 0
database = "seaweedfs"
[elastic7]
enabled = false
servers = [
"http://localhost1:9200",
"http://localhost2:9200",
"http://localhost3:9200",
]
username = ""
password = ""
sniff_enabled = false
healthcheck_enabled = false
# increase the value is recommend, be sure the value in Elastic is greater or equal here
index.max_result_window = 10000
##########################
##########################
# To add path-specific filer store:
#
# 1. Add a name following the store type separated by a dot ".". E.g., cassandra.tmp
# 2. Add a location configuraiton. E.g., location = "/tmp/"
# 3. Copy and customize all other configurations.
# Make sure they are not the same if using the same store type!
# 4. Set enabled to true
#
# The following is just using redis as an example
##########################
[redis2.tmp]
enabled = false
location = "/tmp/"
address = "localhost:6379"
password = ""
database = 1
S3サービスの設定ファイル(クリックで展開)
{
"identities": [
{
"name": "anonymous",
"actions": [
"Read"
]
},
{
"name": "admin_user",
"credentials": [
{
"accessKey": "some_access_key1",
"secretKey": "some_secret_key1"
}
],
"actions": [
"Admin",
"Read",
"List",
"Tagging",
"Write"
]
},
{
"name": "normal_user",
"credentials": [
{
"accessKey": "some_access_key3",
"secretKey": "some_secret_key3"
}
],
"actions": [
"Read",
"List",
"Tagging",
"Write"
]
}
]
}
サービスの有効化/起動(クリックで展開)
sudo systemctl daemon-reload
sudo systemctl enable seaweed-master
sudo systemctl enable seaweed-volume
sudo systemctl enable seaweed-filer
sudo systemctl enable seaweed-s3
sudo systemctl enable seaweed-mount
sudo systemctl start seaweed-master
sudo systemctl start seaweed-volume
sudo systemctl start seaweed-filer
sudo systemctl start seaweed-s3
sudo systemctl start seaweed-mount
方法2 サービスを分けない場合(tmpに保存されます)
[Unit]
Description=SeaweedFS
After=network.target
[Service]
Type=simple
User=root
Group=root
ExecStart=/usr/local/bin/weed server -dataCenter=home -rack=rock -master -master.dir=/mnt/hdd2/master -master.peers="192.168.0.11:9333,192.168.0.12:9333,192.168.0.13:9333" -master.volumeSizeLimitMB=2048 -master.defaultReplication=020 -master.port=9333 -volume -volume.dir.idx=/mnt/hdd2/volume -volume.port=8080 -volume.max=100 -volume.minFreeSpace=10 -volume.fileSizeLimitMB=16384 -volume.concurrentUploadLimitMB=16384 -volume.disk=hdd -volume.publicUrl=192.168.0.11 -filer -filer.peers="192.168.0.11:8888,192.168.0.12:8888,192.168.0.13:8888" -filer.port=8888 -s3 -s3.port=8333 -metricsPort=9326
WorkingDirectory=/usr/local/bin/
SyslogIdentifier=seaweedfs-master
[Install]
WantedBy=multi-user.target
完走した感想
なんとかDockerSwarmで動かせないか努力したんですが結局どうにもならず、動かせるまで、2週間ぐらいかかりました... CephやGlusterFSと比べると情報が全くなかったので今後なにか起こったときが怖いです。導入は簡単だったかというと、簡単じゃなかったし、これもこれでうーんという感じでした。(そもそも今からDockerSwarmを使おうとしたのがよろしくなかった感じがします)
参考
chrislusf/seaweedfs - Github
Setup SeaweedFS Distributed Object Storage Cluster on Ubuntu 20.04
weed help <サービス名> で出てくるヘルプ