tags : Containers
LXC
- LXC Images : Linux Containers - Image server
- OS level virtualization for running multiple isolated containers on single Linux kernel.
- Introduced 2008
- Lowlevel
- Usually managed via manager like LXD
- LXC is because it doesn’t support OCI.
- Since it uses the same kernel,
dmesg
will be the same as the host. If you have unprivileged containers, you won’t be able to rundmesg
LXD
Intro
- LXD is built on top of LXC and aims to provide a better user experience. Basically a management system on top of LXC.
- It implements a single REST API for both local and remote access.
- Scales from one instance on a single machine to a cluster in a full data center rack
LXD consists of two parts:
- Daemon (the
lxd
binary) - Client (the
lxc
binary)
Confusion w LXC
lxc
is notLXC
; the naming is a bit confusing.
lxc
is thelxd
client- All
lxc-*
commands are low level LXC commands
Setting up LXD
- Daemon
- Anyone belonging to the
lxd
group will have access to the daemon. - LXD daemon can be accessed locally over a Unix socket or, if configured, remotely over a TLS socket.
- Anyone belonging to the
- User
- LXD loads the subuid/subgid values from /etc on startup.
- Config & Profile
- Everytime you
lxd init
, config gets overwritten, you can use--preseed
to provide config via file. - For the bare minimum, you need to set a storage pool and network bridge.
- Once the network bridge is setup, it’ll show up in
ip addr
- See Instance options - LXD documentation
- Everytime you
- Net NS
- Once containers are started namespaces can be listed using
ip netns list-id
- Once containers are started namespaces can be listed using
Instances
Containers
Implemented through the use of liblxc
(LXC).
- System container
- Usually one which runs systemd in it as the init process (where using systemd)
- Simulates a virtual version of a full operating system.
- Uses kernel running on the host system.
- Suitable for full solution of libraries, applications, databases etc.
- Can create different user spaces and isolate all processes belonging to each user space
- Application container
- These are more in the likes of what Docker provides
- Usually packages a single process or application.
- Suitable to provide separate components
VMs
- Uses
qemu
to provide the VM functionality. - Uses the hardware of the host system
- Uses kernel provided by the virtual machine.
- Can be used to run a different operating system.
Configuration
- Instance properties
- Instance options
- Instance devices
Privileged and Unprivileged containers
How does LXD do unprivileged
- LXD by default is unprivileged
- Default map: 65536 UIDs and GIDs, w host base id of 100000.
- container
root
(uid0
) : mapped to host uid 100000 - container (
uid65535
) : mapped to host uid 165535
subuid
and subgid
See gids) for details.
LXD allows updating of these via security.idmap.isolated
, security.idmap.size
, security.idmap.base
and raw.idmap
. Read Idmaps for user namespace for more details.
- Change the size of the default map
- Per container maps
lxc config set <instance> security.idmap.isolated true # no sharing btwn containers lxc config set <instance> security.idmap.size 200000 # change alloc size # if allocation > allocated to lxd itself, will throw error
- Access host but not other containers. In unprivileged containers, usually user will be mapped to a user that doesn’t exist on
host
= no storage sharing w host
Personal config and setup
Install LXC
This file is automatically created and populated once LXC is installed.
λ cat /etc/lxc/default.conf
lxc.net.0.type = veth
lxc.net.0.link = lxcbr0
lxc.net.0.flags = up
lxc.net.0.hwaddr = 00:16:3e:xx:xx:xx
Install LXD
- The only entries that matter to LXD are the ones for the
root
user. - LXD itself is restricted by the
root
allocation. One may sometimes seelxd
user in these files, they are there just to ease tracking by the sysadmin. - A user can have multiple allocations.
λ sudo usermod -v 1000000-1000999999 -w 1000000-1000999999 root
λ cat /etc/sub{u,g}id
root:1000000:1000000000
root:1000000:1000000000
Make LXD accessible
- See About security - LXD documentation
lxc
(the LXC client) needs to communicate to thelxd
daemon via unix socket- Access control for LXD daemon is possible only locally via group membership. If anything else, you need to expose LXD over the network.
usermod -a -G lxd geekodour
Sharing folder
There are couple of cases here. They use the shift
method. For readonly none of this is needed.
$ lxc info | grep -E 'idmapped|shiftfs'
idmapped_mounts: "true" # kernel feature
shiftfs: "false"
idmapped_mounts_v2: "true" # lxc feature
If this is enabled, you’re good to go.
-
Mounting host directory to instance
IMPORTANT NOTE
- Adding a idmap to an actual user allows the container to run actual processes as that user
- Which means it can use
ulimit
to apply system-wide restrictions to the uid - Potentially impacting processes in other containers or even on the host.
- Add disk
$ lxc config device add <instance_name> <new_device_name> disk source=/home/geekodour/some_dir path=/home/<someuser>/dir_inside_container
- Now this will add the disk to the container, but the
owner:group
will benobody:nobody
and you won’t have edit permissions. These will be readonly, you’ll be able to edit them from your host as usual. So if that’s what you want, that’s all. - If you want
container user
to have proper access over the files, here’s what you do.######## # Before changes ######## $ lxc exec <instance> -- cat /proc/self/uid_map 0 1000000 1000000000 ######## # Make changes ######## $ id uid=1000(geekodour) gid=1000(geekodour) # truncated # - Allow LXD to map uid of host user (eg. 1000) inside the containers. # - Add root:1000:1 to subuid and subgid files. $ sudo usermod --add-subuids 1000-1000 --add-subgid 1000-1000 root λ cat /etc/sub{g,u}id root:1000000:1000000000 root:1000:1 root:1000000:1000000000 root:1000:1 # Update raw.idmap to use host uid 1000 # lxc config set test raw.idmap='both <host uid/uid-range> <container uid/uid-range> # See https://linuxcontainers.org/lxd/docs/latest/userns-idmap/#custom-idmaps $ lxc config set <instance> raw.idmap='both 1000 1000' # inside container we want to map to 1000 aswell $ lxc restart <instance> # important ######## # After change ######## $ lxc exec <instance> -- cat /proc/self/uid_map 0 1000000 1000 1000 1000 1 1001 1001001 999998999
- To check the mount point:
lxc exec <instance> -- cat /proc/self/mountinfo
-
Access files
There are other methods to access files that I’ve to explore.
Python tooling (remove later)
- Install asdf
- Installing python needs these
sudo apt-get install build-essential zlib1g-dev libffi-dev libssl-dev libbz2-dev libreadline-dev libsqlite3-dev liblzma-dev
- Install python
- Install poetry
- use poetry to create the env
- You can either use pip or use poetry add now
- direnv not needed yet
LXD Profiles
- The configuration hierarchy is as follows:
on the instance > certain ordered profile > default profile
- Instance options: array under
config
. - Instance devices: under
devices
.
- Instance options: array under
Devices
fromprofiles
are applied to theinstance
in the order in which theprofiles
are assigned to theinstance
.Devices
defined directly in the instance configuration are applied last.- At each stage, if a
device
with the same name already exists from an earlier stage, the wholedevice
entry is overridden by the latest definition.
Storage
Jargon
- Storage pool = disk to store data (LXD stores its data in storage pools)
- Storage volume = Different partitions used for specific purposes
- Storage buckets = Uses the Amazon S3 protocol.
Storage pool
- When you first setup LXD, you assign some space for all the containers. This space is called a
storage pool
. - Storage pool = Multiple storage volumes of different content type(images/instances) + Storage buckets
- Storage pool needs a
storage driver
. One of dir, btrfs, lvm, zfs, ceph-X - In a
profile
, thestorage pool
to use is defined by the pool for theroot
disk device
Storage location
When using
dir
, the reported usage by the kernel would be that of the entire partition.These 3 will be same:
df -h
/ on the hostdf -h
/ in any of the containerslxc storage info default
- We have
4
options here: Shared with the host, Dedicated disk or partition, Loop disk, Remote storage - For my usecase it’s Shared with the host with
dir
storage driver
Storage volume
- There is no concept of a default storage pool in LXD. When you create a storage volume, you must specify the storage pool to use.
3
typescontainer/vm
- Auto created at instance creation at storage pool specified by instance/profile/default profile
- Used as the root disk for the instance
- Destroyed when the instance is deleted.
image
- Only for
storage drivers
that support optimized image storage. - If deleted manually, auto deleted after ten days after last used to launch an instance.
- Only for
custom
- Volumes to hold data that you want to store separately from your instances.
- Can be shared between instances
- Has to be manually deleted
2
content types:filesystem
(container and vms) andblock
(vm only)
Networking
- Proxy Device vs Network Forwarding
- Proxy device: Instance specific, bi-directional, does not require a network connection(if non-nat mode)
- Network forward: Similar to proxy device+nat mode. Defined at network level instead of instance level.
- More info: Difference between network forward and proxy device
Container nesting
You can run docker inside LXD by setting security.nesting