RustFS 有三種安裝模式:單機單盤(SNSD)、單機多盤(SNMD)以及多機多盤(MNMD)。其中多機多盤屬於集羣式安裝,也是企業使用最多的模式。多機多盤意味着要在每個服務器上都安裝 RustFS 實例,本文探索用 ansible + docker compose 的方式在四台服務器上部署 MNMD 架構。
前提
- 五台服務器(其中一台用作 ansible 的控制節點,其餘四台作為被管理節點,也就是要安裝 RustFS 的節點)
- 在控制節點上安裝好 ansible
安裝流程
配置 ansible
現在 ansible 控制節點上確保 ansible 安裝成功:
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 到四台目標服務器:
# 生成 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 羣組:
[rustfs]
8.130.164.70
8.130.168.227
39.101.76.181
8.130.119.35
後續 rustfs 羣組名稱會用在 ansible playbook 中。
一切配置妥當後,用 ansible rustfs -m ping 命令進行測試:
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 文件內容如下:
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 環境:
- 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 的模塊指定路徑即可:
- name: Create docker compose dir
file:
path: "{{ docker_compose }}"
state: directory
mode: '0755'
NOTE:{{ docker_compose }} 是 ansible 中的變量引用,該變量定義在 playbook 的頂部:
---
- 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 文件並拷貝至目標服務器的指定目錄下:
- 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 模塊:
- 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 命令卸載安裝好的集羣:
- 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,執行如下命令:
ansible-playbook --skip-tags rustfs_uninstall install.yml
輸出結果如下:
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
在目標服務器上可以查看安裝結果:
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 集羣的卸載:
ansible-playbook --tags rustfs_uninstall install.yml
返回結果如下:
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 查看是否卸載成功。