將 Jupyter 發射到 LXD 軌道

您是否曾經必須在 Linux 中嘗試程式碼或系統實用程序,以便不必擔心基本系統,也不必在應以 root 權限運行的程式碼中出現錯誤時破壞所有內容?

但是,假設您需要在一台計算機上測試或運行由各種微服務組成的整個集群,那又如何呢? 一百甚至一千?

透過虛擬機管理程式管理虛擬機,這些問題可以而且將會得到解決,但代價是什麼? 例如,基於 Alpine Linux 發行版的 LXD 中的容器僅消耗 7.60MB RAM,以及啟動後根分區所佔用的位置 9.5MB! 你覺得怎麼樣,伊隆馬斯克? 我建議查看 LXD的基本能力-Linux中的容器系統

在大致了解LXD 容器是什麼之後,讓我們進一步思考,如果有這樣一個收割機平台,您可以在其中安全地為主機運行程式碼、產生圖表、動​​態(互動式)地將UI 小工具與您的程式碼連結起來,用二十一點...格式的文字補充程式碼? 某種互動部落格? 哇……我​​想要! 想! 🙂

看看貓下面我們將在容器中啟動的地方 Jupyter實驗室 - 下一代使用者介面而不是過時的Jupyter Notebook,我們還將安裝Python模組,例如 數字貨幣, 大熊貓, Matplotlib, IPyWidgets 這將允許您執行上面列出的所有操作並將其全部保存在一個特殊檔案中 - IPython 筆記型電腦。

將 Jupyter 發射到 LXD 軌道

軌道起飛計劃 ^

將 Jupyter 發射到 LXD 軌道

讓我們概述一個簡短的行動計劃,以便我們更容易實施上述方案:

  • 讓我們安裝並啟動一個基於分發包的容器 高山Linux。 我們將使用這個發行版,因為它旨在極簡主義,並且只會在其中安裝最必要的軟體,沒有多餘的軟體。
  • 讓我們在容器中新增一個額外的虛擬磁碟並為其命名 - hostfs 並將其掛載到根檔案系統。 該磁碟使得可以使用容器內給定目錄中的主機上的檔案。 因此,我們的數據將獨立於容器。 如果容器被刪除,資料將保留在主機上。 此外,該方案對於在多個容器之間共用相同的資料非常有用,而無需使用容器分發的標準網路機制。
  • 讓我們安裝 Bash、sudo、必要的庫,新增並配置系統用戶
  • 讓我們安裝 Python、模組並為它們編譯二進位依賴項
  • 讓我們安裝並啟動 Jupyter實驗室,自訂外觀,為其安裝擴充功能。

在本文中,我們將從啟動容器開始,我們不會考慮安裝和配置 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

讓我們使用 key 顯示 LXD 中的容器列表 -c 這顯示哪個 c列顯示:

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 shell

bash 完成
bash shell 的可程式完成

須藤
賦予某些使用者以 root 身分執行某些命令的能力

陰影
支援影子檔案和 PAM 的密碼和帳戶管理工具套件

數據
時區和夏令時資料來源

納米
具有增強功能的 Pico 編輯器克隆

此外,您可以透過安裝以下軟體包在系統手冊頁中安裝支援 - 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 為使用者安裝系統 shell /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 我們稍後將為其配置 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 ^

Jupyter實驗室 是一個Python應用程序,所以我們必須先安裝這個解釋器。 還, Jupyter實驗室 我們將使用 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

安裝 Jupyter實驗室 透過套件管理器 pip:

lxc exec jupyterlab -- python3 -m pip install jupyterlab

由於擴展在 Jupyter實驗室 是實驗性的,並未隨 jupyterlab 套件正式發布,因此我們必須手動安裝和設定它。

讓我們安裝 NodeJS 及其套件管理器 - NPM,因為 Jupyter實驗室 使用它們作為擴展:

lxc exec jupyterlab -- apk add nodejs npm

至擴展名 Jupyter實驗室 我們將安裝的工作正常,它們需要安裝在使用者目錄中,因為應用程式將從使用者啟動 jupyter。 問題是啟動命令中沒有可以傳遞到目錄的參數;應用程式只接受環境變量,因此我們必須定義它。 為此,我們將編寫變數導出命令 JUPYTERLAB_DIR 在使用者環境中 jupyter, 歸檔 .bashrc每次使用者登入時都會執行:

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

下一個命令將安裝一個特殊的擴充功能 - 擴充功能管理器 Jupyter實驗室:

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

現在一切準備就緒,等待首次發布 Jupyter實驗室,但我們仍然可以安裝一些有用的擴充功能:

  • 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"

現在運行以下兩個命令來首次運行它 Jupyter實驗室。 可以用一個命令來啟動它,但在這種情況下,你很難記住的啟動命令將被容器中的 bash 記住,而不是在主機上,因為主機上已經有足夠的命令將它們記錄在歷史中:)

以使用者登入容器 jupyter:

lxc exec jupyterlab -- su -l jupyter

接下來,運行 Jupyter實驗室 鍵和參數如下圖所示:

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

前往網頁瀏覽器中的位址 http://10.0.5.5:8888 然後在打開的頁面上輸入 象徵 您將在控制台中看到存取權限。 複製並貼上到頁面上,然後單擊 登入。 登入後,進入左側擴展選單,如下圖所示,啟動擴展管理器時會提示您安裝第三方擴展,以承擔安全風險,命令如下: JupyterLab開發 不負責:

將 Jupyter 發射到 LXD 軌道

然而,我們正在隔離整個 Jupyter實驗室 並將其放置在容器中,這樣需要並使用 NodeJS 的第三方擴充功能至少無法竊取磁碟上除我們在容器內開啟的資料之外的資料。 取得您在主機上的私人文檔 /home 來自容器的進程不太可能成功,如果成功,那麼您需要對主機系統上的檔案具有權限,因為我們在 非特權模式。 根據此信息,您可以評估將擴展包含在其中的風險 Jupyter實驗室.

建立 IPython 筆記本(頁面 Jupyter實驗室) 現在將在使用者的主目錄中建立 - /home/jupyter,但是我們的計劃是在主機和容器之間分割資料(共享),所以返回控制台並停止 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

你好,世界! ^

如果您仍然在容器中開啟控制台會話 Jupyter實驗室,然後用新密鑰重新啟動它 --notebook-dir 透過設定值 /mnt/hostfs 作為我們在上一步中創建的設備的容器中筆記型電腦根目錄的路徑:

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

然後進入頁面 http://10.0.5.5:8888 然後點擊頁面上的按鈕創建你的第一台筆記型電腦,如下圖所示:

將 Jupyter 發射到 LXD 軌道

然後,在頁面上的欄位中輸入將顯示經典的Python程式碼 Hello World!。 輸入完畢後,按 CTRL+ENTER 或頂部工具列上的「播放」按鈕讓 JupyterLab 執行此操作:

將 Jupyter 發射到 LXD 軌道

至此,幾乎一切都已準備就緒,可以使用了,但如果我們不安裝額外的 Python 模組(成熟的應用程式),這些模組可以顯著擴展 Python 的標準功能,那就沒什麼意思了。 Jupyter實驗室因此,讓我們繼續吧:)

PS 有趣的是舊的實現 朱皮特 在代號下 Jupyter筆記本 並沒有消失,並且與以下平行存在 Jupyter實驗室。 要切換到舊版本,請點擊連結並在地址中添加後綴/tree,並以前綴進行向新版本的過渡 /lab,但不必指定:

擴充 Python 的功能 ^

在本節中,我們將安裝強大的Python語言模組,例如 數字貨幣, 大熊貓, Matplotlib, IPyWidgets 其結果被整合到筆記型電腦中 Jupyter實驗室.

在透過套件管理器安裝列出的 Python 模組之前 pip 我們必須先解決 Alpine Linux 中的系統相依性:

  • g++ — 編譯模組所需,因為其中一些模組是用語言實現的 C + +中 並在運行時作為二進制模組連接到 Python
  • freetype-dev - Python 模組的依賴 Matplotlib

安裝依賴項:

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

有一個問題:在 Alpine Linux 發行版的當前狀態下,將無法編譯新版本的 NumPy;會出現一個我無法解決的編譯錯誤:

ERROR: 無法為使用 PEP 517 的 numpy 建造輪子,且無法直接安裝

因此,我們將將此模組安裝為系統包,分發已編譯的版本,但比網站上目前可用的版本稍舊:

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 中測試模組 ^

如果你正在跑步 Jupyter實驗室,重新啟動以便啟動新安裝的模組。 為此,請在控制台會話中按一下 CTRL+C 你運行它的地方並輸入 y 停止請求然後重新開始 Jupyter實驗室 按鍵盤上的向上箭頭,以免再次輸入指令,然後 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 元素,並且 Matplotlib 將程式碼的結果以圖片的形式顯示為函數圖:

將 Jupyter 發射到 LXD 軌道

很多例子 IPyWidgets 你可以在教程中找到它 這裡

還有什麼? ^

如果您堅持下來並讀到文章的最後,那就太好了。 我故意沒有在文章最後貼上出現成的安裝腳本 Jupyter實驗室 「一鍵點擊」來鼓勵員工:)但是您可以自己做,因為您已經知道如何操作,並將命令收集到單個 Bash 腳本中:)

你也可以:

  • 透過以簡單的方式編寫容器的網路名稱而不是 IP 位址 /etc/hosts 然後在瀏覽器中輸入地址 http://jupyter.local:8888
  • 嘗試使用容器的資源限制,為此請閱讀以下章節 基本 LXD 功能 或在 LXD 開發者網站上獲取更多資訊。
  • 更改主題:

將 Jupyter 發射到 LXD 軌道

您還可以做更多事! 就這樣。 祝你成功!

更新:15.04.2020 年 18 月 30 日 XNUMX:XNUMX - 更正了「Hello, World!」一章中的錯誤
更新:16.04.2020 年 10 月 00 日 XNUMX:XNUMX — 更正並添加了擴展管理器激活描述中的文本 Jupyter實驗室
更新:16.04.2020/10/40 XNUMX:XNUMX - 修正了文本中發現的錯誤,並稍微修改了「安裝基本軟體和設定係統」章節

來源: www.habr.com

添加評論