最近流行りのJupyter Notebook( http://jupyter.org/ )でkubectlコマンドを呼び出すことで、生きている手順書が作れるのでは?と思ったので、試してみることにしました。
このドキュメントではKubernetesクラスタの中にJupyter Notebookをデプロイし、そこから自身がデプロイされている、Kubernetesクラスタを操作する方法を紹介します。
前提条件
- minkube
- kubectl
はインストール済みとします。
minikubeによるKubernetesクラスタの作成
$ minikube start
Starting local Kubernetes v1.10.0 cluster...
Starting VM...
Getting VM IP address...
Moving files into cluster...
Setting up certs...
Connecting to cluster...
Setting up kubeconfig...
Starting cluster components...
Kubectl is now configured to use the cluster.
Loading cached images from config file.
python kernelをつかってみる
まずはシンプルな普通の機能を試してみます。
Jupyter Notebookのデプロイ
まずは公式で用意しているminimal-notebookのコンテナイメージを使ってみることにします。
apiVersion: apps/v1
kind: Deployment
metadata:
name: jupyter-notebook
labels:
app: jupyter-notebook
spec:
replicas: 1
selector:
matchLabels:
app: jupyter-notebook
template:
metadata:
labels:
app: jupyter-notebook
spec:
containers:
- name: minimal-notebook
image: jupyter/minimal-notebook:latest
ports:
- containerPort: 8888
command: ["start-notebook.sh"]
args: ["--NotebookApp.token=''"]
---
kind: Service
apiVersion: v1
metadata:
name: jupyter-notebook
spec:
type: NodePort
selector:
app: jupyter-notebook
ports:
- protocol: TCP
nodePort: 30040
port: 8888
targetPort: 8888
$ kubectl apply -f jupyter.yaml
デプロイしたサービスの確認
$ kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
jupyter-notebook NodePort 10.100.161.148 <none> 8888:30040/TCP 5m
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 25d
ブラウザからアクセス
まずminikubeのIPを確認します。
$ minikube ip
192.168.99.100
サービスのNodePortは30040なのでこの場合は下記のアドレスをブラウザで開きます。
notebookの作成
WebUIからPython 3の形式のNotebookを作成します。
試しに書いてみる
Jupyter NotebookはドキュメントをCellという単位で記述します。CellにはMarkDownのモードとコードのモードなどがあります。
コードのモードの時に普通にプログラムを書くとPythonとして解釈され、!
を前置するとシェルスクリプトとして解釈されます。
Shift+Enter
を押すことでそのコードを実行することができます。
kubectlを呼び出す
!
を前置することでシェルスクリプトが動くのでwget
コマンドでkubectl
のバイナリをダウンロードして、実行してみます。
実行したコマンドは下記です。
!wget https://storage.googleapis.com/kubernetes-release/release/v1.12.0/bin/linux/amd64/kubectl
!chmod 755 kubectl
!./kubectl get pod
権限は無いが、一応動いていることがわかります。
このシェルスクリプトはKubernetesにデプロイされたPodの中で動作しており、権限としてはデフォルトで作成されるdefault
という名前のServiceAccountの権限で動作します。(これらは環境変数によって設定されています。気になる方は!env
をNotebookで実行するとわかります)
権限を付与する
defaultのServiceAccountに権限を与えます。下記コマンドはviewという標準で用意されているRoleをdefaultというServiceAccountに紐づけています。
$ kubectl create rolebinding default-sa --clusterrole=view --serviceaccount=default:default
rolebinding.rbac.authorization.k8s.io/default-sa created
再度実行すると、実行できました!
これがやりたかったことです!
一度全て削除する
次のステップに行く前に一度デプロイしたjupyter notebookを削除します。
$ kubectl delete -f jupyter.yaml
deployment.apps "jupyter-notebook" deleted
service "jupyter-notebook" deleted
bash kernelをつかってみる
ここまでで、Jupyter Notebookでkubectl
が実行できることがわかりましたが、実行する時に先頭に!
をつけるのがどうにも煩わしいです。
これはPython kernelを使っているためデフォルトとしてPythonのコードとして動作しているからです。
そこで、Bash kernelを使うことでもっと素直にシェルスクリプトが実行できるようにしてみましょう。
Dockerイメージの作成
bash kernelの入ったDockerイメージが見当たらなかったので自分で作ります。
また出力を等幅フォントにすることで、出力結果が綺麗に表示されるようにしています。
FROM jupyter/minimal-notebook
USER jovyan
# Make sure not to create a cache dir else NB_UID switching
# will hit issues.
RUN /opt/conda/bin/pip install --no-cache-dir bash_kernel
RUN /opt/conda/bin/python -m bash_kernel.install
RUN mkdir -p ~/.jupyter/custom && echo '.CodeMirror pre, .output pre { font-family: Monaco, monospace; }' > ~/.jupyter/custom/custom.css
USER root
minikubeのDockerを使ってビルドします。
$ eval $(minikube docker-env)
$ docker build -t bash-notebook:v1.0 .
Sending build context to Docker daemon 3.584kB
Step 1/6 : FROM jupyter/minimal-notebook
---> 400c44c4a7a7
Step 2/6 : USER jovyan
---> 858a23692f3d
Step 3/6 : RUN /opt/conda/bin/pip install --no-cache-dir bash_kernel
---> 33313772919f
Step 4/6 : RUN /opt/conda/bin/python -m bash_kernel.install
---> 6ce76d215977
Step 5/6 : RUN mkdir -p ~/.jupyter/custom && echo '.CodeMirror pre, .output pre { font-family: Monaco, monospace; }' > ~/.jupyter/custom/custom.css
---> ebbcec57eea2
Step 6/6 : USER root
---> feb1400abc10
Successfully built feb1400abc10
Successfully tagged bash-notebook:v1.0
デプロイ
下記のようにマニフェストを変更してデプロイします。
apiVersion: apps/v1
kind: Deployment
metadata:
name: jupyter-notebook
labels:
app: jupyter-notebook
spec:
replicas: 1
selector:
matchLabels:
app: jupyter-notebook
template:
metadata:
labels:
app: jupyter-notebook
spec:
containers:
- name: minimal-notebook
image: bash-notebook:v1.0 # イメージ名を変更
imagePullPolicy: IfNotPresent # minikube内のイメージを使う
ports:
- containerPort: 8888
command: ["start-notebook.sh"]
args: ["--NotebookApp.token=''"]
---
kind: Service
apiVersion: v1
metadata:
name: jupyter-notebook
spec:
type: NodePort
selector:
app: jupyter-notebook
ports:
- protocol: TCP
nodePort: 30040
port: 8888
targetPort: 8888
$ kubectl apply -f jupyter-bash.yaml
deployment.apps/jupyter-notebook created
service/jupyter-notebook created
ブラウザからアクセス
アドレスは前と同じです。
遊んでみる
感想
kubernetesのチュートリアルなどを作るのに良さそうと感じました。
参考
- Kubernetes上にjupyter notebookをデプロイする
- jupyer notebookのbash-kernelが便利という記事
- bash-kernel入りのDockerfileの作り方
- jupyter notebookのフォントを等幅にする
- minikubeでローカルのdocker imageを使う