User namespaces
User namespaces are used to isolate containers from the host system and from each other. See man user_namespaces(7) for more information.
ID ranges
In order to ensure that containers are running in separate user namespaces, user/group IDs from the host used for mapping are managed using ID ranges. An ID range is split into blocks of 65536 or more IDs and user namespaces are being allocated from these blocks. osctld creates one default ID range per pool with the following configuration:
osctl id-range ls
POOL NAME START_ID LAST_ID BLOCK_SIZE BLOCK_COUNT ALLOCATED FREE
tank default 1000000 4294918719 65536 65520 0 65520
This range starts from ID 1000000 and has 65520 blocks, i.e. 65520 unique maps can be created. Blocks can be allocated as:
osctl id-range allocate --block-count 4 --owner myblocks default
BLOCK_INDEX: 0
BLOCK_COUNT: 4
OWNER: myblocks
FIRST_ID: 1000000
LAST_ID: 1262143
ID_COUNT: 262144
The entire allocation table can be printed with:
osctl id-range table ls default
TYPE BLOCK_INDEX BLOCK_COUNT OWNER FIRST_ID LAST_ID ID_COUNT
allocated 0 4 myblocks 1000000 1262143 262144
free 4 65516 - 1262144 4294918719 4293656576
Allocated blocks can then be used to create custom user namespace maps. Blocks from one range can be allocated only once, but multiple ID ranges can span over the same IDs.
Blocks are usually allocated automatically when creating user namespace mappings or containers, see below.
User namespace maps
User namespace maps are created automatically with containers. Unless configured otherwise, every container creates its own user namespace mapping allocated from the default ID range. Let's see how it works:
# Create a container
osctl ct new --distribution alpine myct01
# Find out which user the container uses
osctl ct show -o user myct01
USER: myct01
osctl ct new
created a new user with the same name. The mapping itself can be
read with:
osctl user map myct01
TYPE NS_ID HOST_ID COUNT
uid 0 1000000 65536
gid 0 1000000 65536
When needed, user namespace mappings can also be created manually, even independently from ID ranges. Mappings cannot be edited, the only way is to delete it and create a new one with different configuration.
Allocated user namespace mappings
The simplest way to create a new user namespace mapping is:
osctl user new myuser01
The mapping will be allocated from the default ID range. Option --id-range
can be used to specify which ID range to allocate from. When creating containers,
pass option --user myuser01
to use this mapping.
Using specific ID range allocations
Let's say two containers should share the same mapping and more than one block is needed. First, allocate it:
osctl id-range allocate --block-count 10 default
BLOCK_INDEX: 4
BLOCK_COUNT: 10
OWNER: -
FIRST_ID: 1262144
LAST_ID: 1917503
ID_COUNT: 655360
Now pass the block index to user new
:
osctl user new --id-range-block-index 4 myuser02
osctld will create a default mapping spanning the entire ID range allocation:
osctl user map myuser02
TYPE NS_ID HOST_ID COUNT
uid 0 1262144 655360
gid 0 1262144 655360
Custom mappings from ID range allocations
UID/GID mapping can be customized:
osctl user new --id-range-block-index 4 --map 0:1262144:65536 myuser03
Option --map
sets both user and group mappings, options --uid-map
and --gid-map
can be used to have different mappings for user and group IDs.
Custom mappings
User namespace mappings don't have to be allocated from ID ranges, but then
it's the administrator's responsibility to ensure proper isolation. Use
options --map
, --uid-map
or --gid-map
to create custom mappings:
osctl user new --map 0:123000:65536 myuser04