Изстрелване на Юпитер в LXD орбита

Налагало ли ви се е някога да експериментирате с код или системни помощни програми в Linux, за да не се притеснявате за основната система и да не разрушите всичко в случай на грешка в кода, който трябва да работи с root права?

Но какво ще кажете за факта, че да кажем, че трябва да тествате или стартирате цял клъстер от различни микроуслуги на една машина? Сто или дори хиляда?

С виртуални машини, управлявани от хипервайзор, подобни проблеми могат и ще бъдат решени, но на каква цена? Например, контейнер в LXD, базиран на дистрибуцията на Alpine Linux, консумира само 7.60MB RAM и къде заема основният дял след стартиране 9.5MB! Как ти харесва това, Илон Мъск? Препоръчвам да проверите основни възможности на LXD - контейнерна система в Linux

След като стана ясно какво представляват LXD контейнерите, нека отидем по-нататък и да помислим, какво ще стане, ако имаше такава платформа за събиране на средства, където можете безопасно да изпълнявате код за хоста, да генерирате графики, динамично (интерактивно) да свързвате UI-джаджи с вашия код, допълнете кода с текст с блекджек... форматиране? Някакъв вид интерактивен блог? Леле... Искам го! Искам! 🙂

Погледнете под котката, където ще пуснем в контейнер лаборатория Юпитер - следващото поколение потребителски интерфейс вместо остарелия Jupyter Notebook и ние също ще инсталираме Python модули като напр. numpy, Пандите, Матплотлиб, IPyWidgets което ще ви позволи да направите всичко изброено по-горе и да го запишете в специален файл - IPython лаптоп.

Изстрелване на Юпитер в LXD орбита

План за орбитално излитане ^

Изстрелване на Юпитер в LXD орбита

Нека очертаем кратък план за действие, за да ни улесни в прилагането на схемата по-горе:

  • Нека инсталираме и стартираме контейнер, базиран на комплекта за разпространение Алпийски Linux. Ще използваме тази дистрибуция, защото тя е насочена към минимализъм и ще инсталира само най-необходимия софтуер в нея, нищо излишно.
  • Нека добавим допълнителен виртуален диск в контейнера и да му дадем име - hostfs и го монтирайте към основната файлова система. Този диск ще направи възможно използването на файлове на хоста от дадена директория вътре в контейнера. Така нашите данни ще бъдат независими от контейнера. Ако контейнерът бъде изтрит, данните ще останат на хоста. Освен това тази схема е полезна за споделяне на едни и същи данни между много контейнери, без да се използват стандартните мрежови механизми на разпространението на контейнери.
  • Да инсталираме Bash, sudo, необходимите библиотеки, да добавим и конфигурираме системен потребител
  • Нека инсталираме Python, модули и компилираме бинарни зависимости за тях
  • Нека инсталираме и стартираме лаборатория Юпитер, персонализирайте външния вид, инсталирайте разширения за него.

В тази статия ще започнем със стартирането на контейнера, няма да обмисляме инсталиране и конфигуриране на LXD, можете да намерите всичко това в друга статия - Основни характеристики на LXD - Linux контейнерни системи.

Инсталиране и конфигуриране на основната система ^

Създаваме контейнер с командата, в която посочваме изображението - alpine3, идентификатор за контейнера - jupyterlab и, ако е необходимо, конфигурационни профили:

lxc init alpine3 jupyterlab --profile=default --profile=hddroot

Тук използвам конфигурационен профил hddroot което указва да се създаде контейнер с основен дял Басейн за съхранение разположен на физически HDD диск:

lxc profile show hddroot

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

config:
  size: 10GB
  source: /dev/loop1
  volatile.initial_source: /dev/loop1
description: ""
name: hddpool
driver: btrfs
used_by:
- /1.0/images/ebd565585223487526ddb3607f5156e875c15a89e21b61ef004132196da6a0a3
- /1.0/profiles/hddroot
status: Created
locations:
- none

Това ми дава възможност да експериментирам с контейнери на HDD диска, спестявайки ресурсите на SSD диска, който също е наличен в моята система 🙂, за който създадох отделен конфигурационен профил ssdroot.

След като контейнерът е създаден, той е в състояние STOPPED, така че трябва да го стартираме, като стартираме init системата в него:

lxc start jupyterlab

Нека покажем списък с контейнери в LXD с помощта на ключа -c което показва кое colums дисплей:

lxc list -c ns4b
+------------+---------+-------------------+--------------+
|    NAME    |  STATE  |       IPV4        | STORAGE POOL |
+------------+---------+-------------------+--------------+
| jupyterlab | RUNNING | 10.0.5.198 (eth0) | hddpool      |
+------------+---------+-------------------+--------------+

При създаването на контейнера IP адресът беше избран на случаен принцип, тъй като използвахме конфигурационен профил default който беше конфигуриран преди това в статията Основни характеристики на LXD - Linux контейнерни системи.

Ще променим този IP адрес на по-запомнящ се, като създадем мрежов интерфейс на ниво контейнер, а не на ниво профил на конфигурация, както е сега в текущата конфигурация. Не е нужно да правите това, можете да го пропуснете.

Създаване на мрежов интерфейс eth0 който свързваме към комутатора (мрежов мост) lxdbr0 в който активирахме NAT съгласно предишната статия и контейнерът вече ще има достъп до интернет, а също така присвояваме статичен IP адрес на интерфейса - 10.0.5.5:

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

След добавяне на устройство, контейнерът трябва да се рестартира:

lxc restart jupyterlab

Проверка на състоянието на контейнера:

lxc list -c ns4b
+------------+---------+------------------+--------------+
|    NAME    |  STATE  |       IPV4       | STORAGE POOL |
+------------+---------+------------------+--------------+
| jupyterlab | RUNNING | 10.0.5.5 (eth0)  | hddpool      |
+------------+---------+------------------+--------------+

Инсталиране на основен софтуер и настройка на системата ^

За да администрирате нашия контейнер, трябва да инсталирате следния софтуер:

Пакет
Описание

тряскам
Обвивката на GNU Bourne Again

bash-завършване
Програмируемо завършване за bash shell

Sudo
Дайте на определени потребители възможността да изпълняват някои команди като root

сянка
Пакет от инструменти за управление на пароли и акаунти с поддръжка на shadow файлове и PAM

tzdata
Източници на данни за часовата зона и лятното часово време

Нано
Клонинг на Pico редактор с подобрения

Освен това можете да инсталирате поддръжка в системните man-страници, като инсталирате следните пакети − man man-pages mdocml-apropos less

lxc exec jupyterlab -- apk add bash bash-completion sudo shadow tzdata nano

Нека да разгледаме командите и клавишите, които използвахме:

  • lxc — Обадете се на LXD клиент
  • exec - LXD клиентски метод, който изпълнява команда в контейнера
  • jupyterlab — ID на контейнера
  • -- - Специален ключ, който указва да не се интерпретират други ключове като ключове за lxc и прехвърлете останалата част от низа както е към контейнера
  • apk — Мениджър на пакети за разпространение на Alpine Linux
  • add — Метод за управление на пакети, който инсталира пакети, посочени след командата

След това ще зададем часова зона в системата Europe/Moscow:

lxc exec jupyterlab -- cp /usr/share/zoneinfo/Europe/Moscow /etc/localtime

След инсталиране на часовата зона пакетът tzdata вече не е необходимо в системата, ще заема място, така че нека го изтрием:

lxc exec jupyterlab -- apk del tzdata

Проверка на часовата зона:

lxc exec jupyterlab -- date

Wed Apr 15 10:49:56 MSK 2020

За да не прекарваме много време в настройка на Bash за нови потребители в контейнера, в следващите стъпки ще копираме готови skel файлове от хост системата в него. Това ще ви позволи да разкрасите Bash в контейнер интерактивно. Моята хост система е Manjaro Linux и файловете, които се копират /etc/skel/.bash_profile, /etc/skel/.bashrc, /etc/skel/.dir_colors по принцип те са подходящи за Alpine Linux и не създават критични проблеми, но може да имате различна дистрибуция и трябва самостоятелно да разберете дали има грешка при стартиране на Bash в контейнера.

Копирайте skel файловете в контейнера. Ключ --create-dirs ще създаде необходимите директории, ако те не съществуват:

lxc file push /etc/skel/.bash_profile jupyterlab/etc/skel/.bash_profile --create-dirs
lxc file push /etc/skel/.bashrc jupyterlab/etc/skel/.bashrc
lxc file push /etc/skel/.dir_colors jupyterlab/etc/skel/.dir_colors

За съществуващ root потребител, копирайте skel файловете, току-що копирани в контейнера, в началната директория:

lxc exec jupyterlab -- cp /etc/skel/.bash_profile /root/.bash_profile
lxc exec jupyterlab -- cp /etc/skel/.bashrc /root/.bashrc
lxc exec jupyterlab -- cp /etc/skel/.dir_colors /root/.dir_colors

Alpine Linux инсталира системна обвивка за потребителите /bin/sh, ще го заменим с root потребител в Bash:

lxc exec jupyterlab -- usermod --shell=/bin/bash root

Че root потребителят не е бил без парола, той трябва да зададе парола. Следната команда ще генерира и зададе нова произволна парола за него, която ще видите на екрана на конзолата след нейното изпълнение:

lxc exec jupyterlab -- /bin/bash -c "PASSWD=$(head /dev/urandom | tr -dc A-Za-z0-9 | head -c 12); echo "root:$PASSWD" | chpasswd && echo "New Password: $PASSWD""

New Password: sFiXEvBswuWA

Също така, нека създадем нов системен потребител - jupyter за които ще конфигурираме по-късно лаборатория Юпитер:

lxc exec jupyterlab -- useradd --create-home --shell=/bin/bash jupyter

Нека генерираме и зададем парола за него:

lxc exec jupyterlab -- /bin/bash -c "PASSWD=$(head /dev/urandom | tr -dc A-Za-z0-9 | head -c 12); echo "jupyter:$PASSWD" | chpasswd && echo "New Password: $PASSWD""

New Password: ZIcbzWrF8tki

След това ще изпълним две команди, първата ще създаде системна група sudo, а вторият ще добави потребител към него jupyter:

lxc exec jupyterlab -- groupadd --system sudo
lxc exec jupyterlab -- groupmems --group sudo --add jupyter

Нека да видим към кои групи принадлежи потребителят jupyter:

lxc exec jupyterlab -- id -Gn jupyter

jupyter sudo

Всичко е наред, да продължим.

Разрешете всички потребители, които са членове на групата sudo използвайте команда sudo. За да направите това, изпълнете следния скрипт, където sed декоментира реда с параметър в конфигурационния файл /etc/sudoers:

lxc exec jupyterlab -- /bin/bash -c "sed --in-place -e '/^#[ t]*%sudo[ t]*ALL=(ALL)[ t]*ALL$/ s/^[# ]*//' /etc/sudoers"

Инсталиране и конфигуриране на JupyterLab ^

лаборатория Юпитер е приложение на Python, така че първо трябва да инсталираме този интерпретатор. Също, лаборатория Юпитер ще инсталираме с помощта на мениджъра на пакети Python pip, а не системния, защото може да е остарял в системното хранилище и следователно трябва ръчно да разрешим зависимостите за него, като инсталираме следните пакети − python3 python3-dev gcc libc-dev zeromq-dev:

lxc exec jupyterlab -- apk add python3 python3-dev gcc libc-dev zeromq-dev

Нека актуализираме модулите на Python и мениджъра на пакети pip към текущата версия:

lxc exec jupyterlab -- python3 -m pip install --upgrade pip setuptools wheel

инсталирам лаборатория Юпитер чрез мениджъра на пакети pip:

lxc exec jupyterlab -- python3 -m pip install jupyterlab

Тъй като разширенията в лаборатория Юпитер са експериментални и не се доставят официално с пакета jupyterlab, така че трябва да го инсталираме и конфигурираме ръчно.

Нека инсталираме NodeJS и пакетния мениджър за него - NPM, тъй като лаборатория Юпитер ги използва за своите разширения:

lxc exec jupyterlab -- apk add nodejs npm

Към разширения за лаборатория Юпитер които ще инсталираме работят, те трябва да бъдат инсталирани в потребителската директория, тъй като приложението ще се стартира от потребителя jupyter. Проблемът е, че в командата за стартиране няма параметър, който може да бъде предаден на директория; приложението приема само променлива на средата и затова трябва да я дефинираме. За да направим това, ще напишем командата за експортиране на променлива JUPYTERLAB_DIR в средата на потребителя jupyter, да подаде .bashrcкойто се изпълнява всеки път, когато потребителят влезе в системата:

lxc exec jupyterlab -- su -l jupyter -c "echo -e "nexport JUPYTERLAB_DIR=$HOME/.local/share/jupyter/lab" >> .bashrc"

Следващата команда ще инсталира специално разширение - мениджър на разширения в лаборатория Юпитер:

lxc exec jupyterlab -- su -l jupyter -c "export JUPYTERLAB_DIR=$HOME/.local/share/jupyter/lab; jupyter labextension install --no-build @jupyter-widgets/jupyterlab-manager"

Сега всичко е готово за първото изстрелване лаборатория Юпитер, но все пак можем да инсталираме няколко полезни разширения:

  • toc — Съдържание, генерира списък със заглавия в статия/бележник
  • jupyterlab-horizon-theme — Тема на потребителския интерфейс
  • jupyterlab_neon_theme — Тема на потребителския интерфейс
  • jupyterlab-ubu-theme - Друг тема от автора тази статия :) Но в този случай ще бъде показана инсталацията от хранилището на GitHub

И така, изпълнете следните команди последователно, за да инсталирате тези разширения:

lxc exec jupyterlab -- su -l jupyter -c "export JUPYTERLAB_DIR=$HOME/.local/share/jupyter/lab; jupyter labextension install --no-build @jupyterlab/toc @mohirio/jupyterlab-horizon-theme @yeebc/jupyterlab_neon_theme"
lxc exec jupyterlab -- su -l jupyter -c "wget -c https://github.com/microcoder/jupyterlab-ubu-theme/archive/master.zip"
lxc exec jupyterlab -- su -l jupyter -c "unzip -q master.zip && rm master.zip"
lxc exec jupyterlab -- su -l jupyter -c "export JUPYTERLAB_DIR=$HOME/.local/share/jupyter/lab; jupyter labextension install --no-build jupyterlab-ubu-theme-master"
lxc exec jupyterlab -- su -l jupyter -c "rm -r jupyterlab-ubu-theme-master"

След като инсталираме разширенията, трябва да ги компилираме, тъй като преди това, по време на инсталацията, сме посочили ключа --no-build за да спестите време. Сега ще ускорим значително, като ги компилираме заедно наведнъж:

lxc exec jupyterlab -- su -l jupyter -c "export JUPYTERLAB_DIR=$HOME/.local/share/jupyter/lab; jupyter lab build"

Сега изпълнете следните две команди, за да го стартирате за първи път лаборатория Юпитер. Би било възможно да го стартирате с една команда, но в този случай командата за стартиране, която е трудна за запомняне в ума ви, ще бъде запомнена от bash в контейнера, а не на хоста, където вече има достатъчно команди да ги запиша в историята :)

Влезте в контейнера като потребител jupyter:

lxc exec jupyterlab -- su -l jupyter

След това бягайте лаборатория Юпитер с ключове и параметри, както е посочено:

[jupyter@jupyterlab ~]$ jupyter lab --ip=0.0.0.0 --no-browser

Отидете на адреса във вашия уеб браузър http://10.0.5.5:8888 и на страницата, която се отваря, въведете жетон достъп, който ще видите в конзолата. Копирайте и го поставете на страницата, след което щракнете Влезте. След като влезете, отидете в менюто с разширения вляво, както е показано на фигурата по-долу, където ще бъдете подканени, когато активирате диспечера на разширенията, да поемете рискове за сигурността, като инсталирате разширения от трети страни, за които командата Разработка на JupyterLab не носи отговорност:

Изстрелване на Юпитер в LXD орбита

Ние обаче изолираме целия лаборатория Юпитер и го поставете в контейнер, така че разширенията на трети страни, които изискват и използват NodeJS, да не могат поне да откраднат данни на диска, различни от тези, които отваряме вътре в контейнера. Влезте в личните си документи на хоста /home процесите от контейнера е малко вероятно да успеят и ако успеят, тогава трябва да имате привилегии върху файлове в хост системата, тъй като ние изпълняваме контейнера в непривилегирован режим. Въз основа на тази информация можете да оцените риска от включване на разширения в лаборатория Юпитер.

Създадени IPython бележници (страници в лаборатория Юпитер) сега ще бъдат създадени в домашната директория на потребителя - /home/jupyter, но нашите планове са да разделим данните (споделяне) между хоста и контейнера, така че върнете се към конзолата и спрете лаборатория Юпитер чрез изпълнение на бърз клавиш - CTRL+C и отговаряйки y по заявка. След това прекратете интерактивната сесия на потребителя jupyter завършване на клавишна комбинация CTRL+D.

Споделяне на данни с хоста ^

За да споделяте данни с хоста, трябва да създадете устройство в контейнера, което ви позволява да направите това и за да направите това, изпълнете следната команда, където посочваме следните ключове:

  • lxc config device add — Командата добавя конфигурацията на устройството
  • jupyter — ID на контейнера, към който е добавена конфигурацията
  • hostfs — ID на устройството. Можете да зададете всяко име.
  • disk — Видът на устройството е посочен
  • path — Указва пътя в контейнера, към който LXD ще монтира това устройство
  • source — Посочете източника, пътя до директорията на хоста, който искате да споделите с контейнера. Посочете пътя според вашите предпочитания
lxc config device add jupyterlab hostfs disk path=/mnt/hostfs source=/home/dv/projects/ipython-notebooks

За каталога /home/dv/projects/ipython-notebooks разрешението трябва да бъде зададено на потребителя на контейнера, който в момента има UID, равен на SubUID + UID, Вижте Глава Безопасност. Привилегии на контейнера в статията Основни характеристики на LXD - Linux контейнерни системи.

Задайте разрешение на хоста, където собственикът ще бъде потребителят на контейнера jupyterи променливата $USER ще посочи вашия хост потребител като група:

sudo chown 1001000:$USER /home/dv/projects/ipython-notebooks

Здравей свят! ^

Ако все още имате отворена конзолна сесия в контейнера с лаборатория Юпитер, след което го рестартирайте с нов ключ --notebook-dir като зададете стойността /mnt/hostfs като пътя към корена на лаптопите в контейнера за устройството, което създадохме в предишната стъпка:

jupyter lab --ip=0.0.0.0 --no-browser --notebook-dir=/mnt/hostfs

След това отидете на страницата http://10.0.5.5:8888 и създайте първия си лаптоп, като щракнете върху бутона на страницата, както е показано на снимката по-долу:

Изстрелване на Юпитер в LXD орбита

След това в полето на страницата въведете кода на Python, който ще покаже класиката Hello World!. Когато приключите с въвеждането, натиснете CTRL+ENTER или бутона „възпроизвеждане“ на лентата с инструменти в горната част, за да накарате JupyterLab да направи това:

Изстрелване на Юпитер в LXD орбита

В този момент почти всичко е готово за употреба, но ще бъде безинтересно, ако не инсталираме допълнителни модули на Python (пълноценни приложения), които могат значително да разширят стандартните възможности на Python в лаборатория Юпитертака че да продължим :)

PS Интересното е, че старата реализация Юпитер под кодово име Джупиър Бележник не е изчезнал и съществува паралелно с лаборатория Юпитер. За да преминете към старата версия, следвайте връзката, добавяйки суфикса в адреса/tree, а преходът към новата версия се осъществява с наставката /lab, но не е необходимо да се посочва:

Разширяване на възможностите на Python ^

В този раздел ще инсталираме такива мощни езикови модули на Python като numpy, Пандите, Матплотлиб, IPyWidgets резултатите от които са интегрирани в лаптопи лаборатория Юпитер.

Преди да инсталирате изброените модули на Python чрез мениджъра на пакети pip първо трябва да разрешим системните зависимости в Alpine Linux:

  • g++ — Необходими за компилиране на модули, тъй като някои от тях са имплементирани в езика C + + и се свързват с Python по време на изпълнение като двоични модули
  • freetype-dev - зависимост за Python модул Матплотлиб

Инсталиране на зависимости:

lxc exec jupyterlab -- apk add g++ freetype-dev

Има един проблем: в текущото състояние на дистрибуцията на Alpine Linux няма да е възможно да се компилира новата версия на NumPy; ще се появи грешка при компилирането, която не мога да разреша:

ГРЕШКА: Не може да се изградят колела за numpy, които използват PEP 517 и не могат да бъдат инсталирани директно

Затова ще инсталираме този модул като системен пакет, който разпространява вече компилирана версия, но малко по-стара от тази, която в момента е налична на сайта:

lxc exec jupyterlab -- apk add py3-numpy py3-numpy-dev

След това инсталирайте модули на Python чрез мениджъра на пакети pip. Моля, бъдете търпеливи, тъй като някои модули ще се компилират и може да отнеме няколко минути. На моята машина компилацията отне ~15 минути:

lxc exec jupyterlab -- python3 -m pip install pandas ipywidgets matplotlib

Изчистване на инсталационния кеш:

lxc exec jupyterlab -- rm -rf /home/*/.cache/pip/*
lxc exec jupyterlab -- rm -rf /root/.cache/pip/*

Тестване на модули в JupyterLab ^

Ако бягате лаборатория Юпитер, рестартирайте го, за да се активират новоинсталираните модули. За да направите това, в конзолна сесия щракнете CTRL+C където го стартирате и влезте y за да спрете заявката и след това започнете отново лаборатория Юпитер като натиснете стрелката нагоре на клавиатурата, за да не въвеждате отново командата и след това Enter за да го стартирате:

jupyter lab --ip=0.0.0.0 --no-browser --notebook-dir=/mnt/hostfs

Отидете на страницата http://10.0.5.5:8888/lab или опреснете страницата в браузъра си и след това въведете следния код в нова клетка на бележника:

%matplotlib inline

from ipywidgets import interactive
import matplotlib.pyplot as plt
import numpy as np

def f(m, b):
    plt.figure(2)
    x = np.linspace(-10, 10, num=1000)
    plt.plot(x, m * x + b)
    plt.ylim(-5, 5)
    plt.show()

interactive_plot = interactive(f, m=(-2.0, 2.0), b=(-3, 3, 0.5))
output = interactive_plot.children[-1]
output.layout.height = '350px'
interactive_plot

Трябва да получите резултат като на снимката по-долу, където IPyWidgets генерира UI елемент на страницата, който взаимодейства интерактивно с изходния код, а също Матплотлиб показва резултата от кода под формата на картина като функционална графика:

Изстрелване на Юпитер в LXD орбита

Много примери IPyWidgets можете да го намерите в уроци тук

Какво друго? ^

Браво, ако сте останали и сте стигнали до самия край на статията. Умишлено не пуснах готов скрипт в края на статията, който да се инсталира лаборатория Юпитер в „едно кликване“, за да насърчите работниците :) Но можете да го направите сами, тъй като вече знаете как, след като сте събрали командите в един Bash скрипт :)

Можете също:

  • Задайте мрежово име за контейнера вместо IP адрес, като го напишете в прост /etc/hosts и въведете адреса в браузъра http://jupyter.local:8888
  • Поиграйте си с ограничението на ресурсите за контейнера, за това прочетете главата в основни LXD възможности или получете повече информация на сайта за разработчици на LXD.
  • Промяна на темата:

Изстрелване на Юпитер в LXD орбита

И много повече можете да направите! Това е всичко. Пожелавам ти успех!

АКТУАЛИЗАЦИЯ: 15.04.2020 г. 18:30 ч. - Коригирани грешки в глава „Здравей, свят!“
АКТУАЛИЗАЦИЯ: 16.04.2020 г. 10:00 — Коригиран и добавен текст в описанието на активирането на диспечера на разширения лаборатория Юпитер
АКТУАЛИЗАЦИЯ: 16.04.2020 г. 10:40 — Коригирани грешки, открити в текста и леко променена към по-добро главата „Инсталиране на основен софтуер и настройка на системата“

Източник: www.habr.com

Добавяне на нов коментар