This is a stable feature in Kubernetes, and has been since version v1.36. It was first available in the v1.28 release. You can no longer disable or opt out of this feature or behavior (it is locked); if you explicitly set a value for the associated feature gate UserNamespacesSupport, Kubernetes ignores it but does not report any error.
Ця сторінка пояснює, як використовуються простори імен користувачів у Podʼах Kubernetes. Простір імен користувачів ізолює користувача, який працює всередині контейнера, від користувача на хості.
Процес, який працює як root у контейнері, може працювати на хості як інший користувач (не root); іншими словами, процес має повні привілеї для операцій всередині простору імен користувачів, але не має привілеїв для операцій за його межами.
Ви можете використовувати цю функцію, щоб зменшити шкоду, яку скомпрометований контейнер може заподіяти хосту або іншим Podʼам на тому самому вузлі. Є кілька вразливостей безпеки, які оцінено як ВИСОКІ або КРИТИЧНІ, і які неможливо було використати, коли простори імен користувачів активні. Очікується, що простори імен користувачів також помʼякшуватимуть деякі майбутні вразливості.
Це функція, доступна лише для Linux, і потребує підтримки в Linux для монтування idmap на використовуваних файлових системах. Це означає:
/var/lib/kubelet/pods/, або власна тека, яку ви налаштовуєте для цього, повинна підтримувати монтування idmap.На практиці це означає, що вам потрібне ядро Linux принаймні версії 6.3, оскільки tmpfs почав підтримувати монтування idmap у цій версії. Це зазвичай потрібно, оскільки кілька функцій Kubernetes використовують tmpfs (токен ServiceAccount, який монтується стандартно, використовує tmpfs, Secrets також використовують tmpfs тощо).
Деякі популярні файлові системи, які підтримують монтування idmap в Linux 6.3, — це: btrfs, ext4, xfs, fat, tmpfs, overlayfs.
Крім того, середовище виконання контейнерів та його базове середовище виконання OCI повинні підтримувати простори імен користувачів. Підтримку надають такі середовища виконання OCI:
Для використання просторів імен користувачів з Kubernetes також потрібне середовище виконання контейнерів CRI, щоб використовувати цю функцію з Podʼами Kubernetes:
Стан підтримки просторів імен користувачів в cri-dockerd відстежується у тікеті на GitHub.
Простори імен користувачів — це функція Linux, яка дозволяє зіставляти користувачів у контейнері з іншими користувачами на хості. Крім того, можливості, надані Podʼу в просторі імен користувачів, чинні лише в цьому просторі імен і недійсні поза ним.
Pod може увімкнути використання просторів імен користувачів, встановивши поле pod.spec.hostUsers в false.
Kubelet вибере UID/GID хоста, на які зіставляється Pod, і зробить це так, щоб жодні два Podʼи на одному вузлі не використовували однакове зіставлення.
Поля runAsUser, runAsGroup, fsGroup тощо в pod.spec завжди посилаються на користувача всередині контейнера. Ці користувачі використовуватимуться для монтування томів (вказаних у pod.spec.volumes), і тому UID/GID хоста не матимуть жодного впливу на запис/читання з томів, які може монтувати Pod. Іншими словами, inode, створені/зчитані у томах, змонтованих Podʼом, будуть такими самими, як якби Pod не використовував простори імен користувачів.
Таким чином, Pod може легко вмикати та вимикати простори імен користувачів (не впливаючи на права власності на файли томів), а також надавати спільний доступ до томів з Podʼами без просторів імен користувачів, просто вказавши відповідних користувачів всередині контейнера (RunAsUser, RunAsGroup, fsGroup тощо). Це стосується будь-якого тому, який може бути змонтовано в Pod, включно з hostPath (якщо Podʼу дозволено монтувати томи hostPath).
Стандартно дійсні UID/GID, коли цю функцію активовано, лежать у діапазоні 0-65535. Це стосується файлів та процесів (runAsUser, runAsGroup тощо).
Файли з UID/GID за межами цього діапазону вважатимуться такими, що належать до overflow ID, зазвичай 65534 (налаштовано в /proc/sys/kernel/overflowuid та /proc/sys/kernel/overflowgid). Однак змінити ці файли неможливо, навіть якщо працювати як користувач/група 65534.
Якщо діапазон 0-65535 розширено за допомогою налаштування, вищезазначені обмеження застосовуються до розширеного діапазону.
Більшість застосунків, які потребують запуску з правами root, але не мають доступу до інших просторів імен хоста чи ресурсів, повинні продовжувати працювати без змін, якщо простори імен користувачів активовано.
Кілька середовищ виконання контейнерів із їхньою типовою конфігурацією (таких як Docker Engine, containerd, CRI-O) використовують простори імен Linux для ізоляції. Існують інші технології, які також можна використовувати з цими середовищами (наприклад, Kata Containers використовує віртуальні машини замість просторів імен Linux). Ця сторінка стосується середовищ виконання контейнерів, які використовують простори імен Linux для ізоляції.
Під час створення Podʼа стандартно використовується кілька нових просторів імен для ізоляції: мережевий простір імен для ізоляції мережі контейнера, простір імен PID для ізоляції перегляду процесів тощо. Якщо використовується простір імен користувачів, це ізолює користувачів у контейнері від користувачів на вузлі.
Це означає, що контейнери можуть працювати як root і зіставлятися з користувачем, який не є root, на хості. Всередині контейнера процес буде вважати себе root (і, отже, інструменти типу apt, dnf тощо працюватимуть нормально), тоді як насправді процес не має привілеїв на хості. Ви можете перевірити це, наприклад, дізнавшись, від імені якого користувача працює процес контейнера, виконавши ps aux на хості. Користувач, якого показує ps, не той самий, що і користувач, якого ви бачите, якщо ви виконаєте команду id всередині контейнера.
Ця абстракція обмежує те, що може трапитися, наприклад, якщо контейнеру вдасться втекти на хост. Оскільки контейнер працює як непривілейований користувач на хості, обмежено те, що він може зробити на хості.
Крім того, оскільки користувачі в кожному Podʼі будуть зіставлені з різними користувачами на хості, що не перетинаються, обмежено те, що вони можуть зробити з іншими Podʼами.
Можливості, надані Podʼу, також обмежуються простором імен користувачів Podʼа і здебільшого є недійсними поза ним, а деякі навіть абсолютно нечинні. Ось два приклади:
CAP_SYS_MODULE не має жодного ефекту, якщо його надано Podʼу, що використовує простори імен користувачів, Pod не може завантажити модулі ядра.CAP_SYS_ADMIN обмежений простором імен користувачів Podʼа та є недійсним поза його межами.Без використання просторів імен користувачів контейнер, який працює як root, у разі втечі контейнера, має привілеї root на вузлі. І якщо контейнеру надано деякі можливості, ці можливості є дійсними на хості. Цього не відбувається, коли ми використовуємо простори імен користувачів.
Якщо ви хочете дізнатися більше подробиць про те, що змінюється під час використання просторів імен користувачів, дивіться man 7 user_namespaces.
Типово kubelet призначає UID/GID Podʼам вище діапазону 0-65535, ґрунтуючись на припущенні, що файли та процеси хоста використовують UID/GID у цьому діапазоні, що є стандартним для більшості дистрибутивів Linux. Цей підхід запобігає будь-якому перетину між UID/GID хоста та UID/GID Podʼів.
Уникнення перетину є важливим для помʼякшення впливу вразливостей, таких як CVE-2021-25741, де потенційно Pod може читати довільні файли на хості. Якщо UID/GID Podʼа та хоста не перетинаються, те, що може робити Pod, обмежено: UID/GID Podʼа не буде відповідати власнику/групі файлів хоста.
Kubelet може використовувати власний діапазон ідентифікаторів користувачів та груп для Podʼів. Для налаштування власного діапазону вузол повинен мати:
kubelet в системі (ви не можете використовувати інше імʼя користувача тут)getsubids (частина shadow-utils), доступний у PATH для бінарного файлу kubelet.kubelet (див. man 5 subuid та man 5 subgid).Цей параметр лише збирає конфігурацію діапазону UID/GID та не змінює користувача, який виконує kubelet.
Вам потрібно дотримуватися деяких обмежень для допоміжного діапазону ID, який ви призначаєте користувачу kubelet:
Допоміжний ідентифікатор користувача, який визначає початок діапазону UID для Podʼів, має бути кратним 65536 і також повинен бути більшим або рівним 65536. Іншими словами, ви не можете використовувати жодний ідентифікатор з діапазону 0-65535 для Podʼів; kubelet накладає це обмеження, щоб ускладнити створення ненавмисно незахищеної конфігурації.
Кількість допоміжних ID повинна бути кратною 65536.
Кількість допоміжних ID повинна бути щонайменше 65536 x <maxPods>, де <maxPods> — максимальна кількість Podʼів, які можуть запускатися на вузлі.
Ви повинні призначити однаковий діапазон як для ідентифікаторів користувача, так і для ідентифікаторів груп. Не має значення, чи мають інші користувачі діапазони ідентифікаторів користувача, що не збігаються з діапазонами ідентифікаторів груп.
Жоден з призначених діапазонів не повинен перетинатися з жодним іншим призначенням.
Конфігурація допоміжних ID повинна бути лише одним рядком. Іншими словами, ви не можете мати кілька діапазонів.
Наприклад, ви можете визначити /etc/subuid та /etc/subgid, щоб обидва мали такі записи для користувача kubelet:
# Формат такий
# імʼя:firstID:кількість ідентифікаторів
# де
# - firstID дорівнює 65536 (мінімальне можливе значення)
# - кількість ідентифікаторів дорівнює 110 * 65536
# (110 — стандартне обмеження кількості Podʼів на вузлі)
kubelet:65536:7208960
Якщо у вас є вузол, на якому працюють Podʼи з просторами імен користувачів, і ви хочете внести вищезазначені зміни конфігурації, ось кілька важливих приміток.
Конфігурацію слід змінювати, коли на вузлі не запущено жодного Podʼа, що використовує простори імен користувачів. Під час зміни на вузлі, де працюють будь-які Podʼи з просторами імен користувачів, вам потрібно спочатку очистити вузол перед застосуванням конфігурації та перезапуском kubelet. Під час очищення вузла памʼятайте, що Podʼи DaemonSet або інші Podʼи, що толерують taint unschedulable, не будуть виселені.
Причина, чому не може бути запущено жодного Podʼа, що використовує простори імен користувачів, полягає в тому, що вони можуть використовувати будь-який діапазон, потенційно поза новим налаштованим діапазоном. Kubelet не зможе запуститися, якщо він не зможе застосувати нову конфігурацію для наявних Podʼів на вузлі.
Починаючи з Kubernetes v1.33 можна встановити кількість ID для кожного Podʼа в KubeletConfiguration.
apiVersion: kubelet.config.k8s.io/v1beta1
kind: KubeletConfiguration
userNamespaces:
idsPerPod: 1048576
Значення idsPerPod (uint32) має бути кратним 65536. Стандартне значення — 65536. Це значення застосовується лише до контейнерів, створених після запуску kubelet з цією KubeletConfiguration. На запущені контейнери ця конфігурація не впливає.
У версіях Kubernetes до v1.33 кількість ID для кожного Podʼа була жорстко встановлена на рівні 65536.
Для Podʼів Linux, які увімкнули простори імен користувачів, Kubernetes послаблює застосування Стандартів безпеки Podʼа контрольованим способом.
Якщо ви створите Pod, який використовує простори імен користувачів, такі поля не будуть обмежені навіть у контекстах, які застосовують стандарт безпеки Podʼів Baseline чи Restricted. Це не становить проблему безпеки, оскільки root всередині Podʼа з просторами імен користувачів фактично посилається на користувача всередині контейнера, який ніколи не зіставляється з привілейованим користувачем на хості. Ось список полів, які не перевіряються для Podʼів в цих обставинах:
spec.securityContext.runAsNonRootspec.containers[*].securityContext.runAsNonRootspec.initContainers[*].securityContext.runAsNonRootspec.ephemeralContainers[*].securityContext.runAsNonRootspec.securityContext.runAsUserspec.containers[*].securityContext.runAsUserspec.initContainers[*].securityContext.runAsUserspec.ephemeralContainers[*].securityContext.runAsUserКрім того, якщо Pod перебуває в контексті зі стандартом безпеки Podʼів Baseline, перевірка таких полів також буде помʼякшена:
spec.containers[*].securityContext.procMountspec.initContainers[*].securityContext.procMountspec.ephemeralContainers[*].securityContext.procMountЗі стандартом безпеки Podʼів Restricted Pod все одно повинен використовувати лише стандартний або порожній ProcMount.
Під час використання просторів імен користувачів для Podʼа заборонено використовувати інші простори імен хоста. Зокрема, якщо ви встановите hostUsers: false, ви не маєте права встановлювати жодне з такого:
hostNetwork: truehostIPC: truehostPID: trueЖоден контейнер також не може використовувати volumeDevices (блокові томи raw, такі як /dev/sda). Це стосується всіх масивів контейнерів у специфікації Podʼа:
containersinitContainersephemeralContainersPodʼи, які використовують простір імен користувачів, потребують, щоб файлова система підтримувала монтування idmap. Деякі файлові системи не підтримують монтування idmap, і тому не можуть використовуватися з просторами імен користувачів. У таких випадках будуть згенеровані такі події. Зверніть увагу, що деталі попередження залежать від середовища виконання контейнерів, яке ви використовуєте.
Warning Failed 1s kubelet Error: failed to create containerd task: failed to create shim task: OCI runtime create failed: runc create failed: unable to start container process: error during container init: failed to fulfil mount request: failed to set MOUNT_ATTR_IDMAP on ${your mount path} invalid argument (maybe the filesystem used doesn't support idmap mounts on this kernel?): unknown
Томи NFS не можуть бути змонтовані в Pod з простором імен користувачів, оскільки клієнт Linux NFS ще не підтримує монтування idmap. Для поточного списку підтримуваних файлових систем дивіться сторінку керівництва Linux mount_setattr(2).
Kubelet експортує дві метрики prometheus, специфічні для просторів імен користувачів:
started_user_namespaced_pods_total: лічильник, який відстежує кількість спроб створення Podʼів з просторами імен користувачів.started_user_namespaced_pods_errors_total: лічильник, який відстежує кількість помилок під час створення Podʼів з просторами імен користувачів.Елементи на цій сторінці відносяться до сторонніх продуктів чи проєктів, які надають функціонал, необхідний для Kubernetes. Автори проєкту Kubernetes не несуть відповідальності за ці проєкти. Ознайомтесь з настановами на вебсайті CNCF для отримання докладної інформації.
Ознайомтесь з посібником з контенту перед тим, як пропонувати додавання посилання на стороні компоненти.