Sender Jupyter i LXD-kredsløb

Har du nogensinde skullet eksperimentere med kode eller systemværktøjer i Linux for ikke at bekymre dig om basissystemet og ikke rive alt ned i tilfælde af en fejl i koden, der skulle køre med root-rettigheder?

Men hvad med det faktum, at lad os sige, at du skal teste eller køre en hel klynge af forskellige mikrotjenester på én maskine? Hundrede eller endda tusind?

Med virtuelle maskiner, der styres af en hypervisor, kan og vil sådanne problemer blive løst, men til hvilken pris? For eksempel bruger en container i LXD baseret på Alpine Linux-distributionen kun 7.60MB RAM, og hvor rodpartitionen optager efter opstart 9.5MB! Hvordan kan du lide det, Elon Musk? Jeg anbefaler at tjekke ud grundlæggende funktioner i LXD - et containersystem i Linux

Efter at det generelt blev klart, hvad LXD-containere er, lad os gå videre og tænke, hvad nu hvis der var sådan en høsterplatform, hvor du sikkert kunne køre kode for værten, generere grafer, dynamisk (interaktivt) linke UI-widgets med din kode, supplere koden med tekst med blackjack... formatering? En slags interaktiv blog? Wow... jeg vil have det! Vil have! 🙂

Se under katten, hvor vi vil lancere i en container jupyter lab - den næste generation af brugergrænseflade i stedet for den forældede Jupyter Notebook, og vi vil også installere Python-moduler som f.eks. nusset, pandas, Matplotlib, IPyWidgets som giver dig mulighed for at gøre alt, der er anført ovenfor og gemme det hele i en speciel fil - en IPython bærbar computer.

Sender Jupyter i LXD-kredsløb

Orbital startplan ^

Sender Jupyter i LXD-kredsløb

Lad os skitsere en kort handlingsplan for at gøre det nemmere for os at implementere ordningen ovenfor:

  • Lad os installere og starte en container baseret på distributionssættet Alpine Linux. Vi vil bruge denne distribution, fordi den er rettet mod minimalisme og vil kun installere den mest nødvendige software i den, intet overflødigt.
  • Lad os tilføje en ekstra virtuel disk i containeren og give den et navn - hostfs og monter den til rodfilsystemet. Denne disk vil gøre det muligt at bruge filer på værten fra en given mappe inde i containeren. Vores data vil således være uafhængige af containeren. Hvis containeren slettes, forbliver dataene på værten. Dette skema er også nyttigt til at dele de samme data mellem mange containere uden at bruge standardnetværksmekanismerne for containerdistributionen.
  • Lad os installere Bash, sudo, de nødvendige biblioteker, tilføje og konfigurere en systembruger
  • Lad os installere Python, moduler og kompilere binære afhængigheder til dem
  • Lad os installere og starte jupyter lab, tilpas udseendet, installer udvidelser til det.

I denne artikel starter vi med at lancere containeren, vi vil ikke overveje at installere og konfigurere LXD, du kan finde alt dette i en anden artikel - Grundlæggende funktioner i LXD - Linux containersystemer.

Installation og konfiguration af basissystemet ^

Vi opretter en beholder med kommandoen, hvori vi angiver billedet - alpine3, id for containeren - jupyterlab og om nødvendigt konfigurationsprofiler:

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

Her bruger jeg en konfigurationsprofil hddroot som specificerer at oprette en container med en rodpartition i opbevaringspool placeret på en fysisk harddisk:

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

Dette giver mig muligheden for at eksperimentere med containere på HDD-disken, og spare ressourcerne på SSD-disken, som også er tilgængelig i mit system 🙂 som jeg har oprettet en separat konfigurationsprofil til ssdroot.

Når beholderen er oprettet, er den i tilstanden STOPPED, så vi skal starte det ved at køre init-systemet i det:

lxc start jupyterlab

Lad os vise en liste over containere i LXD ved hjælp af tasten -c som angiver hvilken cvisning af olumner:

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

Ved oprettelse af containeren blev IP-adressen valgt tilfældigt, da vi brugte en konfigurationsprofil default som tidligere var konfigureret i artiklen Grundlæggende funktioner i LXD - Linux containersystemer.

Vi vil ændre denne IP-adresse til en mere mindeværdig ved at oprette en netværksgrænseflade på containerniveau og ikke på konfigurationsprofilniveau, som det nu er i den aktuelle konfiguration. Du behøver ikke at gøre dette, du kan springe det over.

Oprettelse af en netværksgrænseflade eth0 som vi linker til switchen (netværksbroen) lxdbr0 hvor vi aktiverede NAT i henhold til den forrige artikel, og containeren vil nu have adgang til internettet, og vi tildeler også en statisk IP-adresse til grænsefladen - 10.0.5.5:

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

Efter tilføjelse af en enhed skal beholderen genstartes:

lxc restart jupyterlab

Kontrol af containerens status:

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

Installation af grundlæggende software og opsætning af systemet ^

For at administrere vores container skal du installere følgende software:

Pakke
Beskrivelse

bash
GNU Bourne Again-skallen

bash-afslutning
Programmerbar afslutning til bash-skallen

sudo
Giv visse brugere mulighed for at køre nogle kommandoer som root

skygge
Adgangskode- og kontostyringsværktøjspakke med understøttelse af skyggefiler og PAM

tzdata
Kilder til data om tidszone og sommertid

nano
Pico editor klon med forbedringer

Derudover kan du installere support i systemets man-sider ved at installere følgende pakker - man man-pages mdocml-apropos less

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

Lad os se på de kommandoer og taster, vi brugte:

  • lxc — Ring til LXD-klient
  • exec - LXD-klientmetode, der kører en kommando i containeren
  • jupyterlab — Container ID
  • -- - En speciel nøgle, der specificerer ikke at fortolke yderligere nøgler som nøgler til lxc og før resten af ​​strengen som den er til beholderen
  • apk — Alpine Linux distributionspakke manager
  • add — En pakkehåndteringsmetode, der installerer pakker angivet efter kommandoen

Dernæst vil vi indstille en tidszone i systemet Europe/Moscow:

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

Efter installation af tidszonen, pakken tzdata ikke længere er nødvendig i systemet, vil det optage plads, så lad os slette det:

lxc exec jupyterlab -- apk del tzdata

Kontrol af tidszonen:

lxc exec jupyterlab -- date

Wed Apr 15 10:49:56 MSK 2020

For ikke at bruge meget tid på at opsætte Bash for nye brugere i containeren, vil vi i de følgende trin kopiere færdige skel-filer fra værtssystemet til den. Dette giver dig mulighed for at forskønne Bash i en container interaktivt. Mit værtssystem er Manjaro Linux og filerne, der kopieres /etc/skel/.bash_profile, /etc/skel/.bashrc, /etc/skel/.dir_colors i princippet er de velegnede til Alpine Linux og forårsager ikke kritiske problemer, men du kan have en anden distribution, og du skal selvstændigt finde ud af, om der er en fejl, når du kører Bash i containeren.

Kopier skel-filerne til containeren. Nøgle --create-dirs vil oprette de nødvendige mapper, hvis de ikke findes:

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

For en eksisterende root-bruger skal du kopiere skel-filerne, der lige er kopieret ind i containeren til hjemmemappen:

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 installerer en systemskal til brugere /bin/sh, vil vi erstatte det med root bruger i Bash:

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

Det root brugeren var ikke uden adgangskode, han skal angive en adgangskode. Følgende kommando vil generere og indstille en ny tilfældig adgangskode til ham, som du vil se på konsolskærmen efter dens udførelse:

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

Lad os også oprette en ny systembruger - jupyter som vi konfigurerer til senere jupyter lab:

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

Lad os generere og indstille en adgangskode til det:

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

Dernæst vil vi udføre to kommandoer, den første vil oprette en systemgruppe sudo, og den anden tilføjer en bruger til den jupyter:

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

Lad os se, hvilke grupper brugeren tilhører jupyter:

lxc exec jupyterlab -- id -Gn jupyter

jupyter sudo

Alt er ok, lad os komme videre.

Tillad alle brugere, der er medlemmer af gruppen sudo brug kommando sudo. For at gøre dette skal du køre følgende script, hvor sed fjerner kommentarer til parameterlinjen i konfigurationsfilen /etc/sudoers:

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

Installation og konfiguration af JupyterLab ^

jupyter lab er et Python-program, så vi skal først installere denne fortolker. Også, jupyter lab vi installerer ved hjælp af Python-pakkehåndteringen pip, og ikke systemet, fordi det kan være forældet i systemlageret, og derfor er vi nødt til manuelt at løse afhængighederne for det ved at installere følgende pakker − python3 python3-dev gcc libc-dev zeromq-dev:

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

Lad os opdatere python-moduler og pakkehåndtering pip til den aktuelle version:

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

Indstil jupyter lab via pakkehåndtering pip:

lxc exec jupyterlab -- python3 -m pip install jupyterlab

Siden udvidelserne i jupyter lab er eksperimentelle og leveres ikke officielt med jupyterlab-pakken, så vi skal installere og konfigurere den manuelt.

Lad os installere NodeJS og pakkehåndteringen til det - NPM, siden jupyter lab bruger dem til sine udvidelser:

lxc exec jupyterlab -- apk add nodejs npm

Til udvidelser til jupyter lab som vi vil installere fungerede, skal de installeres i brugermappen, da applikationen vil blive lanceret fra brugeren jupyter. Problemet er, at der ikke er nogen parameter i startkommandoen, der kan sendes til en mappe; applikationen accepterer kun en miljøvariabel, og derfor skal vi definere den. For at gøre dette skriver vi kommandoen variabel eksport JUPYTERLAB_DIR i brugerens miljø jupyter, til fil .bashrcsom udføres hver gang brugeren logger på:

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

Den næste kommando vil installere en speciel udvidelse - extension manager in jupyter lab:

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

Nu er alt klar til den første lancering jupyter lab, men vi kan stadig installere et par nyttige udvidelser:

  • toc — Indholdsfortegnelse, genererer en liste over overskrifter i en artikel/notesbog
  • jupyterlab-horizon-theme - UI-tema
  • jupyterlab_neon_theme - UI-tema
  • jupyterlab-ubu-theme - Endnu en tema fra forfatteren denne artikel :) Men i dette tilfælde vil installationen fra GitHub-lageret blive vist

Så kør følgende kommandoer sekventielt for at installere disse udvidelser:

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"

Efter installation af udvidelserne skal vi kompilere dem, da vi tidligere under installationen specificerede nøglen --no-build for at spare tid. Nu vil vi fremskynde betydeligt ved at kompilere dem sammen på én gang:

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

Kør nu de følgende to kommandoer for at køre det for første gang jupyter lab. Det ville være muligt at starte den med én kommando, men i dette tilfælde vil startkommandoen, som er svær at huske i dit sind, blive husket af bash i containeren og ikke på værten, hvor der allerede er nok kommandoer at registrere dem i historien :)

Log ind på containeren som bruger jupyter:

lxc exec jupyterlab -- su -l jupyter

Næste, løb jupyter lab med taster og parametre som angivet:

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

Gå til adressen i din webbrowser http://10.0.5.5:8888 og indtast på den side, der åbner token adgang, som du vil se i konsollen. Kopiér og indsæt det på siden, og klik derefter Login. Når du er logget ind, skal du gå til udvidelsesmenuen til venstre, som vist i figuren nedenfor, hvor du, når du aktiverer udvidelsesadministratoren, bliver bedt om at tage sikkerhedsrisici ved at installere udvidelser fra tredjeparter, for hvilke kommandoen JupyterLab udvikling er ikke ansvarlig:

Sender Jupyter i LXD-kredsløb

Men vi isolerer det hele jupyter lab og placer det i en container, så tredjepartsudvidelser, der kræver og bruger NodeJS, ikke i det mindste kan stjæle andre data på disken end dem, vi åbner inde i containeren. Gå til dine private dokumenter på værten i /home processer fra containeren er usandsynligt, at de lykkes, og hvis de gør det, skal du have privilegier på filer på værtssystemet, da vi kører containeren i uprivilegeret tilstand. På baggrund af disse oplysninger kan du vurdere risikoen ved at inkludere udvidelser i jupyter lab.

Oprettet IPython-notesbøger (sider i jupyter lab) vil nu blive oprettet i brugerens hjemmemappe - /home/jupyter, men vores planer er at dele data (share) mellem værten og containeren, så vend tilbage til konsollen og stop jupyter lab ved at udføre genvejstasten - CTRL+C og svarer y efter anmodning. Afslut derefter brugerens interaktive session jupyter udfylde en genvejstast CTRL+D.

Deling af data med værten ^

For at dele data med værten skal du oprette en enhed i containeren, der giver dig mulighed for at gøre dette, og for at gøre dette skal du køre følgende kommando, hvor vi angiver følgende nøgler:

  • lxc config device add — Kommandoen tilføjer enhedskonfigurationen
  • jupyter — ID for den container, som konfigurationen er tilføjet til
  • hostfs — Enheds-id. Du kan indstille et hvilket som helst navn.
  • disk — Enhedstypen er angivet
  • path — Angiver stien i containeren, som LXD vil montere denne enhed på
  • source — Angiv kilden, stien til biblioteket på værten, som du vil dele med containeren. Angiv stien i henhold til dine præferencer
lxc config device add jupyterlab hostfs disk path=/mnt/hostfs source=/home/dv/projects/ipython-notebooks

Til kataloget /home/dv/projects/ipython-notebooks tilladelse skal indstilles til containerbrugeren, som i øjeblikket har et UID svarende til SubUID + UID, se kapitel Sikkerhed. Containerprivilegier i artiklen Grundlæggende funktioner i LXD - Linux containersystemer.

Indstil tilladelsen på værten, hvor ejeren vil være containerbrugeren jupyter, og variablen $USER vil angive din værtsbruger som en gruppe:

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

Hej Verden! ^

Hvis du stadig har en konsolsession åben i containeren med jupyter lab, og genstart den derefter med en ny nøgle --notebook-dir ved at indstille værdien /mnt/hostfs som stien til roden af ​​de bærbare computere i containeren til den enhed, vi oprettede i det forrige trin:

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

Gå derefter til siden http://10.0.5.5:8888 og opret din første bærbare computer ved at klikke på knappen på siden som vist på billedet nedenfor:

Sender Jupyter i LXD-kredsløb

Indtast derefter Python-koden, der viser klassikeren i feltet på siden Hello World!. Når du er færdig med at indtaste, tryk på CTRL+ENTER eller "afspil"-knappen på værktøjslinjen øverst for at få JupyterLab til at gøre dette:

Sender Jupyter i LXD-kredsløb

På dette tidspunkt er næsten alt klar til brug, men det vil være uinteressant, hvis vi ikke installerer yderligere Python-moduler (fuldgyldige applikationer), der kan udvide standardfunktionerne i Python betydeligt i jupyter labså lad os komme videre :)

P.S. Det interessante er, at den gamle implementering jupyter under kodenavn Jupyter Notebook er ikke gået væk og den eksisterer sideløbende med jupyter lab. For at skifte til den gamle version skal du følge linket og tilføje suffikset i adressen/tree, og overgangen til den nye version udføres med suffikset /lab, men det skal ikke angives:

Udvidelse af Pythons muligheder ^

I dette afsnit vil vi installere så kraftfulde Python-sprogmoduler som nusset, pandas, Matplotlib, IPyWidgets hvis resultater er integreret i bærbare computere jupyter lab.

Før du installerer de angivne Python-moduler gennem pakkehåndteringen pip vi skal først løse systemafhængigheder i Alpine Linux:

  • g++ — Nødvendig til kompilering af moduler, da nogle af dem er implementeret på sproget C + + og opret forbindelse til Python under kørsel som binære moduler
  • freetype-dev - afhængighed for Python-modulet Matplotlib

Installation af afhængigheder:

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

Der er et problem: i den nuværende tilstand af Alpine Linux-distributionen vil det ikke være muligt at kompilere den nye version af NumPy; en kompileringsfejl vil dukke op, som jeg ikke kunne løse:

FEJL: Kunne ikke bygge hjul til numpy, som bruger PEP 517 og ikke kan installeres direkte

Derfor vil vi installere dette modul som en systempakke, der distribuerer en allerede kompileret version, men lidt ældre end hvad der i øjeblikket er tilgængeligt på siden:

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

Installer derefter Python-moduler gennem pakkehåndteringen pip. Vær tålmodig, da nogle moduler vil kompilere og kan tage et par minutter. På min maskine tog kompileringen ~15 minutter:

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

Rydning af installationscaches:

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

Test af moduler i JupyterLab ^

Hvis du løber jupyter lab, genstart den, så de nyinstallerede moduler aktiveres. For at gøre dette skal du klikke på i en konsolsession CTRL+C hvor du har den kørende og ind y for at stoppe anmodningen og derefter starte igen jupyter lab ved at trykke på pil op på tastaturet for ikke at indtaste kommandoen igen og derefter Enter for at starte det:

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

Gå til siden http://10.0.5.5:8888/lab eller opdater siden i din browser, og indtast derefter følgende kode i en ny notesbogscelle:

%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

Du skulle få et resultat som på billedet nedenfor, hvor IPyWidgets genererer et UI-element på siden, der interagerer interaktivt med kildekoden, og også Matplotlib viser resultatet af koden i form af et billede som en funktionsgraf:

Sender Jupyter i LXD-kredsløb

Mange eksempler IPyWidgets du kan finde det i tutorials her

Hvad ellers? ^

Godt gået, hvis du blev og nåede helt til slutningen af ​​artiklen. Jeg har bevidst ikke postet et færdigt script i slutningen af ​​artiklen, der ville installere jupyter lab med "et klik" for at opmuntre arbejdere :) Men du kan gøre det selv, da du allerede ved hvordan, efter at have samlet kommandoerne i et enkelt Bash-script :)

Du kan også:

  • Indstil et netværksnavn til containeren i stedet for en IP-adresse ved at skrive det på en enkel måde /etc/hosts og skriv adressen i browseren http://jupyter.local:8888
  • Leg lidt med ressourcegrænsen for containeren, for dette læs kapitlet i grundlæggende LXD-funktioner eller få flere oplysninger på LXD-udviklerwebstedet.
  • Skift tema:

Sender Jupyter i LXD-kredsløb

Og meget mere du kan gøre! Det er alt. Jeg ønsker dig succes!

OPDATERING: 15.04.2020/18/30 XNUMX:XNUMX - Rettet fejl i kapitlet "Hej, verden!"
OPDATERING: 16.04.2020/10/00 XNUMX:XNUMX — Rettet og tilføjet tekst i beskrivelsen af ​​aktivering af extension manager jupyter lab
OPDATERING: 16.04.2020/10/40 XNUMX:XNUMX — Rettede fejl fundet i teksten og lidt ændret til det bedre kapitlet "Installation af grundlæggende software og opsætning af systemet"

Kilde: www.habr.com

Tilføj en kommentar