VS Code の Remote Development (Preview) を体験

VS Code 1.35.0 から Remote Development Extension (Preview) が使えるようになりました。

marketplace.visualstudio.com

ちなみに、このバージョンから VS Code は Stable と Insider という2つのリリースを出すことになり、それぞれのアイコンもリニューアルされています。

code.visualstudio.com

macOS の VS Code から VirtualBox の仮想マシン(Ubuntu) で Remote Development を使えるように設定してみます。事前に公開鍵認証で SSH できるようにしておく必要があります。

ゲスト OS 側 で /etc/ssh/sshd_config を編集して一時的にパスワード認証を有効化。

PubkeyAuthentication yes
PasswordAuthentication yes

sshd を再起動。

$ sudo systemctl restart sshd

macOS 側で公開鍵をゲスト OS に転送*1

$ ssh-copy-id masa@192.168.33.10
The authenticity of host '192.168.33.10 (192.168.33.10)' can't be established.
  :
Are you sure you want to continue connecting (yes/no)? yes
  :
Number of key(s) added:        1

Now try logging into the machine, with:   "ssh 'masa@192.168.33.10'"
and check to make sure that only the key(s) you wanted were added.

ゲスト OS 側 で SSH のパスワード認証をオフに戻して sshd を再起動。macOS 側で公開鍵認証でログインできることを確認。

$ ssh masa@192.168.33.10

Welcome to Ubuntu 18.04.2 LTS (GNU/Linux 4.15.0-54-generic x86_64)

masa@ubuntu-bionic:~$ 

VS Code に Remote Development をインストールしたら、接続設定を行います。

~/.ssh/config を指定。

f:id:kondoumh:20190706215413p:plain

接続先設定を追加。

f:id:kondoumh:20190706220102p:plain

接続開始。

f:id:kondoumh:20190706215615p:plain

接続に成功するとステータスバーがコネクト状態に。

f:id:kondoumh:20190706220255p:plain

フォルダビューに切り替えるとリモートのフォルダを開くように促されます。

f:id:kondoumh:20190706220801p:plain

Git のリポジトリを clone したフォルダを開くとローカルでプロジェクトを開いている感じになります。ターミナルを開くとすでに SSH 接続状態になっています。

f:id:kondoumh:20190706223255p:plain

当然、リモート側には開発環境を構築しておく必要があります。ホストマシンの VS Code にインストールした言語用拡張については、シンタックスハイライトは効いていますが、コード補完などは動いていません。ここで拡張ビューに切り替えるとリモートマシンのセクションができていて、リモート用に拡張をインストールできるようになっています。

f:id:kondoumh:20190706231257p:plain

Go 拡張をインストールすると、リモートマシンのセクションにアイコンが現れ、拡張に必要な go のライブラリもリモート側にインストールされました。

f:id:kondoumh:20190706231610p:plain

コード補完も効いており、ローカル用の Go 拡張の設定がそのまま適用されている模様。

f:id:kondoumh:20190706231958p:plain

プレビュー版でこの完成度は凄いです。

最近は、EC2 インスタンスやローカルの仮想マシンに SSH して作業することが増えて、マシンを作るたびに Emacs や tmux をインストールするのも面倒なので *2 苦手な Vim を使うことが増えてきています。プログラミング言語だけでなく、YAML の設定ファイルを編集したりするのも VS Code の拡張が使えて、フォルダ構成が一覧できる状態で作業できるのは非常に助かります。

*1:ゲスト OS の ~/.ssh/authorized_keys に追加されます。

*2:特に RHEL / CentOS では自分でビルドしないと最新版が使えなかったり

野良 Scrapbox アプリ - ページ一覧の自動リフレッシュ

Scrapbox Electron アプリのページ一覧画面。

f:id:kondoumh:20190703231901p:plain

社内 Scrapbox は頻繁に更新されるため、手動で画面をリフレッシュするのが面倒でした。社内プロジェクトはピン留めしたページが多いので手でスクロールするのも面倒。

そこで、ページ一覧画面がアクティブになったら自動で更新するようにしてみました。スクロール位置はそのままに、追加・更新されたページが上位に上がってきます。

f:id:kondoumh:20190703232938g:plain

更新通知も Slack から来てるのですが、頻繁すぎるのでオフにしています。自分のタイミングで更新情報が見れて地味に便利になりました。

Release v0.8.2 · kondoumh/sbe · GitHub

Magic Keyboard を再び iPad のコンパニオンに

MacBook Pro で Kubernetes 動かしてた時は Let's note を作業マシンにしてましが、その後 Kubernetes の検証環境を AWS / GCP に移して MacBook Pro に戻りました。Let's note に繋いで使っていた HHKB と Windows 用エルゴノミックマウスは MacBook Pro で使い続けてます。HHKB は macOS に最適化してましたし。

blog.kondoumh.com

HHKB 指先痛くならないし、エルゴノミックマウスも腱鞘炎に優しいのでもう Magic Keyboard と Magic Mouse には戻れなくなりました (Magic Trackpad は使ってますが)。

ということで余ってしまった Magic Keyboard JP。以前書きましたが iOS は Magic Keyboard JP のサポートが完璧です。

blog.kondoumh.com

去年これ買ってずっと放置してました。

blog.kondoumh.com

久々に引っ張り出して使ってみました。

f:id:kondoumh:20190621083446j:plain

やはり非常に快適です。フルピッチだし、JIS レイアウトだし、英数・かなで日本語入力切替できるし。iPad 自体には何も装着していないので取り外しの手間もなく、ポートレートでもランドスケープでも使えてよいです。考えてみると Smart Keyboard は高価で使い回し効かないし iPad 自体が重くなるので微妙ですね。

ただ、ケースとキーボードを合わせるとけっこう重量があります。同一コンセプトのこれが気になっています。Amazon JP ではまだお高いですが。

最近は Cloud9 を利用する頻度が増えましたが、iOS の Safari ではまだけっこうツラいです。iPadOS で提供されるというデスクトップクラスの Safari に期待がかかります。Web IDE は iOS 向けの最適化とか全然してないと思うので普通に使いやすくなるのではないでしょうか。

iPadOS になるとキーボードを使うシーン増えそうだし、Google がタブレット戦線から離脱した今となっては、当面 iPad がタブレットのメインストリームでしょう。iPadOS が期待通りなら iPad Air リニューアルして Magic Keyboard のコンビでやっていくのがいいのかなと考えたり。

Netlify で定期的に JSON をジェネレートして通知する

PWA のデプロイに利用した Netlfy。

blog.kondoumh.com

JSON を生成するプログラムをデプロイすれば JSON を置いて定期更新する用途にも使えるということで、Tumblr API で取得したデータから JSON を生成するだけの Node.js アプリを書いて Netlify にデプロイしました。

github.com

デプロイした JSON を別サイトの PWA から参照するために CORS の設定が必要です。_header ファイルを作り読み取りアクセスを許可するようにしておきました。

Netlify のビルドトリガーは GItHub へのコミットの他に Webhook を作成して経由で外部から起動することもできます。

f:id:kondoumh:20190620230902p:plain

あとは外部のサーバーから curl 叩く crontab が仕掛けられればいいだけです。それだけのために CircleCI とかでジョブを作るのもオーバーなので GCP の Cloud Scheduler で1日1回起動するようにしてみました。

f:id:kondoumh:20190620231612p:plain

Webhook URL と HTTP メソッド (POST)、unix-cron 形式で時刻と頻度を指定するだけです。

Netlify からはメールや Slack で通知が可能です。Slack のプライベートチャンネルに Webhook を作って、Netlify の Build & deploy の Deploy notifications でビルド開始、ビルド成功、ビルド失敗 のタイミングで通知するように設定しました。

f:id:kondoumh:20190620232113p:plain

全体像はこんな感じです (図にするほどのものでもありませんが)。

f:id:kondoumh:20190625005307p:plain

これで日々更新される JSON データが Web で取得可能になりましたので表示用の PWA アプリを作ってみました。

github.com

Vue の table コンポーネントにデータバインディングさせています。

f:id:kondoumh:20190625005913p:plain

ひとまず自分用に雑に作ったので、ちょいちょい手を入れていきたいと思います。

Windows Terminal (Preview) を試す

Windows Terminal の Preview が Microsoft Store に出ているというので見に行きました。

f:id:kondoumh:20190623225342p:plain

確かに出てましたが、Windows 10 バージョンが 1803 のため動作要件を満たしてません。

f:id:kondoumh:20190623225812p:plain

とりあえず Windows Update を地道にしてたら May 2019 Update 1903 がロールアウトで降ってきました。

f:id:kondoumh:20190623232539p:plain

そのままバージョンアップ。Windows Terminal も無事にインストールできました。

f:id:kondoumh:20190623230423p:plain

WSL を導入してない状態だと PowerShell と cmd がタブで起動できます。PowerShell がデフォルトになっているようです。

タブに設定のアイコンがあるので押してみると設定の JSON ファイルがシェル起動するようになっていて、デフォルトのエディタがないため関連付けの画面が出てきました。きっと正式リリースの時は何らか GUI 画面が提供されるのでしょう。

f:id:kondoumh:20190623234702p:plain

とりあえず JSON ファイルをメモ帳で開き編集。profiles のプロパティをいじって PowerShell の透明度を変更したりしてみました。

        {
            "acrylicOpacity" : 0.10000001639127731,
            "background" : "#012456",
            "closeOnExit" : true,
            "colorScheme" : "Campbell",
            "commandline" : "powershell.exe",
            "cursorColor" : "#FFFFFF",
            "cursorShape" : "bar",
            "fontFace" : "Consolas",
            "fontSize" : 10,
            "guid" : "{61c54bbd-c2c6-5271-96e7-009a87ff44bf}",
            "historySize" : 9001,
            "icon" : "ms-appx:///ProfileIcons/{61c54bbd-c2c6-5271-96e7-009a87ff44bf}.png",
            "name" : "Windows PowerShell",
            "padding" : "0, 0, 0, 0",
            "snapOnInput" : true,
            "startingDirectory" : "%USERPROFILE%",
            "useAcrylic" : true
        },

f:id:kondoumh:20190623234022p:plain

Windows 10 のおなじみの壁紙がかなりポップになっていますね。

次に Git for Windwos の bash の追加に挑戦。icon は png のみのようです。

        {
            "acrylicOpacity" : 0.44999998807907104,
            "closeOnExit" : true,
            "colorScheme" : "Campbell",
            "commandline" : "C:\\Program Files\\Git\\bin\\bash.exe",
            "cursorColor" : "#FFFFFF",
            "cursorShape" : "bar",
            "fontFace" : "Consolas",
            "fontSize" : 12,
            "guid" : "{c0a23c69-addf-41c8-a214-dc4af501d7ec}",
            "historySize" : 9001,
            "icon" : "C:\\Program Files\\Git\\git-bash.png",
            "name" : "bash",
            "padding" : "0, 0, 0, 0",
            "snapOnInput" : true,
            "startingDirectory" : "%USERPROFILE%",
            "useAcrylic" : true
        }

ファイルをセーブするとメニューは出ました。

f:id:kondoumh:20190624001619p:plain

bash の起動には Windows Terminal 自体の再起動が必要でした。

f:id:kondoumh:20190624002339p:plain

Git の Text UI tig も動きました。

f:id:kondoumh:20190624002900p:plain

ターミナル上の日本語の表示はできましたが、インラインの日本語入力はできず、文字消去もバイト単位。Vim では日本語表示ができていません。Git for Windows の mintty なみというわけにはまだ行かないようです。

それにしてもタブ付きのターミナルが標準で搭載されるというのは素晴らしいです。正式リリースが期待されます。

AWS での作業用に Cloud9 を活用する

GCP には Cloud Shell という Web ベースのターミナルが使えるので、ちょっと作業したい時ブラウザだけで完結できます。

cloud.google.com

AWS には 標準で使える ターミナルはありません。そのため、AWS CLI をローカルマシンにインストールして(そのため Python 環境をインストールして) 環境を作ったり、作業用の EC2 インスタンス作ったりしてました。

blog.kondoumh.com

以前、Cloud IDE を比較したとき初めて使った AWS Cloud9、今は Node.js のコードを書いたりするのに便利に使っています。

aws.amazon.com

IDE のサービスという認識のためターミナルをメインに使うという発想がありませんでした。考えてみたら SSH 不要なので可用性が高いです。環境構築も非常に簡単です。Cloud9 のポータルから Create environment をクリックして開始します。

f:id:kondoumh:20190615182458p:plain

EC2 インスタンスを利用して構築することがほとんどだと思います。Java 開発用の IDE として使うとかでなければ、t2.nano でも十分でしょう。Platform は CentOS ベースの Amazon Linux でも Ubuntu でもお好みで。30分後にインスタンス停止するのがデフォルトオプションなので安心です。

f:id:kondoumh:20190615191742p:plain

EC2 ではなく自前のサーバーに構築することも可能です。このオプションは Cloud 9 を定額の VPS で構築したい場合などに使えそうです。SSH の接続情報を指定することになります。

f:id:kondoumh:20190615192623p:plain

EC2 の場合は確認画面が出ますので構成を確認して Create Environment をクリックします。

f:id:kondoumh:20190615192728p:plain

構築が開始されます。

f:id:kondoumh:20190615203808p:plain

この時、裏では CloudFormation で Stack が作成され始めています。

aws.amazon.com

CloudFormation のスタックを確認してみます。EC2 のセキュリティグループとインスタンスが構築されていっていることが分かります。

f:id:kondoumh:20190615204908p:plain

構築はすぐに終わり IDE が起動します。

f:id:kondoumh:20190615211359p:plain

この時、EC2 管理画面では、t2.micro のインスタンスが起動しているのが確認できます。

f:id:kondoumh:20190615211645p:plain

AWS CLI も最初から使えます。

f:id:kondoumh:20190615205047p:plain

IDE を利用する場合はこれで完了ですが、EKS の CLI で作業をする場合などは、Cloud9 のテンポラリなセッションキーを消して Credential を書き換える必要があります。利用したい IAM ユーザーでターミナルを使用するために設定画面の AWS Settings の AWS managed temporary credentials をオフにします。

f:id:kondoumh:20190615213945p:plain

aws configure を実行して利用したい IAM のアクセスキー ID と秘密アクセスキーを入力します。

masa:~/environment $ aws configure
AWS Access Key ID [None]: XXXXXXXXXXXXXXXXX
AWS Secret Access Key [None]: XXXXXXXXXXXXXXXXXXXXXXXXXXX
Default region name [None]: ap-northeast-1
Default output format [None]: text

Cloud9 は短時間で環境が作れて、課金も微量で、ブラウザだけで作業が完結するので SSH 設定で消耗する必要がなくなりました。

Kubernetes ベースの機械学習基盤 Kubeflow をラップトップにデプロイする

機械学習を業務に適用するには、データの収集、機械学習モデルの作成、機械学習モデルを利用する API 開発、API を利用するアプリ開発、プロダクションへの適用、運用時の経年変化によるモデルの修正 といったプロセスで進めることになります。

Kubeflow は機械学習モデル作成、API 開発とデプロイまでをカバーする基盤ソフトウェアです。その実体は数多くの OSS の 集合体 (best-of-breed *1 ) となっています。

www.kubeflow.org

Kubeflow はその名の通り Kubernetes ネイティブなアプリなので Kubernetes クラスターにデプロイして使用します。GCP / EKS / AKS といったメジャーなマネージド Kubernetes はもちろん、ローカルの Minikube、kind *2 などにデプロイ可能です。

残念ながら現状、Docker for Desktop は Kubernetes のバージョンが 1.10.11 とやや古いので、最新版の Kubeflow はデプロイできません。Minikube だと VirtualBox 仮想マシンの分のオーバーヘッドがあるので Docker for Desktop のバージョンアップが待たれます。

MiniKF を使ったデプロイ

Kubeflow には MiniKF という Minikube ベースのディストリビューションが提供されており vagrant up するだけで試すことができます。Windows でも Mac でも Linux でも OK ですが、起動するだけでメモリは 12GB 以上必要です。

www.kubeflow.org

VirtualBox と Vagrant をインストールしておきます。

www.vagrantup.com

www.virtualbox.org

次に適当なディレクトリで vagrant init / up します。

$ vagrant init arrikto/minikf
$ vagrant up

VirtualBox は headless mode で動きますので Window は出ません。完了したら、次のようなメッセージが表示されます。

f:id:kondoumh:20190614131617p:plain

ブラウザで 10.10.10.10 を開くと次のような画面が出ます。

f:id:kondoumh:20190614131941p:plain

Web の画面にターミナルが出ていて、このまま Kubernetes クラスターの起動と Kubeflow のデプロイ作業を続けることになります。

指示通りブラウザで作業を継続してもいいですが、インストール対象のマシンがリモートの Linux だったりして SSH で作業している場合などは、仮想マシンをポートフォワードしてもターミナルとの通信でエラーになってしまいます。その場合、仮想マシンに SSH 接続して作業を続行できます。vagrant ssh でマシンに入って minikf コマンドを叩きます。

$ vagrant ssh

Last login: Wed Jun 12 13:42:56 2019 from 10.0.2.2


Welcome to MiniKF! Type "minikf" to ensure
everything is up and running.

$ minikf

f:id:kondoumh:20190614132347p:plain

初回は10分以上かかります。完了すると Web 画面がこのようになります。

f:id:kondoumh:20190614140904p:plain

10.10.10.10:8080 で Kubeflow のダッシュボードが開きます。

f:id:kondoumh:20190614141130p:plain

デプロイされた Kubeflow 環境に別マシンから接続したい場合、VirtualBox の設定でポートフォワーディングすれば OK です。

f:id:kondoumh:20190614141403p:plain

名前 プロトコル ホスト IP ホストポート ゲスト IP ゲストポート
任意 TCP 0.0.0.0 空きポート 10.10.10.10 8080

Vagrantfile に以下のように記述することも可能です。

Vagrant.configure("2") do |config|
  :
  config.vm.network "forwarded_port", guest: 8080, host: 8080, host_ip: "0.0.0.0"
  :
end

起動した状態で kubernetes の Service や Pod を見てみます。

vagrant@minikf:~$ kubectl -n kubeflow get svc

NAME                                     TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)             AGE
ambassador                               ClusterIP   10.101.145.42    <none>        80/TCP              17d
ambassador-admin                         ClusterIP   10.101.77.15     <none>        8877/TCP            17d
argo-ui                                  NodePort    10.111.146.214   <none>        80:32457/TCP        17d
centraldashboard                         ClusterIP   10.106.93.62     <none>        80/TCP              17d
jupyter-0                                ClusterIP   None             <none>        8000/TCP            17d
jupyter-lb                               ClusterIP   10.107.106.12    <none>        80/TCP              17d
jupyter-web-app                          ClusterIP   10.105.85.161    <none>        80/TCP              17d
katib-ui                                 ClusterIP   10.108.218.43    <none>        80/TCP              17d
kf-controller                            ClusterIP   10.103.123.244   <none>        80/TCP              17d
minio-service                            ClusterIP   10.111.170.236   <none>        9000/TCP            17d
ml-pipeline                              ClusterIP   10.104.125.126   <none>        8888/TCP,8887/TCP   17d
ml-pipeline-tensorboard-ui               ClusterIP   10.97.28.36      <none>        80/TCP              17d
ml-pipeline-ui                           ClusterIP   10.99.46.227     <none>        80/TCP              17d
mysql                                    ClusterIP   10.99.108.198    <none>        3306/TCP            17d
notebooks-controller                     ClusterIP   10.98.198.91     <none>        443/TCP             17d
profiles                                 ClusterIP   10.104.136.216   <none>        443/TCP             17d
studyjob-controller                      ClusterIP   10.109.150.25    <none>        443/TCP             17d
tf-job-dashboard                         ClusterIP   10.99.61.120     <none>        80/TCP              17d
vizier-core                              NodePort    10.108.253.190   <none>        6789:31426/TCP      17d
vizier-core-rest                         ClusterIP   10.107.7.132     <none>        80/TCP              17d
vizier-db                                ClusterIP   10.100.73.125    <none>        3306/TCP            17d
vizier-suggestion-bayesianoptimization   ClusterIP   10.110.135.67    <none>        6789/TCP            17d
vizier-suggestion-grid                   ClusterIP   10.108.29.137    <none>        6789/TCP            17d
vizier-suggestion-hyperband              ClusterIP   10.100.113.40    <none>        6789/TCP            17d
vizier-suggestion-random                 ClusterIP   10.102.11.44     <none>        6789/TCP            17d


vagrant@minikf:~$ kubectl -n kubeflow get pod
NAME                                                        READY   STATUS    RESTARTS   AGE
ambassador-6776b669f8-hx252                                 1/1     Running   6          17d
argo-ui-5dd54b58dd-zt8b8                                    1/1     Running   5          17d
centraldashboard-655cc9b87d-nfqvw                           1/1     Running   5          17d
jupyter-0                                                   1/1     Running   5          17d
jupyter-web-app-54c87dc6bd-jv474                            1/1     Running   5          17d
katib-ui-555897fdf7-zk6p8                                   1/1     Running   5          17d
kf-controller-bbc79fdbb-2pq6v                               1/1     Running   5          17d
metacontroller-0                                            1/1     Running   5          17d
minio-6f647575fb-97xzm                                      1/1     Running   4          17d
ml-pipeline-77ff6b76d8-wt9g5                                1/1     Running   5          17d
ml-pipeline-persistenceagent-6d4788b46f-8t9rz               1/1     Running   9          17d
ml-pipeline-scheduledworkflow-5cfd76dd45-2hhdb              1/1     Running   5          17d
ml-pipeline-ui-6586fc8cd9-mztfn                             1/1     Running   5          17d
ml-pipeline-viewer-controller-deployment-67cfc45b8c-kd78p   1/1     Running   9          17d
mysql-6ff979f77f-wldk4                                      1/1     Running   4          17d
notebooks-controller-68585fc8b6-r7j5m                       1/1     Running   8          17d
profiles-5bb5b5dc8-zkktm                                    1/1     Running   8          17d
pytorch-operator-55759ffb8d-kdjgn                           1/1     Running   5          17d
spartakus-volunteer-bbb4d6d7b-567pz                         1/1     Running   5          17d
studyjob-controller-fcd7fbcd6-m4dvc                         1/1     Running   8          17d
tf-job-dashboard-6ff5599fb-qfmnt                            1/1     Running   5          17d
tf-job-operator-79f967f447-f8skb                            1/1     Running   5          17d
vizier-core-76b54db47f-gdlwp                                1/1     Running   23         17d
vizier-core-rest-569dc8b789-v6hdn                           1/1     Running   5          17d
vizier-db-f5f495b5c-vs7l7                                   1/1     Running   4          17d
vizier-suggestion-bayesianoptimization-fbfd657b9-p9v72      1/1     Running   5          17d
vizier-suggestion-grid-66b858dfc5-rp2x9                     1/1     Running   5          17d
vizier-suggestion-hyperband-97cbfd98c-vqwt7                 1/1     Running   5          17d
vizier-suggestion-random-66c6f8889-fhrkb                    1/1     Running   5          17d
workflow-controller-c59cc89bc-z72tv                         1/1     Running   7          17d

25の Service、 29の Pod が起動してます。

vagrant@minikf:~$ docker ps | grep kubeflow | wc -l
60

コンテナの数にして60! かなりの規模ですね。試しに MiniKF を使わず素の Minikube 環境を作ってデプロイしてみたところ、起動するだけで 15GB 以上メモリを使ってしまいました。これでは様々なタスク用の Pod を起動する余裕はありません。MiniKF は起動直後は 12-3 GB ぐらいでちょっと余裕があるので、かなりチューニングされている模様です。

Jupyterlab、 Tensorflow、Pipeline などの機能が統合されています。argo-ui という Service が上がっています。argo は Kubernetes native なワークフローエンジンで CI/CD パイプラインの基盤にもなっています。

argoproj.github.io

JupyterLab の起動

JupyterLab を使ってみます。

Notebooks メニューで Notebook Servers メニューを開いて New Server ボタンをクリック。

f:id:kondoumh:20190614152413p:plain

Server 名を入力します。CPU やメモリ、ディスクなどのリソース割り当ても可能です。入力したら SPAWN をクリックしてサーバーを起動します。

f:id:kondoumh:20190614152613p:plain

しばらくするとサーバーが構築されます。

f:id:kondoumh:20190614152933p:plain

CONNECT をクリックすると JupyterLab が起動します。

f:id:kondoumh:20190614153127p:plain

普通に使えます。

f:id:kondoumh:20190614153152p:plain

この状態で、Pod を見てみると、JupyterLab 用の Pod が1つ増えていました。コンテナも2つ増加。

vagrant@minikf:~$ kubectl -n kubeflow get pod
NAME                                                        READY   STATUS    RESTARTS   AGE
  :
hoge-0                                                      1/1     Running   0          26m
jupyter-0                                                   1/1     Running   5          17d
jupyter-web-app-54c87dc6bd-jv474                            1/1     Running   5          17d
   :

vagrant@minikf:~$ docker ps | grep kubeflow | wc -l
62

Kubernetes のリソースとして JupyterLab の Server や Notebook がデプロイされサービスとして提供されていることが分かります。

Pipelines を動かしてみる

Pipelines も少し見てみます。

サンプルのパイプラインが最初からいくつかデプロイされてます。

f:id:kondoumh:20190615112216p:plain

コインを投げて結果を出力するサンプル。Pipeline の DSL である Condition (条件分岐) のデモのようです。

f:id:kondoumh:20190615112711p:plain

コインをトスする部分は Python のワンライナーをシェルで実行して、ファイルと標準出力に結果を出しています。

f:id:kondoumh:20190615113456p:plain

Condition DSL はこのように記述するようです。

f:id:kondoumh:20190615113702p:plain

実行した結果。condition-4 と condition-6 が発動して print-4 が実行されたみたいです。

f:id:kondoumh:20190615113915p:plain

ログ出力結果もパイプラインのノードごとに見ることができます。

f:id:kondoumh:20190615114308p:plain

kubectl で Pod の状態を見るとパイプライン用の Pod がデプロイ・実行されて完了状態になっています。

vagrant@minikf:~$ kubectl -n kubeflow get pod
NAME                                                            READY   STATUS              RESTARTS   AGE
  :
conditional-execution-pipeline-lk5qp-1114233284                 0/2     Completed           0          88m
  :

以上は、超簡単なサンプルでしたが、本格的な機械学習のパイプラインサンプルも入っています。TensorFlow を用いて、データの検証、変換、モデルの学習、モデルを使った予測、モデルの評価、モデルの Serving などを実行できるようです。

f:id:kondoumh:20190615115341p:plain

実行してみましたが、Pod の状態が、ContainerCreating のまま進みません。

vagrant@minikf:~$ kubectl -n kubeflow get pods

tfx-taxi-cab-classification-pipeline-example-5fq7b-4292043047   0/2     ContainerCreating   0          148m

Pod の詳細を describe してみたら、GCP の credentials ボリュームのマウントに失敗しているということで、ローカルの Minikube で動かすのは難しそうです。

vagrant@minikf:~$ kubectl -n kubeflow describe pod tfx-taxi-cab-classification-pipeline-example-5fq7b-4292043047
Name:               tfx-taxi-cab-classification-pipeline-example-5fq7b-4292043047
    :
Events:
  Type     Reason       Age                    From               Message
  ----     ------       ----                   ----               -------
  Warning  FailedMount  8m44s (x62 over 146m)  kubelet, minikube  Unable to mount volumes for pod "tfx-taxi-cab-classification-pipeline-example-5fq7b-4292043047_kubeflow(54dd9cc1-8f0c-11e9-97d8-0800271ba290)": timeout expired waiting for volumes to attach or mount for pod "kubeflow"/"tfx-taxi-cab-classification-pipeline-example-5fq7b-4292043047". list of unmounted volumes=[gcp-credentials]. list of unattached volumes=[podmetadata docker-sock gcp-credentials mlpipeline-minio-artifact pipeline-runner-token-8t2qs]
  Warning  FailedMount  2m27s (x80 over 149m)  kubelet, minikube  MountVolume.SetUp failed for volume "gcp-credentials" : secret "user-gcp-sa" not found

おわりに

Kubeflow はこのように、分析環境やワークフローなどをまとめて面倒見てくれる統合環境ですが、使いこなす上ではデータサイエンティストと Kubernetes に精通したエンジニアが協力し合うチーム体制が必要になりそうです。

*1:開発元に拘らず複数のソフトウェアを組み合わせて構成されたソリューション。Suites と対比される。

*2:https://github.com/kubernetes-sigs/kind コンテナ上に Kubernetes 環境を構築するツール