Intelligente Lösungen
in neuer Dimension

LXD/LXC: Installation auf Ubuntu-22.04 mit Netzwerk

Hier beschreibe ich, wie ich LXD/LXC auf Ubuntu-22.04 in Betrieb nehme. Grob startet die Beschreibung mit dieser hier: LXD/LXC: Installation auf Ubuntu-22.04. Danach wird das Netzwerk konfiguriert und damit der Zugriff auf die LXC-Container via im DNS hinterlegten Containernamen ermöglicht.

Die ganze Aktion dauert grob 1 Stunde, wenn man halbwegs weiß, was man zu erledigen hat. Die Doku habe ich durchgespielt mit Ubuntu-22.04.1 und LXD-5.9.

Aktualisieren

1
2
sudo apt update
sudo apt upgrade

LXD installieren

1
sudo snap install lxd

Plattenbereich für LXC anlegen

1
2
3
4
5
6
7
8
9
10
11
12
$ sudo vgdisplay
  --- Volume group ---
  VG Name               ubuntu-vg
...
  VG Size               500 GiB
  PE Size               4,00 MiB
  Total PE              125000
  Alloc PE / Size       61684 / 240,95 GiB
  Free  PE / Size       57366 / 224,09 GiB
  VG UUID               CZfxss-UeDu-a12223
$ sudo lvcreate -n $(hostname)-lxclv -L 50G ubuntu-vg
 Logical volume "cslpc55-lxclv" created.

LXD initialisieren

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
$ sudo 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 (btrfs, ceph, dir, lvm, zfs) [default=zfs]: btrfs
Create a new BTRFS pool? (yes/no) [default=yes]: yes
Would you like to use an existing block device? (yes/no) [default=no]: yes
Path to the existing block device: /dev/mapper/ubuntu--vg-cslpc55--lxclv
Would you like to connect to a MAAS server? (yes/no) [default=no]: 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]: 
Would you like LXD to be available over the network? (yes/no) [default=no]: no
Would you like stale cached images to be updated automatically? (yes/no) [default=yes]: no
Would you like a YAML "lxd init" preseed to be printed? (yes/no) [default=no]: yes
config:
  images.auto_update_interval: "0"
networks:
- config:
    ipv4.address: auto
    ipv6.address: auto
  description: ""
  name: lxdbr0
  type: ""
  project: default
storage_pools:
- config:
    source: /dev/mapper/ubuntu--vg-cslpc55--lxclv
  description: ""
  name: default
  driver: btrfs
profiles:
- config: {}
  description: ""
  devices:
    eth0:
      name: eth0
      network: lxdbr0
      type: nic
    root:
      path: /
      pool: default
      type: disk
  name: default
projects: []
cluster: null

Container anlegen

1
2
3
4
$ sudo lxc launch ubuntu:22.04 ubuntu-2204
Creating ubuntu-2204
Retrieving image: Unpack: 100% (2.14GB/s)   
Starting ubuntu-2204

Container sichten

1
2
3
4
5
6
$ sudo lxc list
+-------------+---------+----------------------+----------------------------------------------+-----------+-----------+
|    NAME     |  STATE  |         IPV4         |                     IPV6                     |   TYPE    | SNAPSHOTS |
+-------------+---------+----------------------+----------------------------------------------+-----------+-----------+
| ubuntu-2204 | RUNNING | 10.179.95.114 (eth0) | fd42:5061:632:dd27:216:3eff:fed6:4560 (eth0) | CONTAINER | 0         |
+-------------+---------+----------------------+----------------------------------------------+-----------+-----------+

Container-Kommandos ohne SUDO

1
2
3
4
5
USER=uheller
sudo usermod -aG lxd ${USER}
# Abmelden und wieder anmelden falls ${USER} dein eigenes Benutzerkonto ist
# Nachkontrolle - muß "lxd" ausgeben
id ${USER}|grep -o lxd

Basisimage für Uli

Prompt vom Container holen mit sudo lxc exec ubuntu-2204 /bin/bash und dann im Container:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
# Aktualisieren
apt-get -y update
apt-get -y upgrade
apt-get -y dist-upgrade
apt-get -y autoremove
apt-get -y clean
# Zusatzpakete
apt-get -y install joe
apt-get -y install apt-transport-https
apt-get -y install openssh-server
apt-get -y install net-tools # ... provides ifconfig and netstat
apt-get -y clean
# Autostart für SSH
systemctl enable ssh
# PubKey eintragen
mkdir /root/.ssh
chmod 700 /root/.ssh
touch /root/.ssh/authorized_keys
chmod 600 /root/.ssh/authorized_keys
cat >>/root/.ssh/authorized_keys
ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEA1cd... Uli's SSH Key
^D
cat >>/etc/bash.bashrc
HISTFILESIZE=
HISTSIZE=
HISTTIMEFORMAT="[%F %T] "
# Change the file location because certain bash sessions truncate .bash_history file upon close.
# http://superuser.com/questions/575479/bash-history-truncated-to-500-lines-on-each-login
HISTFILE=~/.bash_eternal_history
# Force prompt to write history after every command.
# http://superuser.com/questions/20900/bash-history-loss
PROMPT_COMMAND="history -a; ${PROMPT_COMMAND:-true}"
# Log last command to syslog
log_command () {
 echo "${USER} $(HISTTIMEFORMAT='' builtin history 1|cut -c8-)" |  logger -t shell -p user.info
}
PROMPT_COMMAND="${PROMPT_COMMAND:-true};log_command"
^D
for f in /etc/skel/.bashrc /root/.bashrc /home/ubuntu/.bashrc; do\
  sed -i 's/^\(HISTSIZE\|HISTFILESIZE\)/#\1/' "${f}"
done
timedatectl set-timezone Europe/Berlin

Netzwerk

Sichten

1
2
3
4
5
6
7
8
$ lxc network list
+---------+----------+---------+----------------+--------------------------+-------------+---------+---------+
|  NAME   |   TYPE   | MANAGED |      IPV4      |           IPV6           | DESCRIPTION | USED BY |  STATE  |
+---------+----------+---------+----------------+--------------------------+-------------+---------+---------+
| enp37s0 | physical | NO      |                |                          |             | 0       |         |
+---------+----------+---------+----------------+--------------------------+-------------+---------+---------+
| lxdbr0  | bridge   | YES     | 10.179.95.1/24 | fd42:5061:632:dd27::1/64 |             | 2       | CREATED |
+---------+----------+---------+----------------+--------------------------+-------------+---------+---------+

Anpassen

Ich hätte gerne 2 Netzwerk-Brücken:

  • lxdhostonly … Brücke ohne Zugriff in’s Internet
  • lxdnat … Brücke mit Zugriff von den Containern in’s Internet via NAT

Also:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
$ lxc network create lxdhostonly ipv4.address=10.2.210.1/24 ipv4.nat=false ipv6.address=none
Network lxdhostonly created
$ lxc network create lxdnat ipv4.address=10.38.231.1/24 ipv4.nat=true ipv6.address=none
Network lxdnat created
$ lxc profile device set default eth0 network=lxdnat
$ lxc network delete lxdbr0
Network lxdbr0 deleted
$ lxc network list
|    NAME     |   TYPE   | MANAGED |      IPV4      | IPV6 | DESCRIPTION | USED BY |  STATE  |
+-------------+----------+---------+----------------+------+-------------+---------+---------+
| enp37s0     | physical | NO      |                |      |             | 0       |         |
+-------------+----------+---------+----------------+------+-------------+---------+---------+
| lxdhostonly | bridge   | YES     | 10.2.210.1/24  | none |             | 2       | CREATED |
+-------------+----------+---------+----------------+------+-------------+---------+---------+
| lxdnat      | bridge   | YES     | 10.38.231.1/24 | none |             | 0       | CREATED |
+-------------+----------+---------+----------------+------+-------------+---------+---------+

Namensauflösung temporär

Anleitung: How to integrate with systemd-resolved.

Vorbereitungen

1
2
3
4
5
6
7
8
9
10
# DNS address
root@cslpc55:~# lxc network get lxdhostonly ipv4.address
10.2.210.1/24
root@cslpc55:~# lxc network get lxdnat ipv4.address
10.38.231.1/24

# DNS domain
root@cslpc55:~# lxc network get lxdhostonly dns.domain
root@cslpc55:~# lxc network get lxdnat dns.domain
# If this option is not set, the default domain name is lxd

Temporär aktivieren

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
root@cslpc55:~# resolvectl dns lxdhostonly 10.2.210.1
root@cslpc55:~# resolvectl domain lxdhostonly '~lxd'
root@cslpc55:~# resolvectl dns lxdnat 10.38.231.1
root@cslpc55:~# resolvectl domain lxdnat '~lxd'

# Test
root@cslpc55:~# lxc start ubuntu-2204
root@cslpc55:~# lxc ls
+-------------+---------+---------------------+------+-----------+-----------+
|    NAME     |  STATE  |        IPV4         | IPV6 |   TYPE    | SNAPSHOTS |
+-------------+---------+---------------------+------+-----------+-----------+
| ubuntu-2204 | RUNNING | 10.2.210.114 (eth0) |      | CONTAINER | 0         |
+-------------+---------+---------------------+------+-----------+-----------+
root@cslpc55:~# ping ubuntu-2204.lxd
PING ubuntu-2204.lxd (10.2.210.114) 56(84) bytes of data.
64 bytes from ubuntu-2204.lxd (10.2.210.114): icmp_seq=1 ttl=64 time=0.045 ms
64 bytes from ubuntu-2204.lxd (10.2.210.114): icmp_seq=2 ttl=64 time=0.084 ms
^C
--- ubuntu-2204.lxd ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1029ms
rtt min/avg/max/mdev = 0.045/0.064/0.084/0.019 ms

Dauerhaft aktivieren

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
root@cslpc55:~# cat >/tmp/service-template <<EOF
[Unit]
Description=LXD per-link DNS configuration for NETWORK_BRIDGE
BindsTo=sys-subsystem-net-devices-NETWORK_BRIDGE.device
After=sys-subsystem-net-devices-NETWORK_BRIDGE.device

[Service]
Type=oneshot
ExecStart=/usr/bin/resolvectl dns NETWORK_BRIDGE DNS_ADDRESS
ExecStart=/usr/bin/resolvectl domain NETWORK_BRIDGE DNS_DOMAIN
ExecStopPost=/usr/bin/resolvectl revert NETWORK_BRIDGE
RemainAfterExit=yes

[Install]
WantedBy=sys-subsystem-net-devices-NETWORK_BRIDGE.device
EOF

root@cslpc55:~# sed -e "s/NETWORK_BRIDGE/lxdhostonly/g"\
  -e "s/DNS_ADDRESS/10.2.210.1/g"\
  -e "s/DNS_DOMAIN/~lxd/g"\
  /tmp/service-template >/etc/systemd/system/lxd-dns-lxdhostonly.service
root@cslpc55:~# sed -e "s/NETWORK_BRIDGE/lxdnat/g"\
  -e "s/DNS_ADDRESS/10.38.231.1/g"\
  -e "s/DNS_DOMAIN/~lxd/g"\
  /tmp/service-template >/etc/systemd/system/lxd-dns-lxdnat.service

root@cslpc55:~# rm -f /tmp/service-template

root@cslpc55:~# systemctl daemon-reload
root@cslpc55:~# systemctl enable --now lxd-dns-lxdhostonly
Created symlink /etc/systemd/system/sys-subsystem-net-devices-lxdhostonly.device.wants/lxd-dns-lxdhostonly.service → /etc/systemd/system/lxd-dns-lxdhostonly.service.
Unit /etc/systemd/system/lxd-dns-lxdhostonly.service is added as a dependency to a non-existent unit sys-subsystem-net-devices-lxdhostonly.device.
root@cslpc55:~# systemctl enable --now lxd-dns-lxdnat
Created symlink /etc/systemd/system/sys-subsystem-net-devices-lxdnat.device.wants/lxd-dns-lxdnat.service → /etc/systemd/system/lxd-dns-lxdnat.service.
Unit /etc/systemd/system/lxd-dns-lxdnat.service is added as a dependency to a non-existent unit sys-subsystem-net-devices-lxdnat.device.

Warnung ignorieren, Reboot und Test:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
root@cslpc55:~# lxc ls
+-------------+---------+---------------------+------+-----------+-----------+
|    NAME     |  STATE  |        IPV4         | IPV6 |   TYPE    | SNAPSHOTS |
+-------------+---------+---------------------+------+-----------+-----------+
| ubuntu-2204 | RUNNING | 10.2.210.114 (eth0) |      | CONTAINER | 0         |
+-------------+---------+---------------------+------+-----------+-----------+
root@cslpc55:~# ping ubuntu-2204.lxd
PING ubuntu-2204.lxd (10.2.210.114) 56(84) bytes of data.
64 bytes from ubuntu-2204.lxd (10.2.210.114): icmp_seq=1 ttl=64 time=0.044 ms
64 bytes from ubuntu-2204.lxd (10.2.210.114): icmp_seq=2 ttl=64 time=0.086 ms
^C
--- ubuntu-2204.lxd ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1032ms
rtt min/avg/max/mdev = 0.044/0.065/0.086/0.021 ms
root@cslpc55:~# systemctl status lxd-dns-lxdhostonly
● lxd-dns-lxdhostonly.service - LXD per-link DNS configuration for lxdhostonly
     Loaded: loaded (/etc/systemd/system/lxd-dns-lxdhostonly.service; enabled; vendor preset: enabled)
     Active: active (exited) since Sat 2022-12-24 09:57:05 CET; 58s ago
    Process: 7003 ExecStart=/usr/bin/resolvectl dns lxdhostonly 10.2.210.1 (code=exited, status=0/SUCCESS)
    Process: 7007 ExecStart=/usr/bin/resolvectl domain lxdhostonly ~lxd (code=exited, status=0/SUCCESS)
   Main PID: 7007 (code=exited, status=0/SUCCESS)
        CPU: 6ms

Dez 24 09:57:05 cslpc55 systemd[1]: Starting LXD per-link DNS configuration for lxdhostonly...
Dez 24 09:57:05 cslpc55 systemd[1]: Finished LXD per-link DNS configuration for lxdhostonly.

Isolierte Benutzerkennungen für Container aktivieren

Üblicherweise werden bei LXC-Containern in allen Containern gleichartige Nutzerkennungen (UIDs) verwendet. Ich habe gerne höhere Sicherheit und nutze separate UIDs für die Container.

1
2
3
4
5
6
7
8
9
10
11
12
root@cslpc55:~# cat >>/etc/subuid <<EOF
lxd:100000:1000000000
root:100000:1000000000
EOF

root@cslpc55:~# cat >>/etc/subgid <<EOF
lxd:100000:1000000000
root:100000:1000000000
EOF

root@cslpc55:~# systemctl restart snap.lxd.daemon
# Kontrolle via Log geht leider nicht mehr

Profile für Netzwerkkonfiguration und isolierte Benutzerkennungen anlegen

Ausgangslage

1
2
3
4
5
6
root@cslpc55:~# lxc profile list
+---------+---------------------+---------+
|  NAME   |     DESCRIPTION     | USED BY |
+---------+---------------------+---------+
| default | Default LXD profile | 1       |
+---------+---------------------+---------+

Profil ohne Internet-Zugriff (hostonly)

1
2
3
4
root@cslpc55:~# lxc profile copy default hostonly
root@cslpc55:~# lxc profile set hostonly security.idmap.isolated=true
root@cslpc55:~# lxc profile device set hostonly eth0 network=lxdhostonly
root@cslpc55:~# lxc profile show hostonly|sed -e 's/^description:.*$/description: HOSTONLY LXD profile (without internet access)/'|lxc profile edit hostonly

Profil mit Internet-Zugriff (nat)

1
2
3
4
5
6
7
root@cslpc55:~# lxc profile copy hostonly nat
root@cslpc55:~# lxc profile device add nat eth1 \
  name=eth1\
  network=lxdnat\
  type=nic
Device eth1 added to nat
root@cslpc55:~# lxc profile show nat|sed -e 's/^description:.*$/description: NAT LXD profile (with internet access)/'|lxc profile edit nat

Schlusskontrolle

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
root@cslpc55:~# lxc profile list
+----------+------------------------------------------------+---------+
|   NAME   |                  DESCRIPTION                   | USED BY |
+----------+------------------------------------------------+---------+
| default  | Default LXD profile                            | 1       |
+----------+------------------------------------------------+---------+
| hostonly | HOSTONLY LXD profile (without internet access) | 0       |
+----------+------------------------------------------------+---------+
| nat      | NAT LXD profile (with internet access)         | 0       |
+----------+------------------------------------------------+---------+

root@cslpc55:~# lxc profile show hostonly
config:
  security.idmap.isolated: "true"
description: HOSTONLY LXD profile (without internet access)
devices:
  eth0:
    name: eth0
    network: lxdhostonly
    type: nic
  root:
    path: /
    pool: default
    type: disk
name: hostonly
used_by: []

root@cslpc55:~# lxc profile show nat
config:
  security.idmap.isolated: "true"
description: NAT LXD profile (with internet access)
devices:
  eth0:
    name: eth0
    network: lxdhostonly
    type: nic
  eth1:
    network: lxdnat
    type: nic
  root:
    path: /
    pool: default
    type: disk
name: nat
used_by: []

Anpassungen für Server

Mit der bislang erfolgten Konfiguration werden neue Container per Standard mit aktiviertem Internet-Zugriff angelegt. Das passt für meinen Arbeitsplatz wunderbar. Bei Servern ist es mit lieber, wenn die Container keinen Internet-Zugriff haben:

1
# lxc profile device set default eth0 network=lxdhostonly

Links

Änderungen

  • 2022-12-24: Erste Version