JuiceFS 多主机间同步账户

JuiceFS 支持 POSIX 兼容的 ACL,以目录或文件的粒度管理权限。该行为与本地文件系统相同。

为了让用户获得直观一致的权限管理体验(例如,用户 A 在主机 X 中访问的文件,在主机 Y 中也应该可以用相同的用户身份访问),想要访问 JuiceFS 存储的同一个用户,应该在所有主机上具有相同的 UID 和 GID。

在这里,我们提供了一个简单的 Ansible playbook 来演示如何确保一个帐户在多个主机上具有相同的 UID 和 GID。

注意

如果你是在 Hadoop 环境使用 JuiceFS,除了在多主机间同步账户以外,也可以指定一个全局的用户列表和所属用户组文件,具体请参见这里

安装 Ansible

选择一个主机作为 控制节点,它可以使用 sshroot 或其他在 sudo 用户组的身份,访问所有。在此主机上安装 Ansible。阅读 安装 Ansible 了解更多安装细节。

确保所有主机上的帐户相同

创建一个空目录 account-sync ,将下面的内容保存在该目录下的 play.yaml 中。

  1. ---
  2. - hosts: all
  3. tasks:
  4. - name: "Ensure group {{ group }} with gid {{ gid }} exists"
  5. group:
  6. name: "{{ group }}"
  7. gid: "{{ gid }}"
  8. state: present
  9. - name: "Ensure user {{ user }} with uid {{ uid }} exists"
  10. user:
  11. name: "{{ user }}"
  12. uid: "{{ uid }}"
  13. group: "{{ gid }}"
  14. state: present

在该目录下创建一个名为 hosts 的文件,将所有需要创建账号的主机的 IP 地址放置在该文件中,每行一个 IP。

在这里,我们确保在 2 台主机上使用 UID 1200 的帐户 alice 和 GID 500 的 staff 组:

  1. ~/account-sync$ cat hosts
  2. 172.16.255.163
  3. 172.16.255.180
  4. ~/account-sync$ ansible-playbook -i hosts -u root --ssh-extra-args "-o StrictHostKeyChecking=no" \
  5. --extra-vars "group=staff gid=500 user=alice uid=1200" play.yaml
  6. PLAY [all] ************************************************************************************************
  7. TASK [Gathering Facts] ************************************************************************************
  8. ok: [172.16.255.180]
  9. ok: [172.16.255.163]
  10. TASK [Ensure group staff with gid 500 exists] *************************************************************
  11. ok: [172.16.255.163]
  12. ok: [172.16.255.180]
  13. TASK [Ensure user alice with uid 1200 exists] *************************************************************
  14. changed: [172.16.255.180]
  15. changed: [172.16.255.163]
  16. PLAY RECAP ************************************************************************************************
  17. 172.16.255.163 : ok=3 changed=1 unreachable=0 failed=0
  18. 172.16.255.180 : ok=3 changed=1 unreachable=0 failed=0

现在已经在这 2 台主机上创建了新帐户 alice:staff

如果指定的 UID 或 GID 已分配给某些主机上的另一个用户或组,则创建将失败。

  1. ~/account-sync$ ansible-playbook -i hosts -u root --ssh-extra-args "-o StrictHostKeyChecking=no" \
  2. --extra-vars "group=ubuntu gid=1000 user=ubuntu uid=1000" play.yaml
  3. PLAY [all] ************************************************************************************************
  4. TASK [Gathering Facts] ************************************************************************************
  5. ok: [172.16.255.180]
  6. ok: [172.16.255.163]
  7. TASK [Ensure group ubuntu with gid 1000 exists] ***********************************************************
  8. ok: [172.16.255.163]
  9. fatal: [172.16.255.180]: FAILED! => {"changed": false, "msg": "groupmod: GID '1000' already exists\n", "name": "ubuntu"}
  10. TASK [Ensure user ubuntu with uid 1000 exists] ************************************************************
  11. ok: [172.16.255.163]
  12. to retry, use: --limit @/home/ubuntu/account-sync/play.retry
  13. PLAY RECAP ************************************************************************************************
  14. 172.16.255.163 : ok=3 changed=0 unreachable=0 failed=0
  15. 172.16.255.180 : ok=1 changed=0 unreachable=0 failed=1

在上面的示例中,组 ID 1000 已分配给主机 172.16.255.180 上的另一个组,我们应该 更改 GID删除主机 172.16.255.180 上 GID 为 1000 的组,然后再次运行 playbook。

注意

如果用户帐户已经存在于主机上,并且我们将其更改为另一个 UID 或 GID 值,则用户可能会失去对他们以前拥有的文件和目录的权限。例如:

  1. $ ls -l /tmp/hello.txt
  2. -rw-r--r-- 1 alice staff 6 Apr 26 21:43 /tmp/hello.txt
  3. $ id alice
  4. uid=1200(alice) gid=500(staff) groups=500(staff)

我们将 alice 的 UID 从 1200 改为 1201

  1. ~/account-sync$ ansible-playbook -i hosts -u root --ssh-extra-args "-o StrictHostKeyChecking=no" \
  2. --extra-vars "group=staff gid=500 user=alice uid=1201" play.yaml

现在我们没有权限删除这个文件,因为它的所有者不是 alice:

  1. $ ls -l /tmp/hello.txt
  2. -rw-r--r-- 1 1200 staff 6 Apr 26 21:43 /tmp/hello.txt
  3. $ rm /tmp/hello.txt
  4. rm: remove write-protected regular file '/tmp/hello.txt'? y
  5. rm: cannot remove '/tmp/hello.txt': Operation not permitted