博客 / 詳情

返回

使用 ansible + docker compose 部署 RustFS 多機多盤集羣

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 訪問實例,在 性能 一欄中看到所有節點的信息:
rustfs-docker-compose-mnmd.png

可以看到有四個節點在線,每個節點 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 psdocker compose ps 查看是否卸載成功。

user avatar jintvues 頭像 tengxunyuncosxiaozhushou 頭像
2 位用戶收藏了這個故事!

發佈 評論

Some HTML is okay.