Grundläggande funktioner i LXD - Linux containersystem

Grundläggande funktioner i LXD - Linux containersystem

LXD är nästa generations system container manager, så står det källa. Den erbjuder ett användargränssnitt som liknar virtuella maskiner, men använder Linux-behållare istället.

LXD kärna är en privilegierad demon (en tjänst som körs med roträttigheter) som tillhandahåller ett REST API via en lokal unix-socket, såväl som via nätverket om lämplig konfiguration är installerad. Klienter, som kommandoradsverktyget som levereras med LXD, gör förfrågningar via detta REST API. Detta innebär att oavsett om du använder en lokal värd eller en fjärrvärd, fungerar allt på samma sätt.

I den här artikeln kommer vi inte att uppehålla oss i detalj vid begreppen LXD, vi kommer inte att överväga alla tillgängliga funktioner som beskrivs i dokumentationen, inklusive den senaste implementeringen i de senaste versionerna av LXD av stöd för QEMU virtuella maskiner parallellt med behållare. Istället lär vi oss bara grunderna för containerhantering – konfigurera lagringspooler, nätverk, köra en container, tillämpa resursbegränsningar och hur man använder ögonblicksbilder så att du kan få en grundläggande förståelse för LXD och använda containrar på Linux.

För fullständig information, se den officiella källan:

Навигация

Installation LXD ^

Installera LXD på Ubuntu-distributioner ^

I distributionspaketet Ubuntu 19.10 lxd har en sändning på snappaket:

apt search lxd

lxd/eoan 1:0.7 all
  Transitional package - lxd -> snap (lxd)

Detta innebär att två paket kommer att installeras på en gång, ett som ett systempaket och det andra som ett snappaket. Att installera två paket på ett system kan skapa problem där systempaketet kan bli föräldralöst om snappaketet tas bort av snap-pakethanteraren.

Hitta paket lxd i snap-förvaret kan du använda följande kommando:

snap find lxd

Name             Version        Summary
lxd              3.21           System container manager and API
lxd-demo-server  0+git.6d54658  Online software demo sessions using LXD
nova             ocata          OpenStack Compute Service (nova)
nova-hypervisor  ocata          OpenStack Compute Service - KVM Hypervisor (nova)
distrobuilder    1.0            Image builder for LXC and LXD
fabrica          0.1            Build snaps by simply pointing a web form to...
satellite        0.1.2          Advanced scalable Open source intelligence platform

Genom att köra kommandot list du kan se till att paketet lxd ännu inte installerat:

snap list

Name  Version    Rev   Tracking  Publisher   Notes
core  16-2.43.3  8689  stable    canonical✓  core

Trots att LXD är ett snappaket måste det installeras via systempaketet lxd, som kommer att skapa motsvarande grupp i systemet, de nödvändiga verktygen i /usr/bin etc.

sudo apt update
sudo apt install lxd

Låt oss se till att paketet är installerat som ett snappaket:

snap list

Name  Version    Rev    Tracking  Publisher   Notes
core  16-2.43.3  8689   stable    canonical✓  core
lxd   3.21       13474  stable/…  canonical✓  -

Installera LXD på Arch Linux-distributioner ^

För att installera LXD-paketet på systemet måste du köra följande kommandon, det första kommer att uppdatera listan över paket på systemet som är tillgängliga i förvaret, det andra kommer att installera paketet direkt:

sudo pacman -Syyu && sudo pacman -S lxd

Efter installation av paketet, för att hantera LXD av en vanlig användare, måste det läggas till i systemgruppen lxd:

sudo usermod -a -G lxd user1

Låt oss se till att användaren user1 läggs till i gruppen lxd:

id -Gn user1

user1 adm dialout cdrom floppy sudo audio dip video plugdev netdev lxd

Om gruppen lxd inte visas i listan måste du aktivera användarsessionen igen. För att göra detta behöver du logga ut och logga in under samma användare.

Aktivera in systemd laddar LXD-tjänsten vid systemstart:

sudo systemctl enable lxd

Låt oss starta tjänsten:

sudo systemctl start lxd

Kontrollera servicestatus:

sudo systemctl status lxd

Storage LXD (Storage) ^

Innan initialiseringen börjar måste vi förstå hur lagringen i LXD är logiskt upplagd.

Förvaring (lagring) består av från en eller flera Förvaringspool som använder ett av de filsystem som stöds såsom ZFS, BTRFS, LVM eller vanliga kataloger. Varje Förvaringspool är uppdelad i volymer (Lagringsvolym) som innehåller bilder, behållare eller data för andra ändamål.

  • bildspråk - dessa är specialmonterade distributioner utan Linux-kärnan och tillgängliga från externa källor
  • behållare - dessa är distribuerade distributioner från bilder, redo att användas
  • Ögonblicksbilder - det här är ögonblicksbilder av tillståndet för containrar som du kan återgå till

Grundläggande funktioner i LXD - Linux containersystem

För att hantera lagring i LXD, använd kommandot lxc storage ett certifikat som du kan få genom att ange nyckeln - lxc storage --help

Följande kommando visar en lista över alla Förvaringspool i LXD-lagring:

lxc storage list

+---------+-------------+--------+--------------------------------+---------+
|  NAME   | DESCRIPTION | DRIVER |             SOURCE             | USED BY |
+---------+-------------+--------+--------------------------------+---------+
| hddpool |             | btrfs  | /dev/loop1                     | 2       |
+---------+-------------+--------+--------------------------------+---------+
| ssdpool |             | btrfs  | /var/lib/lxd/disks/ssdpool.img | 4       |
+---------+-------------+--------+--------------------------------+---------+

För att se en lista över alla Lagringsvolym i det valda Förvaringspool tjänar laget lxc storage volume list:

lxc storage volume list hddpool

+-------+----------------------------------+-------------+---------+
| TYPE  |          NAME                    | DESCRIPTION | USED BY |
+-------+----------------------------------+-------------+---------+
| image | ebd565585223487526ddb3607f515... |             | 1       |
+-------+----------------------------------+-------------+---------+

lxc storage volume list ssdpool

+-----------+----------------------------------+-------------+---------+
|   TYPE    |            NAME                  | DESCRIPTION | USED BY |
+-----------+----------------------------------+-------------+---------+
| container | alp3                             |             | 1       |
+-----------+----------------------------------+-------------+---------+
| container | jupyter                          |             | 1       |
+-----------+----------------------------------+-------------+---------+
| image     | ebd565585223487526ddb3607f515... |             | 1       |
+-----------+----------------------------------+-------------+---------+

Även om för Förvaringspool När du skapade valdes BTRFS-filsystemet, få sedan en lista Lagringsvolym eller subvolymer i BTRFS-tolkningen kan du använda verktygslådan för detta filsystem:

sudo btrfs subvolume list -p /var/lib/lxd/storage-pools/hddpool

ID 257 gen 818 parent 5 top level 5 path images/ebd565585223487526ddb3607f5156e875c15a89e21b61ef004132196da6a0a3

sudo btrfs subvolume list -p /var/lib/lxd/storage-pools/ssdpool

ID 257 gen 1820 parent 5 top level 5 path images/ebd565585223487526ddb3607f5156e875c15a89e21b61ef004132196da6a0a3
ID 260 gen 1819 parent 5 top level 5 path containers/jupyter
ID 263 gen 1820 parent 5 top level 5 path containers/alp3

Initierar LXD ^

Innan du skapar och använder behållare måste du utföra en allmän LXD-initiering som skapar och konfigurerar nätverket och lagringen. Detta kan göras manuellt med standardklientkommandon som finns tillgängliga i listan genom att anropa kommandot lxc --help eller med hjälp av initialiseringsguiden lxd init svara på några frågor.

Välja ett filsystem för Storage Pool ^

Under initieringen ställer LXD flera frågor, inklusive att bestämma filsystemtypen för standard Förvaringspool. Som standard är BTRFS-filsystemet valt för det. Det kommer att vara omöjligt att byta till en annan FS efter skapandet. För att välja en FS föreslås det jämförelsetabell för funktioner:

Leverans
katalog
btrfs
LVM
ZFS
CEPH

Optimerad bildlagring
Nej
ja
ja
ja
ja

Optimerad instansskapande
Nej
ja
ja
ja
ja

Skapa optimerad ögonblicksbild
Nej
ja
ja
ja
ja

Optimerad bildöverföring
Nej
ja
Nej
ja
ja

Optimerad instansöverföring
Nej
ja
Nej
ja
ja

Kopiera på skriv
Nej
ja
ja
ja
ja

Blockbaserad
Nej
Nej
ja
Nej
ja

Omedelbar kloning
Nej
ja
ja
ja
ja

Förvaringsdrivrutin användbar inuti en behållare
ja
ja
Nej
Nej
Nej

Återställ från äldre ögonblicksbilder (inte senaste)
ja
ja
ja
Nej
ja

Lagringskvoter
ja(*)
ja
ja
ja
Nej

Initiera nätverket och lagringspoolen med hjälp av guiden ^

Nästa kommando vi ska titta på föreslår att du ställer in huvudkomponenterna i LXD genom att svara på enkla frågor med hjälp av initialiseringsguiden.

Kör kommando lxc init och skriv in svaren på frågorna efter kolon som visas i exemplet nedan eller ändra dem enligt dina förutsättningar:

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]: ssdpool         
Name of the storage backend to use (lvm, btrfs, dir) [default=btrfs]: 
Create a new BTRFS 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=15GB]: 10GB
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]: 10.0.5.1/24
Would you like LXD to NAT IPv4 traffic on your bridge? [default=yes]: 
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] no
Would you like a YAML "lxd init" preseed to be printed? (yes/no) [default=no]: 

Skapa en extra lagringspool ^

I föregående steg skapade vi Förvaringspool som fick namnet ssdpool och vars fil finns på mitt system på /var/lib/lxd/disks/ssdpool.img. Denna filsystemadress motsvarar den fysiska SSD-enheten i min PC.

Följande åtgärder, för att utöka förståelsen för rollen som spelas av Förvaringspool i förvaret kommer vi att skapa en andra Förvaringspool som kommer att finnas fysiskt på en annan typ av disk, HDD. Problemet är att LXD inte tillåter dig att skapa Förvaringspool oadresserad /var/lib/lxd/disks/ och även symboliska länkar fungerar inte, se utvecklarens svar. Vi kan kringgå denna begränsning under initiering/formatering Förvaringspool genom att ange värdet som en blockenhet istället för sökvägen till loopback-filen genom att ange detta i nyckeln source.

Så, innan du skapar Förvaringspool du måste definiera en loopback-fil eller en befintlig partition på ditt filsystem som den ska använda. För att göra detta kommer vi att skapa och använda en fil som vi kommer att begränsa i storlek till 10 GB:

dd if=/dev/zero of=/mnt/work/lxd/hddpool.img bs=1MB count=10000

10000+0 records in
10000+0 records out
10000000000 bytes (10 GB, 9,3 GiB) copied, 38,4414 s, 260 MB/s

Låt oss ansluta loopback-filen till en gratis loopback-enhet:

sudo losetup --find --show /mnt/work/lxd/hddpool.img

/dev/loop1

Tack vare nyckeln --show Om du kör kommandot återgår namnet på enheten som vår loopback-fil är ansluten till skärmen. Om det behövs kan vi visa en lista över alla upptagna enheter av denna typ för att säkerställa att våra åtgärder är korrekta:

losetup -l

NAME       SIZELIMIT OFFSET AUTOCLEAR RO BACK-FILE                      DIO LOG-SEC
/dev/loop1         0      0         0  0 /mnt/work/lxd/hddpool.img        0     512
/dev/loop0         0      0         1  0 /var/lib/lxd/disks/ssdpool.img   0     512

Från listan kan du se att enheten har /dev/loop1 loopback-fil ingår /mnt/work/lxd/hddpool.img, och i enheten /dev/loop0 loopback-fil ingår /var/lib/lxd/disks/ssdpool.img som motsvarar standardinställningen Förvaringspool.

Följande kommando skapar ett nytt Förvaringspool i LXD baserat på loopback-filen vi just förberedde. LXD kommer att formatera loopback-filen /mnt/work/lxd/hddpool.img i enheten /dev/loop1 för BTRFS-filsystemet:

lxc storage create hddpool btrfs size=10GB source=/dev/loop1

Låt oss visa en lista över alla Förvaringspool att undersöka:

lxc storage list

+---------+-------------+--------+--------------------------------+---------+
|  NAME   | DESCRIPTION | DRIVER |             SOURCE             | USED BY |
+---------+-------------+--------+--------------------------------+---------+
| hddpool |             | btrfs  | /dev/loop1                     | 0       |
+---------+-------------+--------+--------------------------------+---------+
| ssdpool |             | btrfs  | /var/lib/lxd/disks/ssdpool.img | 0       |
+---------+-------------+--------+--------------------------------+---------+

Öka storleken på förvaringspoolen ^

Efter skapandet Förvaringspool, vid behov kan den utökas. För Förvaringspool baserat på BTRFS-filsystemet, kör följande kommandon:

sudo truncate -s +5G /mnt/work/lxd/hddpool.img
sudo losetup -c /dev/loop1
sudo btrfs filesystem resize max /var/lib/lxd/storage-pools/hddpool

Automatisk infogning av en loopback-fil i en loopback-enhetsplats ^

Vi har ett litet problem, när vi startar om värdsystemet, filen /mnt/work/lxd/hddpool.img kommer att "flyga" ut ur enheten /dev/loop1 och LXD-tjänsten kommer att krascha när den laddas eftersom den inte kommer att se den i den här enheten. För att lösa detta problem måste du skapa en systemtjänst som infogar den här filen i enheten /dev/loop1 när värdsystemet startar.

Låt oss skapa enhet filtyp service в /etc/systemd/system/ för SystemD-initieringssystemet:

cat << EOF | sudo tee -a /etc/systemd/system/lxd-hddpool.service
[Unit]
Description=Losetup LXD Storage Pool (hddpool)
After=local-fs.target

[Service]
Type=oneshot
ExecStart=/sbin/losetup /dev/loop1 /mnt/work/lxd/hddpool.img
RemainAfterExit=true

[Install]
WantedBy=local-fs.target
EOF

Aktivera tjänsten:

sudo systemctl enable lxd-hddpool

Created symlink /etc/systemd/system/local-fs.target.wants/lxd-hddpool.service → /etc/systemd/system/lxd-hddpool.service.

Efter att ha startat om värdsystemet kontrollerar vi tjänstens status:

systemctl status lxd-hddpool.service 

● lxd-hddpool.service - Losetup LXD Storage Pool (hddpool)
     Loaded: loaded (/etc/systemd/system/lxd-hddpool.service; enabled; vendor preset: disabled)
     Active: active (exited) since Wed 2020-04-08 03:43:53 MSK; 1min 37s ago
    Process: 711 ExecStart=/sbin/losetup /dev/loop1 /mnt/work/lxd/hddpool.img (code=exited, status=0/SUCCESS)
   Main PID: 711 (code=exited, status=0/SUCCESS)

апр 08 03:43:52 manjaro systemd[1]: Starting Losetup LXD Storage Pool (hddpool)...
апр 08 03:43:53 manjaro systemd[1]: Finished Losetup LXD Storage Pool (hddpool).

Från utgången kan vi verifiera att servicetillståndet är aktiv, trots att exekveringen av vårt skript från ett kommando slutfördes, tillät alternativet oss att göra detta RemainAfterExit=true.

Säkerhet. Containerprivilegier ^

Eftersom alla containerprocesser faktiskt körs isolerat på värdsystemet med dess kärna, för att ytterligare skydda åtkomsten av containerprocesser till värdsystemet, erbjuder LXD processprivilegier, där:

  • Privilegerade containrar - det här är behållare där processer med UID och GID motsvarar samma ägare som på värdsystemet. Till exempel har en process som körs i en behållare med ett UID på 0 samma åtkomsträttigheter som en process på värdsystemet med ett UID på 0. Med andra ord har rotanvändaren i behållaren alla rättigheter inte bara i containern, men även på värdsystemet om han kan gå utanför containerns isolerade namnområde.

  • Oprivilegierade containrar - dessa är behållare i vilka processer tillhör ägaren av UID och GID med ett nummer från 0 till 65535, men för värdsystemet är ägaren maskerad med hjälp av de tillagda SubUID- respektive SubGID-bitarna. Till exempel kommer en användare med UID=0 i en behållare att ses på värdsystemet som SubUID + UID. Detta skyddar värdsystemet eftersom om någon process i behållaren kan undkomma sitt isolerade namnområde, kan den bara kommunicera med värdsystemet som en process med en okänd, mycket hög UID/GID.

Som standard har nyskapade behållare en oprivilegierad status och därför måste vi definiera ett SubUID och SubGID.

Låt oss skapa två konfigurationsfiler där vi kommer att ställa in masken för SubUID respektive SubGID:

sudo touch /etc{/subuid,/subgid}
sudo usermod --add-subuids 1000000-1065535 root 
sudo usermod --add-subgids 1000000-1065535 root

För att tillämpa ändringarna måste LXD-tjänsten startas om:

sudo systemctl restart lxd

Skapa en virtuell nätverksswitch ^

Eftersom vi tidigare initierade nätverket med hjälp av initialiseringsguiden lxd init och skapade en nätverksenhet lxdbr0, sedan i det här avsnittet kommer vi helt enkelt att bekanta oss med nätverk i LXD och hur man skapar en virtuell switch (brygga) med klientkommandot.

Följande diagram visar hur en switch (brygga) ansluter värden och behållarna till ett nätverk:

Grundläggande funktioner i LXD - Linux containersystem

Behållare kan kommunicera via ett nätverk med andra behållare eller den värd som dessa behållare serveras på. För att göra detta måste du länka behållarnas virtuella nätverkskort med en virtuell switch. Vi skapar en switch först, och containerns nätverksgränssnitt kommer att länkas i efterföljande kapitel, efter att själva containern har skapats.

Följande kommando skapar en switch med ett subnät 10.0.5.0/24 och IPv4-adress 10.0.5.1/24, och inkluderar även ipv4.nat så att behållare kan komma åt Internet via värden med hjälp av NAT-tjänsten:

lxc network create lxdbr0 ipv4.address=10.0.5.1/24 ipv4.nat=true ipv6.address=none

Kontrollera listan över tillgängliga nätverksenheter i LXD:

lxc network list

+--------+----------+---------+-------------+---------+
|  NAME  |   TYPE   | MANAGED | DESCRIPTION | USED BY |
+--------+----------+---------+-------------+---------+
| eno1   | physical | NO      |             | 0       |
+--------+----------+---------+-------------+---------+
| lxdbr0 | bridge   | YES     |             | 0       |
+--------+----------+---------+-------------+---------+

Du kan också verifiera att en nätverksenhet har skapats med standardverktyget för Linux-distributionen - ip link eller ip addr:

ip addr

1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
2: eno1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
    link/ether bc:ee:7b:5a:6b:44 brd ff:ff:ff:ff:ff:ff
    altname enp0s25
    inet6 fe80::9571:11f3:6e0c:c07b/64 scope link noprefixroute 
       valid_lft forever preferred_lft forever
3: lxdbr0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
    link/ether c2:38:90:df:cb:59 brd ff:ff:ff:ff:ff:ff
    inet 10.0.5.1/24 scope global lxdbr0
       valid_lft forever preferred_lft forever
    inet6 fe80::c038:90ff:fedf:cb59/64 scope link 
       valid_lft forever preferred_lft forever
5: veth3ddab174@if4: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master lxdbr0 state UP group default qlen 1000
    link/ether ca:c3:5c:1d:22:26 brd ff:ff:ff:ff:ff:ff link-netnsid 0

Konfigurationsprofil ^

Varje container i LXD har sin egen konfiguration och kan utöka den med globalt deklarerade konfigurationer som kallas konfigurationsprofiler. Att tillämpa konfigurationsprofiler på en behållare har en kaskadmodell, följande exempel visar detta:

Grundläggande funktioner i LXD - Linux containersystem

I det här exemplet har tre profiler skapats i LXD-systemet: default, hddpool и hostfs. Alla tre profilerna appliceras på en behållare som har en lokal konfiguration (grå område). Profil default har en enhet root som har en parameter pool lika ssdpool, men tack vare applikationsmodellen för kaskadkonfiguration kan vi tillämpa en profil på behållaren hddpool som har en parameter pool kommer att åsidosätta samma parameter från profilen default och behållaren kommer att ta emot enhetskonfigurationen root med parameter pool lika hddpooloch profilen hostfs lägger helt enkelt till en ny enhet i behållaren.

För att se listan över tillgängliga konfigurationsprofiler, använd följande kommando:

lxc profile list

+---------+---------+
|  NAME   | USED BY |
+---------+---------+
| default | 1       |
+---------+---------+
| hddroot | 0       |
+---------+---------+
| ssdroot | 1       |
+---------+---------+

En komplett lista över tillgängliga kommandon för att arbeta med en profil kan erhållas genom att lägga till nyckeln --help:

lxc profile --help

Description:
  Manage profiles

Usage:
  lxc profile [command]

Available Commands:
  add         Add profiles to instances
  assign      Assign sets of profiles to instances
  copy        Copy profiles
  create      Create profiles
  delete      Delete profiles
  device      Manage instance devices
  edit        Edit profile configurations as YAML
  get         Get values for profile configuration keys
  list        List profiles
  remove      Remove profiles from instances
  rename      Rename profiles
  set         Set profile configuration keys
  show        Show profile configurations
  unset       Unset profile configuration keys

Redigera din profil ^

Standardkonfigurationsprofil default har ingen nätverkskortskonfiguration för behållaren och alla nyskapade behållare har inte ett nätverk, för dem är det nödvändigt att skapa lokala (dedikerade) nätverksenheter med ett separat kommando, men vi kan skapa en global nätverksenhet i konfigurationen profil som kommer att delas mellan alla behållare som använder den här profilen. På så sätt, omedelbart efter kommandot för att skapa en ny behållare, kommer de att ha ett nätverk med nätverksåtkomst. Samtidigt finns det inga begränsningar, vi kan alltid skapa en lokal nätverksenhet senare om det behövs.

Följande kommando lägger till enheten i konfigurationsprofilen eth0 типа nic ansluten till nätverket lxdbr0:

lxc profile device add default eth0 nic network=lxdbr0 name=eth0

Det är viktigt att notera att eftersom vi faktiskt har lagt till enheten i konfigurationsprofilen, om vi angav en statisk IP-adress i enheten, kommer alla behållare som kommer att använda den här profilen att dela samma IP-adress. Om det finns ett behov av att skapa en container med en statisk IP-adress tilldelad för containern, bör du skapa en nätverksenhetskonfiguration på containernivå (lokal konfiguration) med IP-adressparametern och inte på profilnivå.

Låt oss kolla profilen:

lxc profile show default

config: {}
description: Default LXD profile
devices:
  eth0:
    name: eth0
    network: lxdbr0
    type: nic
  root:
    path: /
    pool: ssdpool
    type: disk
name: default
used_by: []

I den här profilen kan vi se att för alla nyskapade behållare kommer två enheter att skapas:

  • eth0 - Enhetstyp nic ansluten till en switch (nätverksbrygga) lxdbr0
  • root - Enhetstyp disk som använder en förvaringspool ssdpool

Skapa nya profiler ^

För att använda tidigare skapade Förvaringspool behållare, skapa en konfigurationsprofil ssdroot där vi kommer att lägga till en enhet som disk med monteringspunkt / (root) med den tidigare skapade Förvaringspool - ssdpool:

lxc profile create ssdroot
lxc profile device add ssdroot root disk path=/ pool=ssdpool

På samma sätt skapar vi en enhet som disk, men i det här fallet använder du Förvaringspool - hddpool:

lxc profile create hddroot
lxc profile device add hddroot root disk path=/ pool=hddpool

Kontrollera konfigurationsprofiler:

lxc profile show ssdroot

config: {}
description: ""
devices:
  root:
    path: /
    pool: ssdpool
    type: disk
name: ssdroot
used_by: []

lxc profile show hddroot

config: {}
description: ""
devices:
  root:
    path: /
    pool: hddpool
    type: disk
name: hddroot
used_by: []

Bildförråd ^

Behållare skapas från bilder som är speciellt sammansatta distributioner som inte har en Linux-kärna. Innan behållaren körs måste den därför distribueras från den här bilden. Källan till bilder är ett lokalt arkiv till vilket bilder laddas ner från externa arkiv.

Fjärrstyrda bildarkiv ^

Som standard är LXD konfigurerad för att ta emot bilder från tre fjärrkällor:

  • ubuntu: (för stabila Ubuntu-bilder)
  • ubuntu-dagligen: (för dagliga Ubuntu-bilder)
  • bilder: (för ett gäng andra distros)

lxc remote list

+-----------------+------------------------------------------+--------+--------+
|      NAME       |                   URL                    | PUBLIC | STATIC |
+-----------------+------------------------------------------+--------+--------+
| images          | https://images.linuxcontainers.org       | YES    | NO     |
+-----------------+------------------------------------------+--------+--------+
| local (default) | unix://                                  | NO     | YES    |
+-----------------+------------------------------------------+--------+--------+
| ubuntu          | https://cloud-images.ubuntu.com/releases | YES    | YES    |
+-----------------+------------------------------------------+--------+--------+
| ubuntu-daily    | https://cloud-images.ubuntu.com/daily    | YES    | YES    |
+-----------------+------------------------------------------+--------+--------+

Till exempel förråd ubuntu: har följande bilder:

lxc image -c dasut list ubuntu: | head -n 11

+----------------------------------------------+--------------+----------+------------+
|                   DESCRIPTION                | ARCHITECTURE |   SIZE   |   TYPE     |
+----------------------------------------------+--------------+----------+------------+
| ubuntu 12.04 LTS amd64 (release) (20150728)  | x86_64       | 153.72MB | CONTAINER  |
+----------------------------------------------+--------------+----------+------------+
| ubuntu 12.04 LTS amd64 (release) (20150819)  | x86_64       | 152.91MB | CONTAINER  |
+----------------------------------------------+--------------+----------+------------+
| ubuntu 12.04 LTS amd64 (release) (20150906)  | x86_64       | 154.69MB | CONTAINER  |
+----------------------------------------------+--------------+----------+------------+
| ubuntu 12.04 LTS amd64 (release) (20150930)  | x86_64       | 153.86MB | CONTAINER  |
+----------------------------------------------+--------------+----------+------------+

För att visa ett begränsat antal kolumner använde vi alternativet -c med parametrar dasut, och begränsade även längden på listan med kommandot head.

Filtrering är tillgänglig för att visa en lista med bilder. Följande kommando kommer att lista alla tillgängliga distributionsarkitekturer AlpineLinux:

lxc image -c ldast list images:alpine/3.11

+------------------------------+--------------------------------------+--------------+
|            ALIAS             |             DESCRIPTION              | ARCHITECTURE |
+------------------------------+--------------------------------------+--------------+
| alpine/3.11 (3 more)         | Alpine 3.11 amd64 (20200220_13:00)   | x86_64       |
+------------------------------+--------------------------------------+--------------+
| alpine/3.11/arm64 (1 more)   | Alpine 3.11 arm64 (20200220_13:00)   | aarch64      |
+------------------------------+--------------------------------------+--------------+
| alpine/3.11/armhf (1 more)   | Alpine 3.11 armhf (20200220_13:00)   | armv7l       |
+------------------------------+--------------------------------------+--------------+
| alpine/3.11/i386 (1 more)    | Alpine 3.11 i386 (20200220_13:01)    | i686         |
+------------------------------+--------------------------------------+--------------+
| alpine/3.11/ppc64el (1 more) | Alpine 3.11 ppc64el (20200220_13:00) | ppc64le      |
+------------------------------+--------------------------------------+--------------+
| alpine/3.11/s390x (1 more)   | Alpine 3.11 s390x (20200220_13:00)   | s390x        |
+------------------------------+--------------------------------------+--------------+

Lokalt bildarkiv ^

För att börja använda behållaren måste du lägga till en bild från det globala arkivet till det lokala local:. Nu är det lokala förvaret tomt, kommandot ser till detta lxc image list. Om metoden list ange inte ett arkiv, då kommer det lokala arkivet att användas som standard - local:

lxc image list local:

+-------+-------------+--------+-------------+--------------+------+------+
| ALIAS | FINGERPRINT | PUBLIC | DESCRIPTION | ARCHITECTURE | TYPE | SIZE |
+-------+-------------+--------+-------------+--------------+------+------+

Bilder i arkivet hanteras med följande metoder:

Team
beskrivning

lxc bild alias
Hantera bildalias

lxc bild kopiera
Kopiera bilder mellan servrar

lxc bild radera
Ta bort bilder

lxc bild redigera
Redigera bildegenskaper

lxc bild export
Exportera och ladda ner bilder

lxc bild importera
Importera bilder till bildarkivet

lxc bild info
Visa användbar information om bilder

lxc bild lista
Lista bilder

lxc bild refresh
Uppdatera bilder

lxc bild show
Visa bildegenskaper

Kopiera bilden till det lokala arkivet från det globala images::

lxc image copy images:alpine/3.11/amd64 local: --alias=alpine3

Image copied successfully!

Låt oss visa en lista över alla bilder som för närvarande är tillgängliga i det lokala arkivet local::

lxc image -c lfdatsu list local:

+---------+--------------+------------------------------------+--------------+
|  ALIAS  | FINGERPRINT  |            DESCRIPTION             | ARCHITECTURE |
+---------+--------------+------------------------------------+--------------+
| alpine3 | 73a3093d4a5c | Alpine 3.11 amd64 (20200220_13:00) | x86_64       |
+---------+--------------+------------------------------------+--------------+

LXD-konfiguration ^

Utöver det interaktiva läget stöder LXD också ett icke-interaktivt konfigurationsinstallationsläge, detta är när konfigurationen specificeras i form av en YAML-fil, ett speciellt format som låter dig installera hela konfigurationen på en gång, förbi körningen av många interaktiva kommandon som diskuterades ovan i den här artikeln, inklusive nätverkskonfiguration, skapande av konfigurationsprofiler, etc. Vi kommer inte att täcka detta område här, du kan kolla upp det på egen hand. i dokumentation.

Nästa interaktiva kommando lxc config som vi kommer att titta på låter dig ställa in konfigurationen. Till exempel, för att säkerställa att nedladdade bilder till det lokala arkivet inte uppdateras automatiskt från de globala arkiven, kan vi aktivera detta beteende med följande kommando:

lxc config set images.auto_update_cached=false

Skapa och hantera en container ^

Använd kommandot för att skapa en behållare lxc init till vilka värden överförs репозиторий:образ och sedan önskat ID för behållaren. Förvaret kan anges som lokalt local: så är alla globala. Om arkivet inte är specificerat används som standard det lokala arkivet för att söka efter bilden. Om bilden specificeras från det globala arkivet kommer bilden först att laddas ner till det lokala arkivet och sedan användas för att skapa behållaren.

Låt oss köra följande kommando för att skapa vår första behållare:

lxc init alpine3 alp --storage=hddpool --profile=default --profile=hddroot

Låt oss titta på kommandonycklarna som vi använder här i ordning:

  • alpine3 — Ett alias (alias) specificeras för bilden som tidigare laddades upp till det lokala arkivet. Om aliaset inte skapades för den här bilden kan du alltid referera till bilden med dess Fingeravtryck som visas i tabellen.
  • alp — Ställer in identifieraren för behållaren
  • --storage — Den här knappen indikerar i vilken Förvaringspool en behållare kommer att skapas
  • --profile — Dessa nycklar tillämpar konfiguration från tidigare skapade konfigurationsprofiler på behållaren

Vi lanserar behållaren, som börjar lansera init-systemet för distributionen:

lxc start alp

Du kan också använda kommandot lxc launch som gör att du kan kombinera lag lxc init и lxc start i en operation.

Kontrollera behållarens tillstånd:

lxc list -c ns46tb
+------+---------+------------------+------+-----------+--------------+
| NAME |  STATE  |       IPV4       | IPV6 |   TYPE    | STORAGE POOL |
+------+---------+------------------+------+-----------+--------------+
| alp  | RUNNING | 10.0.5.46 (eth0) |      | CONTAINER | hddpool      |
+------+---------+------------------+------+-----------+--------------+

Kontrollera behållarkonfigurationen:

lxc config show alp

architecture: x86_64
config:
  image.architecture: amd64
  image.description: Alpine 3.11 amd64 (20200326_13:39)
  image.os: Alpine
  image.release: "3.11"
  image.serial: "20200326_13:39"
  image.type: squashfs
  volatile.base_image: ebd565585223487526ddb3607f5156e875c15a89e21b61ef004132196da6a0a3
  volatile.eth0.host_name: vethb1fe71d8
  volatile.eth0.hwaddr: 00:16:3e:5f:73:3e
  volatile.idmap.base: "0"
  volatile.idmap.current: '[{"Isuid":true,"Isgid":false,"Hostid":1000000,"Nsid":0,"Maprange":65536},{"Isuid":false,"Isgid":true,"Hostid":1000000,"Nsid":0,"Maprange":65536}]'
  volatile.idmap.next: '[{"Isuid":true,"Isgid":false,"Hostid":1000000,"Nsid":0,"Maprange":65536},{"Isuid":false,"Isgid":true,"Hostid":1000000,"Nsid":0,"Maprange":65536}]'
  volatile.last_state.idmap: '[{"Isuid":true,"Isgid":false,"Hostid":1000000,"Nsid":0,"Maprange":65536},{"Isuid":false,"Isgid":true,"Hostid":1000000,"Nsid":0,"Maprange":65536}]'
  volatile.last_state.power: RUNNING
devices:
  root:
    path: /
    pool: hddpool
    type: disk
ephemeral: false
profiles:
- default
- hddroot
stateful: false
description: ""

I avsnittet profiles vi kan se till att den här behållaren använder två konfigurationsprofiler − default и hddroot. I avsnitt devices vi kan bara upptäcka en enhet eftersom nätverksenheten skapades på profilnivå default. För att se alla enheter som används av behållaren måste du lägga till en nyckel --expanded:

lxc config show alp --expanded

architecture: x86_64
config:
  image.architecture: amd64
  image.description: Alpine 3.11 amd64 (20200326_13:39)
  image.os: Alpine
  image.release: "3.11"
  image.serial: "20200326_13:39"
  image.type: squashfs
  volatile.base_image: ebd565585223487526ddb3607f5156e875c15a89e21b61ef004132196da6a0a3
  volatile.eth0.host_name: vethb1fe71d8
  volatile.eth0.hwaddr: 00:16:3e:5f:73:3e
  volatile.idmap.base: "0"
  volatile.idmap.current: '[{"Isuid":true,"Isgid":false,"Hostid":1000000,"Nsid":0,"Maprange":65536},{"Isuid":false,"Isgid":true,"Hostid":1000000,"Nsid":0,"Maprange":65536}]'
  volatile.idmap.next: '[{"Isuid":true,"Isgid":false,"Hostid":1000000,"Nsid":0,"Maprange":65536},{"Isuid":false,"Isgid":true,"Hostid":1000000,"Nsid":0,"Maprange":65536}]'
  volatile.last_state.idmap: '[{"Isuid":true,"Isgid":false,"Hostid":1000000,"Nsid":0,"Maprange":65536},{"Isuid":false,"Isgid":true,"Hostid":1000000,"Nsid":0,"Maprange":65536}]'
  volatile.last_state.power: RUNNING
devices:
  eth0:
    name: eth0
    network: lxdbr0
    type: nic
  root:
    path: /
    pool: hddpool
    type: disk
ephemeral: false
profiles:
- default
- hddroot
stateful: false
description: ""

Ställa in en statisk IP-adress ^

Om vi ​​försöker ställa in en IP-adress för en nätverksenhet eth0 team lxc config device set alp avsedd för containerkonfigurationen kommer vi att få ett felmeddelande som rapporterar att enheten inte finns eftersom enheten eth0 som används av behållaren tillhör profilen default:

lxc config device set alp eth0 ipv4.address 10.0.5.5

Error: The device doesn't exist

Vi kan givetvis ställa in en statisk IP-adress för eth0 enheter i profilen, men det kommer att vara samma för alla behållare som kommer att använda den här profilen. Låt oss därför lägga till en enhet dedikerad till behållaren:

lxc config device add alp eth0 nic name=eth0 nictype=bridged parent=lxdbr0 ipv4.address=10.0.5.5

Sedan måste du starta om behållaren:

lxc restart alp

Om vi ​​tittar på containerkonfigurationen nu behöver vi inte använda alternativet --expanded för att se nätverksenheten eth0, eftersom vi skapade den på behållarnivå och den gick över samma enhet från profilen default:

lxc config show alp

architecture: x86_64
config:
  image.architecture: amd64
  image.description: Alpine 3.11 amd64 (20200326_13:39)
  image.os: Alpine
  image.release: "3.11"
  image.serial: "20200326_13:39"
  image.type: squashfs
  volatile.base_image: ebd565585223487526ddb3607f5156e875c15a89e21b61ef004132196da6a0a3
  volatile.eth0.host_name: veth2a1dc59d
  volatile.eth0.hwaddr: 00:16:3e:0e:e2:71
  volatile.idmap.base: "0"
  volatile.idmap.current: '[{"Isuid":true,"Isgid":false,"Hostid":1000000,"Nsid":0,"Maprange":65536},{"Isuid":false,"Isgid":true,"Hostid":1000000,"Nsid":0,"Maprange":65536}]'
  volatile.idmap.next: '[{"Isuid":true,"Isgid":false,"Hostid":1000000,"Nsid":0,"Maprange":65536},{"Isuid":false,"Isgid":true,"Hostid":1000000,"Nsid":0,"Maprange":65536}]'
  volatile.last_state.idmap: '[{"Isuid":true,"Isgid":false,"Hostid":1000000,"Nsid":0,"Maprange":65536},{"Isuid":false,"Isgid":true,"Hostid":1000000,"Nsid":0,"Maprange":65536}]'
  volatile.last_state.power: RUNNING
devices:
  eth0:
    ipv4.address: 10.0.5.5
    name: eth0
    nictype: bridged
    parent: lxdbr0
    type: nic
  root:
    path: /
    pool: hddpool
    type: disk
ephemeral: false
profiles:
- default
- hddroot
stateful: false
description: ""

Ta bort en behållare ^

För att ta bort en behållare, använd kommandot lxc delete, men innan du tar bort behållaren måste den stoppas med kommandot lxc stop:

lxc stop alp

lxc list

+------+---------+-------------------+------+-----------+-----------+
| NAME |  STATE  |       IPV4        | IPV6 |   TYPE    | SNAPSHOTS |
+------+---------+-------------------+------+-----------+-----------+
| alp  | STOPPED | 10.0.5.10 (eth0)  |      | CONTAINER | 0         |
+------+---------+-------------------+------+-----------+-----------+

Efter att vi har verifierat att containerns tillstånd har blivit STOPPAD, kan den tas bort från Förvaringspool:

lxc delete alp

Tillgång till container ^

För att köra kommandon i en behållare direkt, förbi nätverksanslutningar, använd kommandot lxc exec som kör kommandon i behållaren utan att starta systemskalet. Om du behöver köra ett kommando i ett skal med hjälp av skalmönster som variabler, filomdirigeringar (pipe), etc., måste du explicit starta skalet och skicka kommandot som en nyckel, till exempel:

lxc exec alp -- /bin/sh -c "echo $HOME"

Kommandot använde ett speciellt escape-tecken för speciell karaktär $ så att variabeln $HOME tolkades inte på värddatorn, utan tolkades endast inuti behållaren.

Det är också möjligt att starta det interaktiva skalläget och sedan avsluta sessionen genom att köra snabbtangenten CTRL+D:

lxc exec alp -- /bin/sh

Container resurshantering ^

I LXD kan du hantera containerresurser med en speciell uppsättning konfigurationer. En komplett lista över containerkonfigurationsparametrar finns i dokumentation.

RAM-resursbegränsning ^

Parameter limits.memory begränsar mängden RAM tillgängligt för behållaren. Värdet är ett nummer och ett av tillgängliga suffix.

Låt oss ställa in behållarens RAM-gräns till 256 MB:

lxc config set alp limits.memory 256MB

Det finns också andra parametrar för att begränsa minnet:

  • limits.memory.enforce
  • limits.memory.hugepages
  • limits.memory.swap
  • limits.memory.swap.priority

Team lxc config show låter dig visa hela behållarkonfigurationen, inklusive den tillämpade resursgränsen som ställts in:

lxc config show alp

architecture: x86_64
config:
  image.architecture: amd64
  image.description: Alpine 3.11 amd64 (20200220_13:00)
  image.os: Alpine
  image.release: "3.11"
  image.serial: "20200220_13:00"
  image.type: squashfs
  limits.memory: 256MB
  volatile.base_image: 73a3093d4a5ce0148fd84b95369b3fbecd19a537ddfd2e2d20caa2eef0e8fd60
  volatile.eth0.host_name: veth75b6df07
  volatile.eth0.hwaddr: 00:16:3e:a1:e7:46
  volatile.idmap.base: "0"
  volatile.idmap.current: '[]'
  volatile.idmap.next: '[]'
  volatile.last_state.idmap: '[]'
  volatile.last_state.power: RUNNING
devices: {}
ephemeral: false
profiles:
- default
stateful: false
description: ""

CPU-resursgräns ^

Det finns flera sätt att begränsa CPU-resurser. typer av begränsningar:

  • limit.cpu - binder en behållare till en eller flera CPU-kärnor
  • limits.cpu.allowance - hanterar antingen CFS-schemaläggarens kvoter när tidsgränsen har passerat, eller den universella CPU-resursdelningsmekanismen när procenten har passerat
  • limits.cpu.priority - schemaläggarprioritet när flera instanser som delar en uppsättning processorer tilldelas samma procentandel processorer

lxc config set alp limits.cpu.allowance 40%

lxc config show alp

architecture: x86_64
config:
  image.architecture: amd64
  image.description: Alpine 3.11 amd64 (20200220_13:00)
  image.os: Alpine
  image.release: "3.11"
  image.serial: "20200220_13:00"
  image.type: squashfs
  limits.cpu.allowance: 40%
  limits.memory: 256MB
  volatile.base_image: 73a3093d4a5ce0148fd84b95369b3fbecd19a537ddfd2e2d20caa2eef0e8fd60
  volatile.eth0.host_name: veth75b6df07
  volatile.eth0.hwaddr: 00:16:3e:a1:e7:46
  volatile.idmap.base: "0"
  volatile.idmap.current: '[]'
  volatile.idmap.next: '[]'
  volatile.last_state.idmap: '[]'
  volatile.last_state.power: RUNNING
devices: {}
ephemeral: false
profiles:
- default
stateful: false
description: ""

Diskutrymmesbegränsning ^

Förutom restriktioner som t.ex limits.read, limits.write vi kan också begränsa mängden diskutrymme som konsumeras av behållaren (fungerar bara med ZFS eller BTRFS):

lxc config device set alp root size=2GB

Efter installationen, i parametern devices.root.size Vi kan verifiera den inställda gränsen:

lxc config show alp
...
devices:
  root:
    path: /
    pool: hddpool
    size: 2GB
    type: disk
ephemeral: false
profiles:
- default
- hddroot
stateful: false
description: ""

För att se de använda diskkvoterna kan vi få från kommandot lxc info:

lxc info alp
...
Resources:
  Processes: 5
  Disk usage:
    root: 1.05GB
  CPU usage:
    CPU usage (in seconds): 1
  Memory usage:
    Memory (current): 5.46MB
  Network usage:
    eth0:
      Bytes received: 802B
      Bytes sent: 1.59kB
      Packets received: 4
      Packets sent: 14
    lo:
      Bytes received: 0B
      Bytes sent: 0B
      Packets received: 0
      Packets sent: 0

Trots att vi har satt en gräns för containerns rotenhet till 2GB, systemverktyg som t.ex. df kommer inte att se denna begränsning. För att göra detta kommer vi att göra ett litet test och ta reda på hur det fungerar.

Låt oss skapa 2 nya identiska behållare i samma Förvaringspool (hddpool):

lxc init alpine3 alp1 --storage=hddpool --profile=default --profile=hddroot
lxc init alpine3 alp2 --storage=hddpool --profile=default --profile=hddroot

lxc list
+------+---------+------------------+------+-----------+-----------+
| NAME |  STATE  |       IPV4       | IPV6 |   TYPE    | SNAPSHOTS |
+------+---------+------------------+------+-----------+-----------+
| alp1 | RUNNING | 10.0.5.46 (eth0) |      | CONTAINER | 0         |
+------+---------+------------------+------+-----------+-----------+
| alp2 | RUNNING | 10.0.5.30 (eth0) |      | CONTAINER | 0         |
+------+---------+------------------+------+-----------+-----------+

Låt oss skapa en 1GB-fil i en av behållarna:

lxc exec alp1 -- dd if=/dev/urandom of=file.img bs=1M count=1000

Låt oss se till att filen skapas:

lxc exec alp1 -- ls -lh
total 1000M  
-rw-r--r--    1 root     root     1000.0M Mar 27 10:16 file.img

Om vi ​​tittar i den andra behållaren, kontrollera om det finns en fil på samma plats, då kommer den här filen inte att finnas där, vilket förväntas, eftersom behållare skapas i sina egna Lagringsvolym i samma Förvaringspool:

lxc exec alp2 -- ls -lh
total 0

Men låt oss jämföra de värden den producerar df på den ena och den andra behållaren:

lxc exec alp1 -- df -hT
Filesystem           Type            Size      Used Available Use% Mounted on
/dev/loop1           btrfs           9.3G   1016.4M      7.8G  11% /
...

lxc exec alp2 -- df -hT
Filesystem           Type            Size      Used Available Use% Mounted on
/dev/loop1           btrfs           9.3G   1016.4M      7.8G  11% /
...

anordning /dev/loop1 monterad som rotpartitionen är Förvaringspool som dessa behållare använder, så de delar dess volym mellan två.

Resursförbrukningsstatistik ^

Du kan se resursförbrukningsstatistik för en behållare med kommandot:

lxc info alp

Name: alp
Location: none
Remote: unix://
Architecture: x86_64
Created: 2020/04/08 18:05 UTC
Status: Running
Type: container
Profiles: default, hddroot
Pid: 19219
Ips:
  eth0: inet    10.0.5.5        veth2a1dc59d
  eth0: inet6   fe80::216:3eff:fe0e:e271        veth2a1dc59d
  lo:   inet    127.0.0.1
  lo:   inet6   ::1
Resources:
  Processes: 5
  Disk usage:
    root: 495.62kB
  CPU usage:
    CPU usage (in seconds): 1
  Memory usage:
    Memory (current): 4.79MB
  Network usage:
    eth0:
      Bytes received: 730B
      Bytes sent: 1.59kB
      Packets received: 3
      Packets sent: 14
    lo:
      Bytes received: 0B
      Bytes sent: 0B
      Packets received: 0
      Packets sent: 0

Arbeta med ögonblicksbilder ^

LXD har förmågan att skapa ögonblicksbilder och återställa behållartillståndet från dem.

För att skapa en ögonblicksbild, kör följande kommando:

lxc snapshot alp snapshot1

Laget lxc snapshot ingen nyckel tillgänglig list, därför, för att se listan över ögonblicksbilder måste du använda kommandot som visar allmän information om behållaren:

lxc info alp
...
...
Snapshots:
  snapshot1 (taken at 2020/04/08 18:18 UTC) (stateless)

Du kan återställa en behållare från en ögonblicksbild med kommandot lxc restore anger behållaren för vilken återställningen ska utföras och ögonblicksbildaliaset:

lxc restore alp snapshot1

Följande kommando används för att radera en ögonblicksbild. Observera att kommandosyntaxen inte liknar alla andra; här måste du ange ett snedstreck efter behållarens namn. Om snedstrecket utelämnas tolkas kommandot för att ta bort en ögonblicksbild som ett kommando för att ta bort en behållare!

lxc delete alp/snapshot1

I exemplet ovan tittade vi på så kallade statslösa ögonblicksbilder. LXD har en annan typ av ögonblicksbilder - stateful, som sparar det aktuella tillståndet för alla processer i behållaren. Det finns ett antal intressanta och användbara funktioner förknippade med statistiska ögonblicksbilder.

Vad annars? ^

  • En modul är tillgänglig för Python-utvecklare PyLXD som tillhandahåller ett API till LXD

UPPDATERING 10.04.2020/15/00 XNUMX:XNUMX: Lade till navigering

Källa: will.com

Lägg en kommentar