关于 RustFS 在过往的博客中已经有过介绍:
根据 RustFS 官网介绍,RustFS 有三种安装模式:
- 单机单盘(SNSD)
- 单机多盘(SNMD)
- 多机多盘(MNMD)
其中多机多盘属于集群式安装,也是企业使用最多的模式。多机多盘意味着要在每个服务器上都安装 RustFS 实例,本文探索用 ansible + docker compose 的方式在四台服务器上部署 MNMD 架构。
前提
- 五台服务器(其中一台用作 ansible 的控制节点,其余四台作为被管理节点,也就是要安装 RustFS 的节点)
- 在控制节点上安装好 ansible
安装流程
配置 ansible
现在 ansible 控制节点上确保 ansible 安装成功:
1
2
3
4
5
6
7
8
9
10
| ansible --version
ansible [core 2.18.10]
config file = /etc/ansible/ansible.cfg
configured module search path = ['/root/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
ansible python module location = /usr/lib/python3/dist-packages/ansible
ansible collection location = /root/.ansible/collections:/usr/share/ansible/collections
executable location = /usr/bin/ansible
python version = 3.12.3 (main, Aug 14 2025, 17:47:21) [GCC 13.3.0] (/usr/bin/python3)
jinja version = 3.1.6
libyaml = True
|
在控制节点上生成 ssh key 并 copy 到四台目标服务器:
1
2
3
4
5
| # 生成 ssh key
ssh-keygen -t rsa -C "your.email.address"
# 拷贝 ssh key 到目标服务器(执行四次)
ssh-copy-id -i ~/.ssh/id_rsa_rustfs.pub root@your.server.ip
|
在控制节点上配置 /etc/ansible/hosts
文件,将四台服务器配置为 rustfs 群组:
1
2
3
4
5
| [rustfs]
8.130.164.70
8.130.168.227
39.101.76.181
8.130.119.35
|
后续 rustfs
群组名称会用在 ansible playbook 中。
一切配置妥当后,用 ansible rustfs -m ping
命令进行测试:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
| 8.130.119.35 | SUCCESS => {
"changed": false,
"ping": "pong"
}
8.130.164.70 | SUCCESS => {
"changed": false,
"ping": "pong"
}
39.101.76.181 | SUCCESS => {
"changed": false,
"ping": "pong"
}
8.130.168.227 | SUCCESS => {
"changed": false,
"ping": "pong"
}
|
看到上述结果后,可认为 ansible 和服务器配置完成,可进行 RustFS 的安装了。
NOTE:执行上述命令需要服务器开启 ICMP 协议。
编写 ansible playbook
ansible playbook 的撰写完全围绕 RustFS 的安装进行。RustFS 官方提供 docker compose 安装方式,docker-compose.yml
文件内容如下:
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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
| services:
rustfs:
image: rustfs/rustfs:latest
container_name: rustfs
hostname: rustfs
network_mode: host
environment:
# Use service names and correct disk indexing (1..4 to match mounted paths)
- RUSTFS_VOLUMES=http://rustfs-node{1...4}:9000/data/rustfs{1...4}
- RUSTFS_ADDRESS=0.0.0.0:9000
- RUSTFS_CONSOLE_ENABLE=true
- RUSTFS_CONSOLE_ADDRESS=0.0.0.0:9001
- RUSTFS_EXTERNAL_ADDRESS=0.0.0.0:9000 # Same as internal since no port mapping
- RUSTFS_ACCESS_KEY=rustfsadmin
- RUSTFS_SECRET_KEY=rustfsadmin
- RUSTFS_CMD=rustfs
command: ["sh", "-c", "apk update && apk add curl && sleep 3 && rustfs"]
healthcheck:
test:
[
"CMD-SHELL",
"curl -f http://localhost:9000/health && curl -f http://localhost:9001/health || exit 1"
]
interval: 10s
timeout: 5s
retries: 3
start_period: 30s
ports:
- "9000:9000" # API endpoint
- "9001:9001" # Console
volumes:
- rustfs-data1:/data/rustfs1
- rustfs-data2:/data/rustfs2
- rustfs-data3:/data/rustfs3
- rustfs-data4:/data/rustfs4
extra_hosts:
- "rustfs-node1:172.20.92.202"
- "rustfs-node2:172.20.92.201"
- "rustfs-node3:172.20.92.200"
- "rustfs-node4:172.20.92.199"
volumes:
rustfs-data1:
rustfs-data2:
rustfs-data3:
rustfs-data4:
|
核心原理就是将上述内容写入 docker-compose.yml
文件并拷贝到目标服务器上,然后执行 docker compose up -d
命令。因此,playbook 的整体流程包括:
- 安装 docker 环境
- 创建存放
docker-compose.yml
文件的目录 - 生成
docker-compose.yml
文件 - 执行
docker compose up -d
命令安装 rustfs 集群 - 确认安装结果
- (optional)执行卸载命令
docker compose down
下面看使用到的 ansible 模块及具体实践。
安装 docker 环境
本次实践所用的服务器是 Ubuntu OS,可以直接使用 shell 模块来安装 docker 环境:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
| - name: Install docker
shell: |
apt-get remove -y docker docker.io containerd runc || true
apt-get update -y
apt-get install -y ca-certificates curl gnupg lsb-release
install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://mirrors.aliyun.com/docker-ce/linux/ubuntu/gpg | gpg --dearmor --yes -o /etc/apt/keyrings/docker.gpg
chmod a+r /etc/apt/keyrings/docker.gpg
echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://mirrors.aliyun.com/docker-ce/linux/ubuntu \
$(lsb_release -cs) stable" | tee /etc/apt/sources.list.d/docker.list > /dev/null
apt-get update -y
apt-get install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin
become: yes
register: docker_installation_result
changed_when: false
- name: Installation check
debug:
var: docker_installation_result.stdout
|
NOTE:使用了 ansible 的 register 和 debug 对安装结果进行输出检查。
创建目录
创建一个目录用来存放后面生成的 docker-compose.yml
文件,直接使用 ansible 的 file
的模块指定路径即可:
1
2
3
4
5
| - name: Create docker compose dir
file:
path: "{{ docker_compose }}"
state: directory
mode: '0755'
|
NOTE:{{ docker_compose }} 是 ansible 中的变量引用,该变量定义在 playbook 的顶部:
1
2
3
4
5
6
7
8
| ---
- name: Prepare for RustFS installation
hosts: rustfs
become: yes
vars:
ansible_python_interpreter: /usr/bin/python3
install_script_url: "https://rustfs.com/install_rustfs.sh"
docker_compose: "/home/xiaomage/rustfs/docker-compose"
|
生成 docker-compose.yml
文件
使用 ansible 的 copy
模块生成 docker-compose.yml
文件并拷贝至目标服务器的指定目录下:
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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
| - name: Prepare docker compose file
copy:
content: |
services:
rustfs:
image: rustfs/rustfs:latest
container_name: rustfs
hostname: rustfs
network_mode: host
environment:
# Use service names and correct disk indexing (1..4 to match mounted paths)
- RUSTFS_VOLUMES=http://rustfs-node{1...4}:9000/data/rustfs{1...4}
- RUSTFS_ADDRESS=0.0.0.0:9000
- RUSTFS_CONSOLE_ENABLE=true
- RUSTFS_CONSOLE_ADDRESS=0.0.0.0:9001
- RUSTFS_EXTERNAL_ADDRESS=0.0.0.0:9000 # Same as internal since no port mapping
- RUSTFS_ACCESS_KEY=rustfsadmin
- RUSTFS_SECRET_KEY=rustfsadmin
- RUSTFS_CMD=rustfs
command: ["sh", "-c", "apk update && apk add curl && sleep 3 && rustfs"]
healthcheck:
test:
[
"CMD-SHELL",
"curl -f http://localhost:9000/health && curl -f http://localhost:9001/health || exit 1"
]
interval: 10s
timeout: 5s
retries: 3
start_period: 30s
ports:
- "9000:9000" # API endpoint
- "9001:9001" # Console
volumes:
- rustfs-data1:/data/rustfs1
- rustfs-data2:/data/rustfs2
- rustfs-data3:/data/rustfs3
- rustfs-data4:/data/rustfs4
extra_hosts:
- "rustfs-node1:172.20.92.202"
- "rustfs-node2:172.20.92.201"
- "rustfs-node3:172.20.92.200"
- "rustfs-node4:172.20.92.199"
volumes:
rustfs-data1:
rustfs-data2:
rustfs-data3:
rustfs-data4:
dest: "{{ docker_compose }}/docker-compose.yml"
mode: '0644'
|
dest
参数指定了 docker-compose.yml
文件存放的路径。
NOTE:由于是多机多盘(MNMD)安装模式,因此 RUSTFS RUSTFS_VOLUME
环境变量的值为 http://rustfs-node{1...4}:9000/data/rustfs{1...4}
,因此需要将 rustfs-node{1...4}
和服务器的 IP 地址映射起来,这部分需要修改容器的 /etc/hosts
文件,在 docker compose 环境下直接使用 extra_hosts
即可。需要注意的是,这部分一定要用服务器的内网地址。
执行安装
执行 docker compose -f docker-compose.yml up -d
命令即可安装,直接使用 command
模块:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
| - name: Install rustfs using docker compose
tags: rustfs_install
command: docker compose -f "{{ docker_compose}}/docker-compose.yml" up -d
args:
chdir: "{{ docker_compose }}"
- name: Get docker compose output
command: docker compose ps
args:
chdir: "{{ docker_compose }}"
register: docker_compose_output
- name: Check the docker compose installation output
debug:
msg: "{{ docker_compose_output.stdout }}"
|
NOTE:由于将 RustFS 的安装和卸载写在了同一个 playbook 中,因此使用了 ansible 的 tags
属性来标记不同的 task。其中用 rustfs_install
标记 RustFS 安装,rustfs_uninstall
标记卸载。因此,执行的时候使用 tags
来指定执行的 task,使用 --skip-tags
来指定跳过特定的 task。
(可选)卸载 RustFS
执行 docker compose -f docker-compose.yml down
命令卸载安装好的集群:
1
2
3
4
5
| - name: Uninstall rustfs using docker compose
tags: rustfs_uninstall
command: docker compose -f "{{ docker_compose}}/docker-compose.yml" down
args:
chdir: "{{ docker_compose }}"
|
开始安装
将上述内容存放到一个 YAML 文件中,存放在 ansible 控制节点的目录下,比如名为 install.yml
,执行如下命令:
1
| ansible-playbook --skip-tags rustfs_uninstall install.yml
|
输出结果如下:
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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
|
PLAY [Prepare for RustFS installation] ****************************************************************************************************************************************************************************************************
TASK [Gathering Facts] ********************************************************************************************************************************************************************************************************************
ok: [8.130.168.227]
ok: [8.130.119.35]
ok: [8.130.164.70]
ok: [39.101.76.181]
TASK [Uninstall rustfs using docker compose] **********************************************************************************************************************************************************************************************
changed: [39.101.76.181]
changed: [8.130.164.70]
changed: [8.130.119.35]
changed: [8.130.168.227]
PLAY RECAP ********************************************************************************************************************************************************************************************************************************
39.101.76.181 : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
8.130.119.35 : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
8.130.164.70 : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
8.130.168.227 : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
root@xiaomage-hs:/home/xiaomage/ansible# ansible-playbook --skip-tags rustfs_uninstall docker.yml
PLAY [Prepare for RustFS installation] ****************************************************************************************************************************************************************************************************
TASK [Gathering Facts] ********************************************************************************************************************************************************************************************************************
ok: [8.130.119.35]
ok: [8.130.164.70]
ok: [39.101.76.181]
ok: [8.130.168.227]
TASK [Install docker] *********************************************************************************************************************************************************************************************************************
ok: [8.130.164.70]
ok: [8.130.119.35]
ok: [8.130.168.227]
ok: [39.101.76.181]
TASK [Installation check] *****************************************************************************************************************************************************************************************************************
......TLDR......
TASK [Create docker compose dir] **********************************************************************************************************************************************************************************************************
ok: [8.130.164.70]
ok: [8.130.168.227]
ok: [39.101.76.181]
ok: [8.130.119.35]
TASK [Prepare docker compose file] ********************************************************************************************************************************************************************************************************
ok: [8.130.168.227]
ok: [8.130.119.35]
ok: [8.130.164.70]
ok: [39.101.76.181]
TASK [Install rustfs using docker compose] ************************************************************************************************************************************************************************************************
changed: [8.130.164.70]
changed: [39.101.76.181]
changed: [8.130.119.35]
changed: [8.130.168.227]
TASK [Get docker compose output] **********************************************************************************************************************************************************************************************************
changed: [8.130.164.70]
changed: [8.130.168.227]
changed: [8.130.119.35]
changed: [39.101.76.181]
TASK [Check the docker compose installation output] ***************************************************************************************************************************************************************************************
ok: [8.130.164.70] => {
"msg": "NAME IMAGE COMMAND SERVICE CREATED STATUS PORTS\nrustfs rustfs/rustfs:latest \"/entrypoint.sh sh -…\" rustfs 3 seconds ago Up 2 seconds (health: starting) "
}
ok: [8.130.168.227] => {
"msg": "NAME IMAGE COMMAND SERVICE CREATED STATUS PORTS\nrustfs rustfs/rustfs:latest \"/entrypoint.sh sh -…\" rustfs 2 seconds ago Up 1 second (health: starting) "
}
ok: [39.101.76.181] => {
"msg": "NAME IMAGE COMMAND SERVICE CREATED STATUS PORTS\nrustfs rustfs/rustfs:latest \"/entrypoint.sh sh -…\" rustfs 3 seconds ago Up 3 seconds (health: starting) "
}
ok: [8.130.119.35] => {
"msg": "NAME IMAGE COMMAND SERVICE CREATED STATUS PORTS\nrustfs rustfs/rustfs:latest \"/entrypoint.sh sh -…\" rustfs 3 seconds ago Up 2 seconds (health: starting) "
}
PLAY RECAP ********************************************************************************************************************************************************************************************************************************
39.101.76.181 : ok=8 changed=2 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
8.130.119.35 : ok=8 changed=2 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
8.130.164.70 : ok=8 changed=2 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
8.130.168.227 : ok=8 changed=2 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
|
在目标服务器上可以查看安装结果:
1
2
3
| docker compose ps
NAME IMAGE COMMAND SERVICE CREATED STATUS PORTS
rustfs rustfs/rustfs:latest "/entrypoint.sh sh -…" rustfs 2 minutes ago Up 2 minutes (healthy)
|
使用任意 RustFS 节点的 ip + 9000 端口,并用默认用户名密码 rustfsadmin
访问实例,在 性能 一栏中看到所有节点的信息:

可以看到有四个节点在线,每个节点 4 个 disk。接下来就可以使用该集群了。
卸载 RustFS
由于将 RustFS 的安装和卸载写到了同一个 playbook 中,并且使用了 tags
来标记。执行如下命令即可完成 RustFS 集群的卸载:
1
| ansible-playbook --tags rustfs_uninstall install.yml
|
返回结果如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
| ansible-playbook --tags rustfs_uninstall docker.yml
PLAY [Prepare for RustFS installation] ****************************************************************************************************************************************************************************************************
TASK [Gathering Facts] ********************************************************************************************************************************************************************************************************************
ok: [8.130.164.70]
ok: [8.130.168.227]
ok: [39.101.76.181]
ok: [8.130.119.35]
TASK [Uninstall rustfs using docker compose] **********************************************************************************************************************************************************************************************
changed: [8.130.168.227]
changed: [8.130.119.35]
changed: [39.101.76.181]
changed: [8.130.164.70]
PLAY RECAP ********************************************************************************************************************************************************************************************************************************
39.101.76.181 : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
8.130.119.35 : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
8.130.164.70 : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
8.130.168.227 : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
|
可在目标服务器上通过 docker ps
或 docker compose ps
查看是否卸载成功。