Базові можливості LXD - системи контейнерів у Linux
LXD - Це системний менеджер контейнерів наступного покоління, так говорить джерело. Він пропонує інтерфейс користувача, схожий на віртуальні машини, але використовує натомість контейнери Linux.
Ядро LXD — це привілейований демон (сервіс запущений з правами root), який надає REST API через локальний сокет unix, а також через мережу, якщо встановлена відповідна конфігурація. Клієнти, такі як інструмент командного рядка, що поставляється з LXD, посилають запити через цей REST API. Це означає, що незалежно від того, чи звертаєтесь ви до локального хоста або до віддаленого, все працює однаково.
У цій статті ми не будемо докладно зупинятися на концепціях LXD, не розглядатимемо всі доступні можливості, викладені в документації, в тому числі нещодавню реалізацію в останніх версіях LXD підтримки віртуальних машин QEMU паралельно з контейнерами. Натомість ми дізнаємося лише базові можливості управління контейнерами — налаштуємо пули сховищ, мережу, запустимо контейнер, застосуємо ліміти на ресурси, а також розглянемо як використовувати снепшоти, щоб ви змогли отримати базове уявлення про LXD та використовувати контейнери в Linux.
Для отримання повної інформації слід звернутися до офіційного джерела:
Це означає, що буде встановлено відразу два пакети, один системний, а інший як snap-пакет. Встановлення двох пакетів у системі може створити деяку проблему, коли системний пакет може стати сиротою, якщо видалити snap-пакет менеджером snap-пакетів.
Знайти пакет lxd у snap-репозиторії можна наступною командою:
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
Запустивши команду list можна переконатися, що пакет lxd ще не встановлено:
snap list
Name Version Rev Tracking Publisher Notes
core 16-2.43.3 8689 stable canonical✓ core
Незважаючи на те, що LXD є snap-пакетом, потрібно встановлювати його через системний пакет. lxd, який створить у системі відповідну групу, необхідні утиліти в /usr/bin тощо.
sudo apt update
sudo apt install lxd
Переконайтеся, що пакет встановлений як snap-пакет:
snap list
Name Version Rev Tracking Publisher Notes
core 16-2.43.3 8689 stable canonical✓ core
lxd 3.21 13474 stable/… canonical✓ -
Для встановлення пакета LXD у системі необхідно запустити наступні команди, перша — актуалізує список пакетів у системі доступних у репозиторії, друга — безпосередньо встановить пакет:
sudo pacman -Syyu && sudo pacman -S lxd
Після встановлення пакета, для керування LXD звичайним користувачем, його необхідно додати до системної групи lxd:
sudo usermod -a -G lxd user1
Переконаємося, що користувач user1 доданий до групи lxd:
id -Gn user1
user1 adm dialout cdrom floppy sudo audio dip video plugdev netdev lxd
Якщо група lxd не видно у списку, тоді потрібно активувати сесію користувача заново. Для цього потрібно вийти і зайти в систему під цим користувачем.
Активуємо у systemd завантаження сервісу LXD при старті системи:
До початку ініціалізації нам необхідно розібратися як логічно влаштоване сховище в LXD.
Сховище (зберігання) складається з одного чи кількох Пул зберігання який використовує одну з підтримуваних файлових систем, таких як ZFS, BTRFS, LVM або звичайні директорії. Кожен Пул зберігання поділяється на томи (Обсяг зберігання) які містять образи, контейнери або дані для інших цілей.
образи — це спеціально зібрані дистрибутиви без ядра Linux та доступні із зовнішніх джерел.
контейнери - це розгорнуті дистрибутиви з образів, готові до експлуатації
Сніпшоти — це знімки стану контейнерів, до яких можна повертатися.
Для управління сховищем у LXD служить команда lxc storage довідку за якою можна отримати вказавши ключ. lxc storage --help
Наступна команда виводить на екран список усіх Пул зберігання в LXD сховище:
lxc storage list
+---------+-------------+--------+--------------------------------+---------+
| NAME | DESCRIPTION | DRIVER | SOURCE | USED BY |
+---------+-------------+--------+--------------------------------+---------+
| hddpool | | btrfs | /dev/loop1 | 2 |
+---------+-------------+--------+--------------------------------+---------+
| ssdpool | | btrfs | /var/lib/lxd/disks/ssdpool.img | 4 |
+---------+-------------+--------+--------------------------------+---------+
Для перегляду списку всіх Обсяг зберігання у вибраному Пул зберігання служить команда 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 |
+-----------+----------------------------------+-------------+---------+
Також, якщо для Пул зберігання при створенні була обрана файлова система BTRFS, то отримати список Обсяг зберігання або підпункти в інтерпретації BTRFS можна за допомогою інструментарію цієї файлової системи:
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
Перед створенням та використанням контейнерів необхідно виконати загальну ініціалізацію LXD, яка створює та налаштовує мережу, а також сховище. Це можна зробити вручну за допомогою стандартних команд клієнта, які доступні у списку за викликом команди lxc --help або за допомогою майстра ініціалізації lxd init відповівши на кілька запитань.
Під час ініціалізації LXD ставить кілька питань, серед яких буде визначення типу файлової системи для дефолтного Пул зберігання. За промовчанням для нього вибирається файлова система BTRFS. Поміняти на іншу ФС після створення буде неможливо. Для вибору ФС пропонується таблиця порівняння можливостей:
особливість
Каталог
Btrfs
НВМ
ZFS
CEPH
Optimized image storage
немає
так
так
так
так
Optimized instance creation
немає
так
так
так
так
Optimized snapshot creation
немає
так
так
так
так
Optimized image transfer
немає
так
немає
так
так
Optimized instance transfer
немає
так
немає
так
так
Копіювати на запис
немає
так
так
так
так
Block based
немає
немає
так
немає
так
Instant cloning
немає
так
так
так
так
Storage driver usable inside a container
так
так
немає
немає
немає
Restore from older snapshots (not latest)
так
так
так
немає
так
Storage quotas
yes(*)
так
так
так
немає
Ініціалізація мережі та Storage Pool за допомогою майстра ^
Наступна команада, яку ми розглянемо, пропонує налаштувати основні компоненти LXD відповідями на прості питання за допомогою майстра ініціалізації.
Запустіть команду lxc 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]: 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]:
У попередньому кроці ми створили Пул зберігання якому дали назву ssdpool і файл якого розташувався у моїй системі за адресою /var/lib/lxd/disks/ssdpool.img. Ця адреса файлової системи відповідає фізичному SSD диску на моєму ПК.
Наступними діями для розширення розуміння того, яку роль відіграє Пул зберігання у сховищі, ми створимо другий Пул зберігання який фізично розташовуватиметься на іншому типі диску, на HDD. Проблема полягає в тому, що LXD не дозволяє створювати Пул зберігання поза адресою /var/lib/lxd/disks/ і навіть символічні посилання не працюватимуть, дивіться відповідь розробника. Минемо це обмеження ми можемо при ініціалізації/форматуванні Пул зберігання вказавши значення як блоковий пристрій замість шляху до loopback-файлу, вказавши це в ключі source.
Отже, до створення Пул зберігання необхідно визначити loopback-файл або існуючий розділ у файловій системі який він буде використовувати. Для цього ми створимо і будемо використовувати файл, який обмежимо розміром в 10GB:
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
Підключимо loopback-файл у вільний loopback-пристрій:
Завдяки ключу --show виконання команди повертає на екран ім'я пристрою, до якого підключився наш loopback-файл. За потреби, ми можемо вивести на екран список усіх зайнятих пристроїв цього типу, щоб переконатися у коректності наших дій:
Зі списку можна виявити, що у пристрої /dev/loop1 підключений loopback-файл /mnt/work/lxd/hddpool.img, а у пристрої /dev/loop0 підключений loopback-файл /var/lib/lxd/disks/ssdpool.img який відповідає дефолтному Пул зберігання.
Наступна команда створює новий Пул зберігання в LXD на основі щойно підготовленого loopback-файлу. LXD відформатує файл loopback /mnt/work/lxd/hddpool.img у пристрої /dev/loop1 під файлову систему BTRFS:
Автовставка loopback-файлу в слот loopback-пристрою ^
У нас є одна невелика проблема, при перезавантаженні системи хоста, файл /mnt/work/lxd/hddpool.img "вилетить" із пристрою /dev/loop1 і сервіс LXD впаде при завантаженні, оскільки не побачить його в цьому пристрої. Для вирішення цієї проблеми потрібно створити системний сервіс, який буде вставляти цей файл у пристрій /dev/loop1 під час завантаження системи хоста.
Створимо блок файл типу обслуговування в /etc/systemd/system/ для системи ініціалізації SystemD:
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
Активуємо сервіс:
sudo systemctl enable lxd-hddpool
Created symlink /etc/systemd/system/local-fs.target.wants/lxd-hddpool.service → /etc/systemd/system/lxd-hddpool.service.
Після рестарту хостової системи перевіряємо статус сервісу:
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).
З висновку ми можемо переконатися, що стан сервісу дорівнює активнийнезважаючи на те, що виконання нашого скрипту з однієї команди завершилося, це дозволило нам зробити опцію RemainAfterExit=true.
Оскільки всі процеси контейнера фактично виконуються в ізоляції на хостовій системі, використовуючи його ядро, то для додаткового захисту доступу процесів контейнера до системи хоста LXD пропонує привілейованість процесів, де:
Привілейовані контейнери — це контейнери в яких процеси з UID та GID відповідають тому ж власнику, що й на хостовій системі. Наприклад, процес запущений у контейнері з UID рівним 0 має все ті ж права доступу, що і процес хостової системи з UID рівним 0. Іншими словами, root користувач у контейнері має всі права не тільки в контейнері, але і на хостовій системі якщо він зможе вийти за межі ізольованого простору імен контейнера.
Непривілейовані контейнери — це контейнери в яких процеси належать власнику UID і GID з номером від 0 до 65535, але для хостової системи власник маскується за допомогою біта SubUID і SubGID, що додається відповідно. Наприклад, користувач з UID=0 у контейнері буде помічений у хостовій системі як SubUID + UID. Це захищає хост-систему, оскільки якщо будь-який процес у контейнері зможе вийти зі свого ізольованого простору імен, він може взаємодіяти з хост-системою тільки як процес з невідомим, дуже високим UID/GID.
За замовчуванням, новостворені контейнери мають статус непривілейованих і тому ми повинні визначити SubUID та SubGID.
Створимо два конфігураційні файли в яких задамо маску для SubUID і SubGID відповідно:
Оскільки ми раніше ініціалізували мережу за допомогою майстра ініціалізації lxd init та створили мережевий пристрій lxdbr0, то в цьому розділі ми просто ознайомимося з мережею LXD і з тим, як створювати віртуальний комутатор (мережевий міст, bridge) за допомогою команди клієнта.
Наступна схема демонструє як комутатор (мережевий міст, bridge) поєднує хост і контейнери в мережу:
Контейнери можуть взаємодіяти через мережу з іншими контейнерами або хостом на якому обслуговуються ці контейнери. Для цього необхідно з'єднати віртуальні мережеві карти контейнерів з віртуальним комутатором. На початку створимо комутатор, а мережні інтерфейси контейнера будуть слинковані в наступних розділах, після того, як буде створено сам контейнер.
Наступна команда створює комутатор із підмережею 10.0.5.0/24 та IPv4 адресою 10.0.5.1/24, а також включає ipv4.nat щоб контейнери змогли отримувати інтернет через хост за допомогою служби NAT:
Кожен контейнер в LXD має свою власну конфігурацію і може розширювати її за допомогою глобально декларованих конфігурацій, які називаються профілями конфігурації. Застосування конфігураційних профілів до контейнера має каскадну модель, наступний приклад демонструє це:
У цьому прикладі в системі LXD створено три профілю: default, hddpool и hostfs. Всі три профілю застосовані до контейнера, у якого є локальна конфігурація (сіра зона). Профіль default має пристрій root у якого параметр pool дорівнює ssdpool, але завдяки каскадній моделі застосування конфігурації ми можемо застосувати для контейнера профіль hddpool у якого параметр pool перекриє цей параметр із профілю default та контейнер отримає конфігурацію пристрою root з параметром pool рівним hddpool, а профіль hostfs просто додає новий пристрій у контейнер.
Для того, щоб побачити список доступних профілів конфігурації, служить наступна команда:
lxc profile list
+---------+---------+
| NAME | USED BY |
+---------+---------+
| default | 1 |
+---------+---------+
| hddroot | 0 |
+---------+---------+
| ssdroot | 1 |
+---------+---------+
Повний список доступних команд для роботи з профілем можна отримати додавши ключ --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
Профіль конфігурації за промовчанням default не має конфігурації мережевої карти для контейнера і всі новостворені контейнери не мають мережу, для них необхідно створювати локальні (виділені) пристрої мережі окремою командою, але ми можемо створити у профілі конфігурації глобальний мережевий пристрій, який буде розділятися між усіма контейнерами, які використовують цей профіль. Таким чином, відразу після команди створення нового контейнера у них буде мережа з доступом до мережі. При цьому, немає обмежень, ми завжди можемо пізніше створити локальний мережевий пристрій, якщо буде в цьому необхідність.
Наступна команда додасть у профіль конфігурації пристрій eth0 типу nic що приєднується до мережі lxdbr0:
lxc profile device add default eth0 nic network=lxdbr0 name=eth0
Оскільки ми фактично додали пристрій у профіль конфігурації, то якби ми вказали в пристрої статичну IP адресу, то всі контейнери які будуть застосовувати цей профіль розділять одну і ту ж IP адресу. Якщо необхідно створити контейнер з виділеним для контейнера статичним IP адерсом, тоді слід створити конфігурацію мережного пристрою на рівні контейнера (локальна конфігурація) з параметром IP адреси, а не на рівні профілю.
Перевіримо профіль:
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: []
У цьому профілі ми можемо побачити, що для всіх новостворених контейнерів буде створено два пристрої (devices):
eth0 - Пристрій типу nic з'єднане з комутатором (мережевим мостом) lxdbr0
root - Пристрій типу disk яке використовує пул сховища ssdpool
Для використання раніше створених Пул зберігання контейнерами, створимо профіль конфігурації ssdroot в якому додамо пристрій типу disk з точкою монтування / (root) використовує раніше створене Пул зберігання - ssdpool:
Контейнери створюються з образів, які є спеціально зібраними дистрибутивами, що не мають ядра Linux. Тому, перш ніж запустити контейнер, він має бути розгорнутий із цього образу. Джерелом образів служить локальний репозиторій, у який образи завантажуються із зовнішніх репозиторіїв.
Для початку експлуатації контейнера необхідно додати образ із глобального репозиторію до локального local:. Наразі локальний репозиторій порожній, переконається в цьому нам дасть команда lxc image list. Якщо методом list не вказати репозиторій, то за умовчанням використовуватиметься локальний репозиторій. local:
lxc image list local:
+-------+-------------+--------+-------------+--------------+------+------+
| ALIAS | FINGERPRINT | PUBLIC | DESCRIPTION | ARCHITECTURE | TYPE | SIZE |
+-------+-------------+--------+-------------+--------------+------+------+
Управління образами у репозиторії проводиться такими методами:
Команда
Опис
lxc image псевдонім
Manage image aliases
lxc image скопіювати
Copy images between servers
lxc image видаляти
Видалити зображення
lxc image редагувати
Edit image properties
lxc image експорт
Export and download images
lxc image імпорт
Import images into the image store
lxc image інформація
Show useful information o images
lxc image список
Список зображень
lxc image оновлення
Refresh images
lxc image Показувати
Show image properties
Копіюємо образ у локальний репозиторій із глобального images::
Крім інтерактивного режиму, LXD підтримує також неінтерактивний режим установки конфігурації, це коли конфігурація задається у вигляді YAML-файлу, спеціального формату, який дозволяє встановити всю конфігурацію за один раз, минаючи виконання безлічі інтерактивних команд, які були розглянуті вище в цій статті. конфігурацію мережі, створення конфігураційних профілів і т.д. Тут ми не будемо розглядати цю область, ви можете самостійно ознайомитись із цим у документації.
Наступна інтерактивна команда lxc config яку ми розглянемо дозволяє встановлювати конфігурацію. Наприклад, щоб завантажені образи до локального репозиторію не оновлювалися автоматично з глобальних репозиторіїв, ми можемо включити цю поведінку наступною командою:
Для створення контейнера служить команда lxc init якій передаються значення репозиторий:образ і потім бажаний ідентифікатор контейнера. Репозиторій може бути вказаний як локальний local: так і будь-який глобальний. Якщо репозиторій не вказано, за замовчуванням, для пошуку образу використовується локальний репозиторій. Якщо образ вказаний із глобального репозиторію, то спочатку образ буде завантажений у локальний репозиторій, а потім використаний для створення контейнера.
Виконаємо наступну команду, щоб створити наш перший контейнер:
lxc init alpine3 alp --storage=hddpool --profile=default --profile=hddroot
Розберемо по порядку ключі команди, які ми тут використовуємо:
alpine3 — Вказується альяс (псевдонім) для образу, який раніше був завантажений у локальний репозиторій. Якби альяс був не створений для цього образу, то завжди можна послатися на образ за його відбиток пальця який виводиться у таблиці.
alp — Визначається ідентифікатор для контейнера
--storage — Цей ключ вказує у якому Пул зберігання буде створено контейнер
--profile — Ці ключі каскадно застосовують до контейнера конфігурацію із раніше створених профілів конфігурації
Запускаємо контейнер, який починає запускати init-систему дистрибутива:
lxc start alp
Також, можна скористатися командою lxc launch яка дозволяє об'єднати команди lxc init и lxc start за одну операцію.
Перевіряємо стан контейнера:
lxc list -c ns46tb
+------+---------+------------------+------+-----------+--------------+
| NAME | STATE | IPV4 | IPV6 | TYPE | STORAGE POOL |
+------+---------+------------------+------+-----------+--------------+
| alp | RUNNING | 10.0.5.46 (eth0) | | CONTAINER | hddpool |
+------+---------+------------------+------+-----------+--------------+
У секції profiles ми можемо переконатися, що цей контейнер використовує два профілі конфігурації. default и hddroot. У секції devices ми можемо виявити лише один пристрій, оскільки мережний пристрій було створено на рівні профілю default. Для того, щоб побачити всі пристрої, що використовуються контейнером, необхідно додати ключ. --expanded:
Якщо ми спробуємо встановити IP-адресу для мережного пристрою eth0 командою lxc config device set alp призначеної для конфігурації контейнера, ми отримаємо помилку яка повідомить, що пристрій не існує тому що пристрій eth0 яке використовується контейнером належить профілю default:
lxc config device set alp eth0 ipv4.address 10.0.5.5
Error: The device doesn't exist
Ми можемо звичайно встановити статичну IP адресу для eth0 пристрої в профілі, але він буде єдиний для всіх контейнерів, які цей профіль будуть використовувати. Тому, додамо виділений для контейнера пристрій:
lxc config device add alp eth0 nic name=eth0 nictype=bridged parent=lxdbr0 ipv4.address=10.0.5.5
Потім потрібно рестартувати контейнер:
lxc restart alp
Якщо ми зараз подивимося на конфігурацію контейнера, то нам не потрібно використовувати опцію --expanded щоб побачити мережевий пристрій eth0, тому що ми створили його на рівні контейнера і воно каскадно перекрило цей же пристрій із профілю default:
Для виконання команд у контейнері, безпосередньо, минаючи мережеві з'єднання, служить команда lxc exec яка виконує команди у контейнері без запуску системної оболонки. Якщо вам потрібно виконати команду в оболонці, використовуючи shell патерни, такі як змінні, файлові перенаправлення (pipe) і т.д., необхідно явно запускати оболонку і передавати команду в якості ключа, наприклад:
lxc exec alp -- /bin/sh -c "echo $HOME"
У команді був задіяний спецсимвол екранування для спецсимволу $ щоб змінна $HOME не інтерпретувалася на хостовій машині, а була інтерпретована лише усередині контейнера.
Також, можна запустити інтерактивний режим оболонки, а потім завершити сеанс виконавши hotkey CTRL+D:
У LXD можна управляти ресурсами контейнера за допомогою спеціального набору конфігурації. Повний список конфігураційних параметрів контейнера можна знайти у документації.
Для обмеження ресурсів ЦП існує декілька типів обмежень:
limit.cpu - Прив'язує контейнер до одного або кількох ядрів ЦП
limits.cpu.allowance - Керує або квотами планувальника CFS, коли пройшло обмеження за часом, або універсальним механізмом спільного використання ресурсів CPU, коли пройшло відсоткове значення
limits.cpu.priority — пріоритет планувальника, коли для кількох примірників, які спільно використовують набір процесорів, призначений однаковий відсоток процесорів
Крім таких обмежень як limits.read, limits.write ми також можемо обмежити обсяг споживання контейнером дискового простору (працює лише з ZFS або BTRFS):
lxc config device set alp root size=2GB
Після встановлення у параметрі devices.root.size ми можемо переконатися у встановленому обмеженні:
lxc config show alp
...
devices:
root:
path: /
pool: hddpool
size: 2GB
type: disk
ephemeral: false
profiles:
- default
- hddroot
stateful: false
description: ""
Для перегляду використаних квот на диск ми можемо отримати з команди 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
Незважаючи на те, що ми встановили обмеження для кореневого пристрою контейнера в 2GB, системні утиліти, такі як df не бачитимуть цього обмеження. Для цього ми проведемо невеликий тест і з'ясуємо, як це працює.
Створимо 2 нових однакових контейнери в тому самому Пул зберігання (hddpool):
lxc exec alp1 -- ls -lh
total 1000M
-rw-r--r-- 1 root root 1000.0M Mar 27 10:16 file.img
Якщо ми подивимося в другому контейнері, перевіримо існування файлу в тому самому місці, то цього файлу не буде, що очікувано, оскільки контейнери створюються у своїх власних Обсяг зберігання в цьому ж Пул зберігання:
lxc exec alp2 -- ls -lh
total 0
Але давайте порівняємо значення які видає df на одному та іншому контейнерах:
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% /
...
Пристрій /dev/loop1 змонтований як кореневий розділ є Пул зберігання яке ці контейнери використовують, тому вони поділяють його об'єм на двох.
У LXD є можливість створення снапшотів і відновлення стану контейнера.
Щоб створити снепшот, виконайте таку команду:
lxc snapshot alp snapshot1
У команди lxc snapshot немає ключа list, тому, щоб переглянути список снепшотів потрібно скористатися командою, яка виводить загальну інформацію про контейнер:
lxc info alp
...
...
Snapshots:
snapshot1 (taken at 2020/04/08 18:18 UTC) (stateless)
Відновити контейнер із снепшоту можна командою lxc restore вказавши контейнер для якого буде зроблено відновлення та псевдонім снепшота:
lxc restore alp snapshot1
Наступна команда служить видалення снепшота. Зверніть увагу, що синтаксис команди не схожий на решту, тут необхідно вказати прямий слєш після імені контейнера. Якщо слід опустити, то команда видалення снепшота інтерпретується як команда видалення контейнера!
lxc delete alp/snapshot1
У наведеному вище прикладі ми розглянули так звані stateless-снапшоти. У LXD є інший тип снапшотів — stateful, у яких зберігається поточний стан всіх процесів у контейнері. Зі stateful-снапшотами пов'язані ряд цікавих і корисних функцій.