avatarYao-Jen Kuo

Free AI web copilot to create summaries, insights and extended knowledge, download it at here

4761

Abstract

ast1-c </span> <span class="hljs-comment">--cluster-version latest </span> jhub</pre></div><p id="b6c6">需要自行調整輸入的參數有:</p><ul><li>zone:調整輸入為 asia-east1-c 指向台灣彰化縣的機房,可供選擇的清單可以參考 <a href="https://cloud.google.com/compute/docs/regions-zones/#available">https://cloud.google.com/compute/docs/regions-zones/#available</a></li><li>CLUSTERNAME:我們調整輸入為 jhub</li></ul><p id="5499">執行完畢後可以使用 <code>kubectl get node</code> 指令檢查叢集是否已經啟動;接下來的指令是將帳號調整為叢集管理員權限。</p><div id="b273"><pre>kubectl <span class="hljs-keyword">create</span> clusterrolebinding <span class="hljs-keyword">cluster</span>-<span class="hljs-keyword">admin</span>-binding
<span class="hljs-comment">--clusterrole=cluster-admin </span> <span class="hljs-comment">--user=<GOOGLE-EMAIL-ACCOUNT></span></pre></div><p id="b144">需要自行調整的參數是替換 <google-email-account> 為自己的 Gmail 帳號;最後的指令是做一個最適化調整,另外為學員未來所使用的 pods 建置為 user pods,與核心服務的 pods 區隔開來(註:pods 是 K8s 中可部署、管理的最小單位,可以想像成是一組資源隔絕的映像檔。)同樣也調整參數 zone 與 CLUSTERNAME。</google-email-account></p><div id="92d2"><pre>gcloud beta container <span class="hljs-keyword">node</span><span class="hljs-title">-pools</span> create user-pool
--machine-<span class="hljs-keyword">type</span> n1-standard-<span class="hljs-number">2</span>
--num-nodes <span class="hljs-number">0</span>
--enable-autoscaling
--min-nodes <span class="hljs-number">0</span>
--max-nodes <span class="hljs-number">3</span>
--<span class="hljs-keyword">node</span><span class="hljs-title">-labels</span> hub.jupyter.org/<span class="hljs-keyword">node</span><span class="hljs-title">-purpose</span>=<span class="hljs-keyword">user</span> <span class="hljs-title">
--node-taints</span> hub.jupyter.<span class="hljs-attr">org_dedicated=</span>user:NoSchedule
--zone asia-east1-c
--cluster jhub</pre></div><h2 id="67a5">步驟二:安裝 Helm</h2><p id="474a"><a href="https://helm.sh/">Helm</a> 是 K8s 的套件管理工具,可以協助我們安裝、升級和管理套件,Helm 之於 K8s 就像是 pip 之於 Python、npm 之於 nodejs 的關係;我們將使用 Helm chart 管理 K8s 設定檔,如此未來透過編輯 config.yaml 檔案即可完成 JupyterHub 的安裝與部署。</p><p id="504b">使用 <code>curl</code> 指令下載安裝指令並執行。</p><div id="80ea"><pre><span class="hljs-string">curl</span> <span class="hljs-string">https</span>://<span class="hljs-string">raw</span>.<span class="hljs-string">githubusercontent</span>.<span class="hljs-string">com</span>/<span class="hljs-string">helm</span>/<span class="hljs-string">helm</span>/<span class="hljs-string">master</span>/<span class="hljs-string">scripts</span>/<span class="hljs-built_in">get-helm-3</span> | <span class="hljs-string">bash</span></pre></div><h2 id="4b2f">步驟三:安裝 JupyterHub</h2><p id="0c7f">在終端機以 <code>openssl rand -hex 32</code> 指令生成一組金鑰,並複製起來。在家目錄新增 <code>config.yaml</code> 檔,並貼入以下的內容,替換 <RANDOM_HEX> 為前一個指令所生成的金鑰;官方文件使用的文字編輯器是 nano,我習慣使用 vim 所以直接以 <code>vim config.yaml</code> 指令新增設定檔,並新增金鑰至文件中後儲存離開。</p><div id="dae8"><pre><span class="hljs-symbol">proxy:</span> <span class="hljs-symbol"> secretToken:</span> <span class="hljs-string">"<RANDOM_HEX>"</span></pre></div><p id="5944">新增 JupyterHub Helm chart 為安裝做準備。</p><div id="74af"><pre><span class="hljs-symbol">helm</span> repo <span class="hljs-keyword">add</span> jupyterhub https:<span class="hljs-comment">//jupyterhub.github.io/helm-chart/</span> <span class="hljs-symbol">helm</span> repo update</pre></div><p id="125d">在家目錄執行安裝指令,請 Helm chart 透過 config.yaml 安裝 JupyterHub。</p><div id="8ff8"><pre><span class="hljs-attribute">RELEASE</span><span class="hljs-operator">=</span>jhub <span class="hljs-attribute">NAMESPACE</span><span class="hljs-operator">=</span>jhub</pre></div><div id="c5b7"><pre>helm upgrade <span class="hljs-attr">--cleanup-on-fail</span>
<span class="hljs-attr">--install</span> <span class="hljs-variable">RELEASE</span> jupyterhub/jupyterhub \ <span class="hljs-attr">--namespace</span> <span class="hljs-variable">NAMESPACE</span>
<span class="hljs-attr">--create-namespace</span>
<span class="hljs-attr">--version</span>=<span class="hljs-number">0.9</span>.<span class="hljs-number">0</span>
<span class="hljs-attr">--values</span> config.yaml</pre></div><h2 id="c942">步驟四:設定網域名稱</h2><p id="ecbb">JupyterHub 安裝完畢之後,可使用指令 <code>kubectl get service — namespace jhu</code> 查詢可以透過哪一組 IP 位址登入 JupyterHub,在 (proxy-public, EXTERNAL-IP) 就能檢視該組 IP。</p><p id="5af5">將 proxy-public 所對應的 EXTERNAL-IP 複製貼上至瀏覽器網址列即可來到 JupyterHub 的登入頁面;此時可以注意到登入頁面有一個安全連線的警告訊息,值得注意的是,<b>必須</b>在設定完網域名稱後才能進行 HTTPS 設定。</p><figure id="fb16"><img src="https://cdn-images-1.readmedium.com/v2/resize:fit:800/0*Su2QMBKaE3t6gts9.png"><figcaption>JupyterHub 的登入頁面</figcaption></figure><p id="f032">前往網域名稱供應商做好設定,以我的例子來說是從既有的網域新增一個子網域,那麼就要新增一筆 A 記錄對應 JupyterHub 的 EXTERNAL-IP。</p><div id="294f"><pre>A jhub <span class="hljs-t

Options

ag"><<span class="hljs-name">YOUR_JHUB_EXTERNAL_IP</span>></span></pre></div><p id="ac68">稍微等待一下,將 jhub.YOUR-DOMAIN-NAME 輸入至瀏覽器網址列,就可以來到 JupyterHub 的登入頁面,接著才能設定 HTTPS。</p><h2 id="3342">步驟五:設定 HTTPS</h2><p id="62d4">JupyterHub 使用 <a href="https://letsencrypt.org/">Let’s Encrypt</a> 服務自動產生 HTTPS 憑證,我們只需要透過編輯 config.yaml 就可以完成設定,在 config.yaml 中的 proxy 項目下加入 HTTPS 設定後儲存文件離開。</p><div id="a108"><pre><span class="hljs-symbol">proxy:</span> <span class="hljs-symbol"> secretToken:</span> <span class="hljs-string">"<RANDOM_HEX>"</span> <span class="hljs-symbol"> https:</span> <span class="hljs-symbol"> enabled:</span> true <span class="hljs-symbol"> hosts:</span> - <span class="hljs-params"><YOUR-DOMAIN-NAME></span> <span class="hljs-symbol"> letsencrypt:</span> <span class="hljs-symbol"> contactEmail:</span> <span class="hljs-params"><YOUR-EMAIL-ADDRESS></span></pre></div><p id="9c4c">每一次更新 config.yaml 設定檔後都需要執行 <code>helm upgrade</code> 指令讓更新生效。</p><div id="21c7"><pre><span class="hljs-attribute">RELEASE</span><span class="hljs-operator">=</span>jhub <span class="hljs-attribute">NAMESPACE</span><span class="hljs-operator">=</span>jhub</pre></div><div id="c2d0"><pre>helm upgrade <span class="hljs-attr">--cleanup-on-fail</span>
<span class="hljs-attr">--install</span> <span class="hljs-variable">RELEASE</span> jupyterhub/jupyterhub \ <span class="hljs-attr">--namespace</span> <span class="hljs-variable">NAMESPACE</span>
<span class="hljs-attr">--create-namespace</span>
<span class="hljs-attr">--version</span>=<span class="hljs-number">0.9</span>.<span class="hljs-number">0</span>
<span class="hljs-attr">--values</span> config.yaml</pre></div><p id="eeff">如果有發現找不到 Helm 指令的情況,可以重新安裝 Helm 之後在執行 <code>helm upgrade</code> 指令。</p><h2 id="a735">步驟六:設定 GitHub OAuth</h2><p id="efdc">截至目前為止,我們所建置好的 JupyterHub with K8s 可以透過 jhub.YOUR-DOMAIN-NAME 讓任何人註冊登入使用,還需要再設定 GitHub OAuth,讓管理員能夠驗證上課學員。</p><p id="e96f">透過帳戶圖片、設定(Settings)來到開發者設定(Developer settings),點選 OAuth Apps 然後新增 OAuth Apps。</p><figure id="add7"><img src="https://cdn-images-1.readmedium.com/v2/resize:fit:800/1*0nf_54_Oy5oPKRjgDYyLLA.png"><figcaption>新增 OAuth Apps</figcaption></figure><p id="1ce8">為新增的 OAuth App 註冊獲得一組 Client ID 與 Client Secret。</p><figure id="161c"><img src="https://cdn-images-1.readmedium.com/v2/resize:fit:800/1*VVMWO3_W7tYgvxvZCu7EUg.png"><figcaption>為新增的 OAuth App 註冊</figcaption></figure><p id="22af">在 config.yaml 設定檔中的 auth 項目新增 OAuth App 的 Client ID、Client Secret 以及 Callback URL。</p><div id="f289"><pre><span class="hljs-symbol">auth:</span> <span class="hljs-symbol"> type:</span> github <span class="hljs-symbol"> github:</span> <span class="hljs-symbol"> clientId:</span> <span class="hljs-string">"<y0urg1thubc1ient1d>"</span> <span class="hljs-symbol"> clientSecret:</span> <span class="hljs-string">"<an0ther1ongs3cretstr1ng>"</span> <span class="hljs-symbol"> callbackUrl:</span> <span class="hljs-string">"https://jhub.YOUR-DOMAIN-NAME/hub/oauth_callback"</span></pre></div><p id="483a">設定完成 OAuth App 之後,學員只要註冊有 GitHub 帳號就可以登入使用 JupyterHub,最後是將課堂學員的 GitHub 帳戶新增到白名單(whitelist)中,文件儲存離開後,也別忘了再執行一次 <code>helm update</code> 的指令。</p><div id="4357"><pre><span class="hljs-symbol">auth:</span> <span class="hljs-symbol"> type:</span> github <span class="hljs-symbol"> github:</span> <span class="hljs-symbol"> clientId:</span> <span class="hljs-string">"<y0urg1thubc1ient1d>"</span> <span class="hljs-symbol"> clientSecret:</span> <span class="hljs-string">"<an0ther1ongs3cretstr1ng>"</span> <span class="hljs-symbol"> callbackUrl:</span> <span class="hljs-string">"https://jhub.YOUR-DOMAIN-NAME/hub/oauth_callback"</span> <span class="hljs-symbol"> whitelist:</span> <span class="hljs-symbol"> users:</span> - student1 - student2 <span class="hljs-meta"># ...</span></pre></div><p id="4db7">大功告成!我們順利完成了步驟一到六,建置了一個有持續性的 JupyterHub with K8s 可以讓學員以 GitHub 帳號登入使用!</p><h2 id="af73">延伸閱讀</h2><div id="c053" class="link-block"> <a href="https://zero-to-jupyterhub.readthedocs.io/en/latest/index.html"> <div> <div> <h2>Zero to JupyterHub with Kubernetes - Zero to JupyterHub with Kubernetes 0.0.1-set.by.chartpress…</h2> <div><h3>JupyterHub allows users to interact with a computing environment through a webpage. As most devices have access to a…</h3></div> <div><p>zero-to-jupyterhub.readthedocs.io</p></div> </div> <div> <div style="background-image: url(https://miro.readmedium.com/v2/resize:fit:320/)"></div> </div> </div> </a> </div></article></body>

JupyterHub with K8s 步驟一到六

在 GCP Kubernetes Engines 建置 JupyterHub 的筆記

Photo by Luciano Resende on Jupyter Blog

A multi-user version of the notebook designed for companies, classrooms and research labs.

Project Jupyter | JupyterHub

TL; DR

依循 Zero to JupyterHub with Kubernetes 官方文件,建置一個讓學員以 GitHub 帳號登入使用有持續性(Persistent)的 Jupyter Notebook 伺服器。

緣起

雖然很清楚多數學員的使用習慣其實還是「本機端」開發環境,但是伴隨著作業系統、Python 版本、開發介面還有環境模組管理套件這四個面向的排列組合,常在一開始就容易讓人(不管是學員或老師)覺得有些疲憊:

  • 作業系統:Windows、macOS、Linux
  • Python 版本:Python.org、Anaconda
  • 開發介面:IDLE、PyCharm、Spyder、Jupyter Notebook、Visual Studio Code
  • 環境模組管理套件:venv、pip、conda

當然我並不覺得可以完全不用理會環境建置的議題,只是以 Python 多樣化的使用管理排列組合,更會希望學員是在已經對 Python 還有命令列熟悉的情況下,再比較完整地認識該怎麼在一台電腦中設定 Python、PATH、虛擬環境還有專案管理。

為什麼使用 JupyterHub with K8s

假如希望可以跳過本機端開發環境建置切入教學的主題,簡單來說就是讓學員只需要透過「瀏覽器」跟「網路」就可以進行程式撰寫跟輸出檢視;以資料科學開發介面的 Jupyter Notebook 來說,符合這個特性的選項有三個:

  1. Google Colab:Google 文件版的 Jupyter Notebook,可以即時互動、協作,缺點是沒有終端機介面、沒有文字編輯器介面、不能將資料與筆記本一起共享;
  2. BinderHub:奠基於 repo2docker 技術的 JupyterHub,可以開啟終端機、使用文字編輯器以及共享資料集;缺點是無持續性(Non-persistent)以及閒置斷線時間過短(10 分鐘),不過這算是無可厚非的,畢竟 BinderHub 並不需要使用者註冊登入且沒有收費;
  3. JupyterHub:多人版本的 Jupyter 伺服器,可以開啟終端機、使用文字編輯器、共享資料集、有持續性(Persistent)以及閒置斷線時間可以由管理員設定。

而 JupyterHub 其實也分兩個版本:

由於我的 JupyterHub 教學場景是一個學期的三學分課程,在這一個學期中,學員的使用頻率應該有很大的變異性,可能在課堂進行、作業繳交期限以及期中期末考試這些特定的時段才會有比較大的用量,我選擇了 JupyterHub with K8s。

步驟一到六

步驟一到六基本上就是依循 Zero to JupyterHub with Kubernetes 官方文件的指引,並在過程中加入一些容易忽略的備註。

在開始之前,請注意一個預設的 JupyterHub with K8s 每天的基本花費約 5 塊美金,如果讀者只想試著操作一遍,事後請務必記得將專案關閉刪除。

  1. 建置 Kubernetes Engine
  2. 安裝 Helm
  3. 安裝 JupyterHub
  4. 設定網域名稱
  5. 設定 HTTPS
  6. 設定 GitHub OAuth

步驟一:建置 Kubernetes Engine

登入自己的 Google 雲端平台 https://console.cloud.google.com/ 建立一個新專案:JupyterHub with K8s。

建立一個新專案

來到新專案的儀表板之後,點選 Go to APIs overview。

點選 Go to APIs overview

點選 ENABLE APIS AND SERVICES。

點選 ENABLE APIS AND SERVICES

在搜尋文字方框中輸入 Kubernetes Engine API。

在搜尋文字方框中輸入 Kubernetes Engine API

點選 Kubernetes Engine API。

點選 Kubernetes Engine API

啟動 Kubernetes Engine API。

啟動 Kubernetes Engine API

Google 雲端平台會花費一些時間啟動 Kubernetes Engine API ,請務必記得操作這個步驟,否則接下來在 Cloud Shell 的指令將發生錯誤;接著在右上角點選 Activate Cloud Shell。

在右上角點選 Activate Cloud Shell

Cloud Shell 啟動之後,輸入指令建置叢集(cluster)

gcloud container clusters create \
  --machine-type n1-standard-2 \
  --num-nodes 2 \
  --zone asia-east1-c \
  --cluster-version latest \
  jhub

需要自行調整輸入的參數有:

執行完畢後可以使用 kubectl get node 指令檢查叢集是否已經啟動;接下來的指令是將帳號調整為叢集管理員權限。

kubectl create clusterrolebinding cluster-admin-binding \
  --clusterrole=cluster-admin \
  --user=<GOOGLE-EMAIL-ACCOUNT>

需要自行調整的參數是替換 為自己的 Gmail 帳號;最後的指令是做一個最適化調整,另外為學員未來所使用的 pods 建置為 user pods,與核心服務的 pods 區隔開來(註:pods 是 K8s 中可部署、管理的最小單位,可以想像成是一組資源隔絕的映像檔。)同樣也調整參數 zone 與 CLUSTERNAME。

gcloud beta container node-pools create user-pool \
  --machine-type n1-standard-2 \
  --num-nodes 0 \
  --enable-autoscaling \
  --min-nodes 0 \
  --max-nodes 3 \
  --node-labels hub.jupyter.org/node-purpose=user \
  --node-taints hub.jupyter.org_dedicated=user:NoSchedule \
  --zone asia-east1-c \
  --cluster jhub

步驟二:安裝 Helm

Helm 是 K8s 的套件管理工具,可以協助我們安裝、升級和管理套件,Helm 之於 K8s 就像是 pip 之於 Python、npm 之於 nodejs 的關係;我們將使用 Helm chart 管理 K8s 設定檔,如此未來透過編輯 config.yaml 檔案即可完成 JupyterHub 的安裝與部署。

使用 curl 指令下載安裝指令並執行。

curl https://raw.githubusercontent.com/helm/helm/master/scripts/get-helm-3 | bash

步驟三:安裝 JupyterHub

在終端機以 openssl rand -hex 32 指令生成一組金鑰,並複製起來。在家目錄新增 config.yaml 檔,並貼入以下的內容,替換 <RANDOM_HEX> 為前一個指令所生成的金鑰;官方文件使用的文字編輯器是 nano,我習慣使用 vim 所以直接以 vim config.yaml 指令新增設定檔,並新增金鑰至文件中後儲存離開。

proxy:
  secretToken: "<RANDOM_HEX>"

新增 JupyterHub Helm chart 為安裝做準備。

helm repo add jupyterhub https://jupyterhub.github.io/helm-chart/
helm repo update

在家目錄執行安裝指令,請 Helm chart 透過 config.yaml 安裝 JupyterHub。

RELEASE=jhub
NAMESPACE=jhub
helm upgrade --cleanup-on-fail \
  --install $RELEASE jupyterhub/jupyterhub \
  --namespace $NAMESPACE \
  --create-namespace \
  --version=0.9.0 \
  --values config.yaml

步驟四:設定網域名稱

JupyterHub 安裝完畢之後,可使用指令 kubectl get service — namespace jhu 查詢可以透過哪一組 IP 位址登入 JupyterHub,在 (proxy-public, EXTERNAL-IP) 就能檢視該組 IP。

將 proxy-public 所對應的 EXTERNAL-IP 複製貼上至瀏覽器網址列即可來到 JupyterHub 的登入頁面;此時可以注意到登入頁面有一個安全連線的警告訊息,值得注意的是,必須在設定完網域名稱後才能進行 HTTPS 設定。

JupyterHub 的登入頁面

前往網域名稱供應商做好設定,以我的例子來說是從既有的網域新增一個子網域,那麼就要新增一筆 A 記錄對應 JupyterHub 的 EXTERNAL-IP。

A        jhub        <YOUR_JHUB_EXTERNAL_IP>

稍微等待一下,將 jhub.YOUR-DOMAIN-NAME 輸入至瀏覽器網址列,就可以來到 JupyterHub 的登入頁面,接著才能設定 HTTPS。

步驟五:設定 HTTPS

JupyterHub 使用 Let’s Encrypt 服務自動產生 HTTPS 憑證,我們只需要透過編輯 config.yaml 就可以完成設定,在 config.yaml 中的 proxy 項目下加入 HTTPS 設定後儲存文件離開。

proxy:
  secretToken: "<RANDOM_HEX>"
  https:
    enabled: true
    hosts:
      - <YOUR-DOMAIN-NAME>
    letsencrypt:
      contactEmail: <YOUR-EMAIL-ADDRESS>

每一次更新 config.yaml 設定檔後都需要執行 helm upgrade 指令讓更新生效。

RELEASE=jhub
NAMESPACE=jhub
helm upgrade --cleanup-on-fail \
  --install $RELEASE jupyterhub/jupyterhub \
  --namespace $NAMESPACE \
  --create-namespace \
  --version=0.9.0 \
  --values config.yaml

如果有發現找不到 Helm 指令的情況,可以重新安裝 Helm 之後在執行 helm upgrade 指令。

步驟六:設定 GitHub OAuth

截至目前為止,我們所建置好的 JupyterHub with K8s 可以透過 jhub.YOUR-DOMAIN-NAME 讓任何人註冊登入使用,還需要再設定 GitHub OAuth,讓管理員能夠驗證上課學員。

透過帳戶圖片、設定(Settings)來到開發者設定(Developer settings),點選 OAuth Apps 然後新增 OAuth Apps。

新增 OAuth Apps

為新增的 OAuth App 註冊獲得一組 Client ID 與 Client Secret。

為新增的 OAuth App 註冊

在 config.yaml 設定檔中的 auth 項目新增 OAuth App 的 Client ID、Client Secret 以及 Callback URL。

auth:
  type: github
  github:
    clientId: "<y0urg1thubc1ient1d>"
    clientSecret: "<an0ther1ongs3cretstr1ng>"
    callbackUrl: "https://jhub.YOUR-DOMAIN-NAME/hub/oauth_callback"

設定完成 OAuth App 之後,學員只要註冊有 GitHub 帳號就可以登入使用 JupyterHub,最後是將課堂學員的 GitHub 帳戶新增到白名單(whitelist)中,文件儲存離開後,也別忘了再執行一次 helm update 的指令。

auth:
  type: github
  github:
    clientId: "<y0urg1thubc1ient1d>"
    clientSecret: "<an0ther1ongs3cretstr1ng>"
    callbackUrl: "https://jhub.YOUR-DOMAIN-NAME/hub/oauth_callback"
  whitelist:
    users:
      - student1
      - student2
      # ...

大功告成!我們順利完成了步驟一到六,建置了一個有持續性的 JupyterHub with K8s 可以讓學員以 GitHub 帳號登入使用!

延伸閱讀

Jupyterhub
Kubernetes
Recommended from ReadMedium