Вопрос или проблема
rsync
поддерживает --chown
, но вам нужно что-то вроде podman unshare
, чтобы правильно работать с subuid
. Как я могу их объединить (на удаленном хосте) ?
Я разобрался в этом, и так как я не нашел ничего подобного при поиске, решил сам ответить на этот вопрос для будущих искателей.
Суммирую:
rsync --rsync-path="podman unshare rsync" -zav --delete-during --chown 33:33 /src remote-server:/dst
Объяснение: --rsync-path
, изначально предназначенный для указания местоположения исполняемого файла rsync
, может выполнять произвольные команды (и часто используется для выполнения sudo
на удаленном сервере). Запуская rsync
‘внутри’ podman unshare
, предоставленный аргумент для --chown
интерпретируется в сопоставленном пространстве имен пользователя, так что вместо установки файлов с идентификаторами хоста 33:33
, это происходит в сопоставленном пространстве имен, в результате чего файлы принадлежат пользователю с высоким идентификатором на хосте (1345216:1345216
, например, для меня) и указанному пользователю 33:33
внутри контейнера:
$ sudo ls -alsh /mnt/data
total 648K
4.0K drwxrwx---. 17 1345216 1345216 4.0K Mar 10 16:12 .
4.0K drwxrwx---. 7 root root 4.0K Mar 10 17:19 ..
16K drwxrwx---. 456 1345216 1345216 12K Mar 11 08:35 stuff
$ podman run --rm -it -v /mnt/data:/data:ro alpine ls -alsh /data
total 644K
4.0K drwxrwx--- 17 33 33 4.0K Mar 10 15:12 .
0 dr-xr-xr-x 1 root root 40 Mar 12 14:14 ..
16.0K drwxrwx--- 456 33 33 12.0K Mar 11 07:35 stuff
Кроме того, у меня была дополнительная трудность: пользователь, которому должны принадлежать файлы, был не моим пользователем, а другим, которому не было разрешено удаленное подключение, поэтому вот команда выше с дополнительными командами, необходимыми для ‘передачи’ файлов пользователю внутри пространства имен другого пользователя:
rsync --rsync-path="cd /tmp && sudo --user=target-user podman unshare rsync" -zav --delete-during --chown 33:33 /src remote-server:/dst
Дополнительные параметры здесь сводятся к добавлению sudo --user=target-user ...
, но так как rsync
запускается в домашней директории пользователя, инициирующего подключение, дополнительно нужен cd
, чтобы избежать ошибки rsync
, связанной с невозможностью чтения .
после sudo
.
Надеюсь, кому-то это будет полезно в будущем.
Ответ или решение
Использование rsync
для установки владельца файлов на удалённом сервере на определённый userid
внутри контейнера Podman или Docker с режимом без root (rootless) требует понимания как работы с user namespace, так и надлежащей интеграции с инструментами контейнеризации. Давайте подробнее разберём, как это можно реализовать, учитывая контекст предоставленной задачи.
Теория
Инструмент rsync
является мощным средством для синхронизации файлов между различными системами. Одной из его ключевых функций является способность изменять владельца файлов при копировании, что достигается с помощью флага --chown
. Обычно, назначение владельца файлов требует прав суперпользователя, однако в контексте контейнеров с rootless режимом, это делается в рамках изолированного пространства (namespace) пользователями.
Rootless режим в Podman или Docker позволяет запускать контейнеры без привилегий суперпользователя, используя подмену идентификаторов пользователей (User Namespace Remapping). Это означает, что внутри контейнера стандартный пользователь, например с UID 0 (который обыкновенно ассоциируется с root), может быть сопоставлен с обычным пользователем с высоким UID на хосте. Это сопоставление осуществляется через суб-идентификаторы (subuid, subgid).
Пример
Допустим, вы хотите синхронизировать файлы из директории /src
на локальном сервере в директорию /dst
на удалённом сервере, и хотите, чтобы файлы имели определённый uid
и gid
внутри контейнера, которые в маппинге упоминаются как 33:33
. Используя podman unshare
, можно выполнить rsync
в контексте user namespace, где предоставленные аргументы --chown
будут интерпретированы правильно.
Команда, реализующая эту задачу, выглядит следующим образом:
rsync --rsync-path="podman unshare rsync" -zav --delete-during --chown 33:33 /src remote-server:/dst
Применение
-
–rsync-path: Этот параметр
rsync
позволяет указать путь к его исполняемому файлу на удалённом сервере. Однако его можно использовать и для выполнения более сложных сценариев, включая запуск команд в контексте специфических пространств пользователей. Когда передаётсяpodman unshare rsync
, мы принуждаем запускrsync
в контексте User Namespace, управляемогоPodman
. -
–chown: Параметр
--chown 33:33
указываетrsync
изменить владельца и группу синхронизируемых файлов на указанные UID и GID внутри user namespace. Внешне на уровне хостов они будут отображаться как высокие идентификаторы (например,1345216:1345216
), но внутри контейнера эти идентификаторы соответствуют ожидаемым33:33
. -
sudo –user: Если возникает необходимость выполнять
rsync
от имени другого пользователя, который не имеет доступа к удалённому серверу напрямую, можно использоватьsudo
для изменения пользователя в команде:
rsync --rsync-path="cd /tmp && sudo --user=target-user podman unshare rsync" -zav --delete-during --chown 33:33 /src remote-server:/dst
Здесь важно отметить использование cd /tmp
, чтобы избежать ошибок доступа, поскольку по умолчанию rsync
стартует в домашней директории пользователя.
Заключение
Этот сценарий подчёркивает важность учёта всех деталей при работе с контейнеризацией и синхронизацией данных. В мире DevOps и контейнеризации знание, как правильно сопоставлять и управлять пользовательскими пространствами с помощью инструментов вроде Podman и Docker, может значимо повысить эффективность работы и безопасность окружающей инфраструктуры. Прямое взаимодействие с rootless контейнерами через подобные механизмы не только способствует безопасности, убирая необходимость в superuser прав, но также добавляет гибкости в управлении распределёнными приложениями и их зависимостями.