Install
apt install lxd lxd-client
# https://raw.githubusercontent.com/panticz/installit/master/install.lxd.sh
Install LXD as snap package
sudo apt install -y snapd sudo snap install lxd # configure default storage lxc storage create zfs zfs source=rpool/lxd lxc profile device add default root disk path=/ pool=zfs # configure default network lxc network create lxdbr0 lxc profile device add default enp0s25 nic nictype=bridged parent=lxdbr0
Migrate LXD from APT to snap
https://discuss.linuxcontainers.org/t/is-the-snap-the-recommended-way-to-install-lxd-in-ubuntu-18-04/2248/10
snap run lxd.migrate
#apt remove lxd lxd-client lxcfs liblxc1 liblxc-common
lxc profile delete default lxc profile device add default root disk path=/ pool=default lxc profile create default lxd init --auto
# Add user to group
sudo usermod -a -G lxd ${USER}
Create VM
# Container lxc launch ubuntu:lts ubuntu lxc launch ubuntu-minimal:lts ubuntu lxc launch images:ubuntu/20.04 u2004 lxc launch images:ubuntu/20.04/cloud u2004c lxc launch ubuntu:20.04 u2004 lxc launch ubuntu:trusty trusty lxc launch ubuntu:lts ubuntu-lts -p disk-zfs -p nic-dev-mgmt -p disk-httpboot -c boot.autostart=true -c volatile.dev-mgmt.hwaddr=00:16:32:48:64:80 # VMs lxc launch images:ubuntu/21.04 vm2104 --vm lxc launch images:ubuntu/21.04/cloud vm2104c --vm lxc launch images:centos/7 centos7 lxc exec xenial bash # remove container lxc delete xenial -f # list container name only lxc list -c n --format csv # -c volatile.dev-mgmt.hwaddr=00:11:22:33:44:55
Configuration
lxc profile set ubuntu-profile boot.autostart true lxc profile set ubuntu-profile boot.autostart.delay 1 lxc profile set ubuntu-profile limits.cpu 2 lxc config set ${CONTAINER} limits.cpu 4 lxc profile set ubuntu-profile limits.memory 64MB lxc profile device set ubuntu-profile root size 512MB lxc config set core.trust_password mobile lxc remote add mobile 127.0.0.1 --accept-certificate lxc remote set-default mobile # remove limit lxc config unset ${CONTAINER} limits.cpu
Create priviliged VM
CONTAINER_NAME=vm1 CONTAINER_IP=10.0.1.23 lxc launch ubuntu:18.04 ${CONTAINER_NAME} -p mgmt-dev -c security.privileged true lxc config set ${CONTAINER_NAME} boot.autostart true lxc config set ${CONTAINER_NAME} security.privileged true lxc config set ${CONTAINER_NAME} boot.autostart.priority 99 lxc config device add ${CONTAINER_NAME} eth1 nic mtu=9000 nictype=macvlan parent=vlan-1234
Console
Ctrl-a q
CLI
lxc list
Image
# list local images lxc image list # list all remote images lxc image list images: # search specific remote image lxc image list images: 20.04 lxc image list images: ubuntu lxc image list images: centos lxc image list images: ubuntu i386 # Add Ubuntu minimal images simplestreams endpoint https://blog.simos.info/a-closer-look-at-minimal-ubuntu-for-lxd/ lxc remote add --protocol simplestreams ubuntu-minimal https://cloud-images.ubuntu.com/minimal/releases/ lxc image alias list ubuntu-minimal: lxc image list ubuntu-minimal:lts lxc image list ubuntu-minimal:22.04 lxc image info ubuntu-minimal:20.04 lxc image show ubuntu-minimal:lts # create VM based on Ubuntu minimal image lxc launch ubuntu-minimal:focal u2004m # add daily images lxc remote add --protocol simplestreams ubuntu-minimal-daily https://cloud-images.ubuntu.com/minimal/daily/ lxc launch ubuntu-minimal-daily:eoan lxc remote add --protocol simplestreams ubuntu-minimal https://cloud-images.ubuntu.com/minimal/releases/ lxc launch ubuntu-minimal:disco # image info lxc image info images:ubuntu/20.04/cloud # refresh lxc image refresh <IMAGE_HASH>
Get started
https://linuxcontainers.org/lxd/getting-started-cli/
Rootfs
/var/lib/lxd/containers/<CONTAINER>/rootfs
Ansible module
http://docs.ansible.com/ansible/latest/lxd_container_module.html
Configuration
# Non-interactive configuration via preseed YAML https://lxd.readthedocs.io/en/latest/preseed/ /etc/default/lxd-bridge /var/lib/lxd/containers/<CONTAINER>/rootfs/config ~/.config/lxc/config.yml ... aliases: list: list -c n,user.fqdn:FQDN,s46tS # output only container name lxc list -c n --format csv
Containers
https://uk.images.linuxcontainers.org/
Network
https://lxd.readthedocs.io/en/latest/networks/
https://ubuntu.com/blog/network-management-with-lxd-2-3
lxc config device add container1 eth1 nic name=eth1 nictype=bridged parent=br0 lxc config device remove router eth1 lxc config device add router eth1 nic nictype=physical parent=eth0 lxc network set lxdbr0 ipv4.routes 100.200.200.48/29 # Fixed IP ? echo "dhcp-host=xenial,10.135.253.200" >> /etc/lxd/dnsmasq.conf sed -i 's|LXD_CONFILE=""|LXD_CONFILE="/etc/lxd/dnsmasq.conf"|' /etc/default/lxd-bridge lxc network show lxdbr0 # cat /etc/dnsmasq.d/lxd server=/lxd/10.135.253.1 bind-interfaces except-interface=lxdbr0 # static lxc stop c1 lxc network attach lxdbr0 c1 eth0 eth0 lxc config device set c1 eth0 ipv4.address 10.99.10.42 lxc start c1
Stop
NODES=$(lxc list -c n --format csv volatile.last_state.power="RUNNING" lab-vm | sort | tac) for NODE in ${NODES}; do lxc stop ${NODE} done
Snapshot
# create lxc snapshot u1804 ssh # list lxc info u1804 # restore lxc restore u1804 ssh # delete lxc delete <instance>/<snapshot>
Snap
snap install lxd && lxd.migrate apt install -t <release>-backports lxd lxd-client
Configure bridge
lxc profile device remove default eth0 lxc profile device add default eth0 nic nictype=macvlan parent=br0 name=eth0 lxc profile show default # test me lxc network set lxdbr0 ipv4.routes PUBLIC-IP/32
create profile
lxc profile copy default mgmt-dev # lxc profile list lxc profile device set mgmt-dev eth0 nictype macvlan lxc profile device set mgmt-dev eth0 parent mgmt-dev-v1234 lxc profile show mgmt-dev # change profile lxc profile assign container1 mgmt-prod # add / delete profile lxc profile add container1 profile1 lxc profile remove container1 profile1
Add / remove interface to container
lxc config device add bifrost-dev eth1 nic name=eth1 nictype=macvlan parent=ipmi-dev-v4421 lxc config device del bifrost-dev2 eth1
Configure MAC address
lxc config set CONAINER_1 volatile.eth0.hwaddr 00:11:22:33:44:55 lxc launch ubuntu:x --config volatile.eth0.hwaddr=00:11:22:33:44:55
Pass through external USB interface as eth1
lxc stop router lxc config device remove router eth1 lxc start router lxc config device add router eth1 nic nictype=physical parent=enx0022f731b929
Mount drive
lxc config device add bionic1 images disk source=/var/lib/images path=/media/images
Configure http(s) proxy
# cat /etc/environment export http_proxy='http://foo:bar@192.168.11.253:8080' export https_proxy='http://foo:bar@192.168.11.253:8080' export no_proxy="localhost,127.0.0.1,*dev.example.com" # Configure http proxy for LXD daemon lxc config set core.proxy_http ${http_proxy} lxc config set core.proxy_https ${https_proxy} lxc config set core.proxy_ignore_hosts ${no_proxy} #sudo service lxd restart # Configure http proxy inside of container # lxc config set mycontainer environment.http_proxy http://[fe80::1%eth0]:13128 echo "export http_proxy=http://proxy.example.com:8080" | lxc shell <container_name> -- tee -a /etc/environment echo "export https_proxy=http://proxy.example.com:8080" | lxc shell <container_name> -- tee -a /etc/environmen
# test me (set limits)
lxc config set container1 limits.kernel.nofile 90000
lxc restart container1
Deploy SSH key
#cat ~/.ssh/id_rsa.pub | lxc shell container1 -- tee -a /root/.ssh/authorized_keys lxc file push --uid 0 --gid 0 --mode 600 ~/.ssh/id_rsa.pub ${CONTAINER}/root/.ssh/authorized_keys
Documentation
https://github.com/lxc/lxd/blob/master/doc/containers.md
Issues
# ERROR utils - utils.c:lxc_setup_keyring:1801 - Disk quota exceeded - Failed to create kernel keyring lxc profile set default security.syscalls.blacklist "keyctl errno 38"
Export / backup (all) container
https://discuss.linuxcontainers.org/t/backup-the-container-and-install-it-on-another-server/463/2
CONTAINER=my-container1 #CONTAINERS=$(lxc list -c n --format csv) #for CONTAINER in ${CONTAINERS}; do #echo ${CONTAINER} lxc stop ${CONTAINER} lxc publish ${CONTAINER} --alias ${CONTAINER} lxc start ${CONTAINER} lxc image export ${CONTAINER} ${CONTAINER} lxc image delete ${CONTAINER} #done # lxc delete ${CONTAINER}
Import container from image
CONTAINER=my-container1 lxc image import ${CONTAINER}.tar.gz --alias ${CONTAINER} lxc launch ${CONTAINER} ${CONTAINER} #-p storage-zfs -p nic-mgmt-dev -c boot.autostart=true
Search for eth1 in all containers
for CONTAINER in $(lxc list -c n --format csv); do echo ${CONTAINER} lxc config show ${CONTAINER} | grep "volatile.eth0.name: eth1" done # timezone lxc config set contrainer1 environment.TZ Europe/Berlin
Init
# lxd init Would you like to use LXD clustering? (yes/no) [default=no]: Do you want to configure a new storage pool? (yes/no) [default=yes]: Name of the new storage pool [default=default]: Name of the storage backend to use (dir, lvm, zfs) [default=zfs]: Create a new ZFS pool? (yes/no) [default=yes]: Would you like to use an existing block device? (yes/no) [default=no]: Size in GB of the new loop device (1GB minimum) [default=45GB]: Would you like to connect to a MAAS server? (yes/no) [default=no]: Would you like to create a new local network bridge? (yes/no) [default=yes]: What should the new bridge be called? [default=lxdbr0]: What IPv4 address should be used? (CIDR subnet notation, “auto” or “none”) [default=auto]: What IPv6 address should be used? (CIDR subnet notation, “auto” or “none”) [default=auto]: none Would you like LXD to be available over the network? (yes/no) [default=no]: Would you like stale cached images to be updated automatically? (yes/no) [default=yes] Would you like a YAML "lxd init" preseed to be printed? (yes/no) [default=no]: yes config: {} cluster: null networks: - config: ipv4.address: auto ipv6.address: none description: "" managed: false name: lxdbr0 type: "" storage_pools: - config: size: 45GB description: "" name: default driver: zfs profiles: - config: {} description: "" devices: eth0: name: eth0 nictype: bridged parent: lxdbr0 type: nic root: path: / pool: default type: disk name: default
change priviliged to unpriviliged container
lxc config set c1 security.privileged false chown 100000.100000 /additional/mount/path/on/hypervisor -R
Update APT packages in all running containers
# --download-only for CONTAINER in $(lxc list -c n --format csv volatile.last_state.power=RUNNING); do echo ${CONTAINER} lxc exec ${CONTAINER} -- bash -c "apt update -qq && apt dist-upgrade -y && apt clean && apt autoremove -y" | tee ${CONTAINER}.dist-upgrade.$(date -I).log done
Restart all running container
for CONTAINER in $(lxc list -c n --format csv volatile.last_state.power=RUNNING); do echo ${CONTAINER} lxc stop ${CONTAINER} && lxc start ${CONTAINER} done
distrobuilder
https://github.com/lxc/distrobuilder
tcpdump (todo)
# on the hypervisor ln -s /etc/apparmor.d/usr.sbin.tcpdump /etc/apparmor.d/disable/ service apparmor reload
Device documentation
https://github.com/lxc/lxd/blob/master/doc/containers.md
Docker and LXD on same host
# cat /etc/docker/daemon.json { "iptables": false } #sudo ufw allow in on lxdbr0 #sudo ufw route allow in on lxdbr0 #sudo ufw route allow out on lxdbr0
cloud-init
https://blog.simos.info/how-to-preconfigure-lxd-containers-with-cloud-init/
DB edit
lxd sql global "DELETE FROM containers_devices WHERE name='root' AND type='disk';"
LXD monitor
lxc monitor --pretty --type logging
USB
https://stgraber.org/2017/03/27/usb-hotplug-with-lxd-containers/
Find container using devices
for CONTAINER in $(lxc list -c n --format csv); do echo ${CONTAINER} #lxc config show ${CONTAINER} | grep pool lxc config show ${CONTAINER} | grep devices -5 done
journalctl -u snap.lxd.daemon
Mounting Devices in LXD
https://ericroc.how/mounting-devices-in-lxd.html#mounting-devices-in-lxd
# share directory lxc config device add container1 modules disk source=/usr/lib/modules path=/usr/lib/modules
LXD cloud-config profile
- name: Create cloud-config profile lxd_profile: name: cloud-config config: user.user-data: | #cloud-config locale: en_US.UTF-8 timezone: Europe/Berlin # apt: # disable_suites: [release, updates, backports, security] # primary: # - arches: [amd64] # uri: http://mirror.example.com/current/ubuntu apt: sources_list: | deb [arch=amd64] http://mirror.example.com/current/ubuntu $RELEASE main restricted universe multiverse deb [arch=amd64] http://mirror.example.com/current/ubuntu $RELEASE-updates main restricted universe multiverse deb [arch=amd64] http://mirror.example.com/current/ubuntu $RELEASE-security main restricted universe multiverse deb [arch=amd64] http://mirror.example.com/current/ubuntu $RELEASE-backports main restricted universe multiverse apt_upgrade: true package_upgrade: true packages: - openssh-server disable_root: false ssh_authorized_keys: - "{{ lookup('file', '~/.ssh/id_rsa.pub') }}" user.network-config: | version: 1 config: - type: physical name: mgmt subnets: - type: dhcp
Expose port
lxc config device add ${CONTAINER_NAME} 443 proxy nat=true listen=tcp:${CONTAINER_IP}:443 connect=tcp:0.0.0.0:443 lxc config device add ${CONTAINER_NAME} port8080 proxy listen=tcp:0.0.0.0:8080 connect=tcp:127.0.0.1:3000
Expose port
# Find volume disk IDs ls -l /dev/disk/by-id | grep "sd[b,c,d]" | egrep -v "lvm|part" | cut -d" " -f10 # Attach additional volumes to container lxc config device add <CONTAINER_NAME> disk unix-block source=/dev/disk/by-id/<DISK_ID>
CLI
# restart network in all dev containers lxc list -c n --format csv volatile.last_state.power=RUNNING *dev | xargs -i -t lxc exec {} -- netplan apply
Live LXD container
https://linuxcontainers.org/lxd/try-it/
Restart netzwork bridge lxdbr0
# v1 sudo systemctl restart snap.lxd.daemon #sudo systemctl restart snapd # v2 snap stop lxd.daemon lxc network create lxdbr0 snap services sudo snap stop lxd.daemon sudo snap start lxd.daemon sudo snap start lxd.activate
Bash completion
. /usr/share/bash-completion/completions/lxd-client
Configure default editor
echo 'export EDITOR=vim' >> ~/.profile source ~/.profile
Database
https://linuxcontainers.org/lxd/docs/master/database/
# database diretory # ll /var/snap/lxd/common/lxd/database/ total 60 drwx------ 3 root root 4096 Jan 13 23:42 ./ drwx--x--x 17 root root 4096 Jan 13 23:42 ../ drwxr-x--- 2 root root 4096 Jan 14 01:07 global/ -rw-r--r-- 1 root root 49152 Jan 13 23:42 local.db # dump SQL lxd sql global .dump
Recover container
https://linuxcontainers.org/lxd/docs/master/backup/
# get backup.yaml from container # zfs set mountpoint=legacy lxd/containers/container1 # mount -t zfs lxd/containers/container1 /tmp/container1 # cat /tmp/container1/backup.yaml # zfs set mountpoint=none lxd/containers/container1 # debug # zfs list # lxc ls # lxc storage list # recover # lxd recover -d This LXD server currently has the following storage pools: Would you like to recover another storage pool? (yes/no) [default=no]: yes Name of the storage pool: default Name of the storage backend (btrfs, cephfs, dir, lvm, zfs, ceph): zfs Source of the storage pool (block device, volume group, dataset, path, ... as applicable): lxd Additional storage pool configuration property (KEY=VALUE, empty when done): zfs.pool_name=lxd Additional storage pool configuration property (KEY=VALUE, empty when done): volatile.initial_source=lxd Additional storage pool configuration property (KEY=VALUE, empty when done): Would you like to recover another storage pool? (yes/no) [default=no]: The recovery process will be scanning the following storage pools: - NEW: "default" (backend="zfs", source="lxd") Would you like to continue with scanning for lost volumes? (yes/no) [default=yes]: Scanning for unknown volumes... DBUG[01-14|00:31:39] Sending request to LXD method=POST url=http://unix.socket/internal/recover/validate etag= DBUG[01-14|00:31:39] { "pools": [ { "config": { "source": "lxd", "volatile.initial_source": "lxd", "zfs.pool_name": "lxd" }, "description": "", "name": "default", "driver": "zfs" } ] }
Get OS version</strong> <code> CONTAINERS=$(lxc list volatile.last_state.power="RUNNING" -c n --format csv) for CONTAINER in ${CONTAINERS}; do echo ${CONTAINER} lxc exec ${CONTAINER} -- lsb_release -ds done | paste - -
Links
https://insights.ubuntu.com/2016/03/22/lxd-2-0-your-first-lxd-container/
https://www.cyberciti.biz/faq/how-to-install-lxd-container-hypervisor-on-ubuntu-16-04-lts-server/
https://lxd.readthedocs.io/en/latest/
https://linuxcontainers.org/lxd/getting-started-cli/
https://help.ubuntu.com/lts/serverguide/lxd.html
https://cloud-images.ubuntu.com/releases/
https://stgraber.org/2016/03/30/lxd-2-0-image-management-512/
https://insights.ubuntu.com/2017/02/14/network-management-with-lxd-2-3/
https://help.ubuntu.com/lts/serverguide/lxd.html.en
https://ubuntu.com/blog/lxd-5-easy-pieces