水底

ScalaとかC#とかk8sとか

#scala_kb で「scala.collection 再入門」をしゃべってきた

spark+dl4j+scalaで遊んだ話と悩んだが, 自分の確認の意味も含めて scala.collection について調べ直した. 内容としては scala.collection のよく使われる各データ構造がどのように表現されているかの概要, どのような場面で使うべきかに焦点を当て, 詳しいアルゴリズム(e.g. red-black tree の挙動)は省いた. 詳しい内容はスライドで見て頂ければと思う. また, scala.collection の適切な選択のためのフローチャートを用意した.

scala.collection選択フローチャート

doc.co

指摘や提案を歓迎します (特にフローチャート)

2016/7/10 23:00, @xuwei_k さんよりimmutable.Stackがdeprecatedであると教えて頂いたため, 発表時から修正を入れました. ありがとうございます.

sbtを使ってDeeplearning4jをSpark上で動かす(ver: 0.4-rc3.9)

Deeplearning4j(DL4J)をSpark上で動かしたかったがいろいろ問題点があったのでメモ. 最終的には動かすことに成功した.

sparkアプリケーションを動かすには

  • 一旦jarを作ってからspark-submitコマンドで利用する方法
    • sparkの環境が必要
  • アプリケーションに埋め込んでスタンドアロンに利用する方法
    • 事前にsparkの環境は必要ないがクラスタは利用できない

があるが, 今回は「とりあえず試したい」程度だったので後者を目標とした(ちなみにsetMasterを調整してsbt packageすれば簡単に前者のアプローチへ移行可能).

既存の問題点

  • 本記事のタイトル通り「sbtを使ってDL4JをSpark上で動かす時に使うプラグイン」として提供されている GitHub - deeplearning4j/dl4j-spark-ml が古い
  • そのサンプル実装とされている https://github.com/deeplearning4j/dl4j-spark-ml-examples が謎の404
  • とにかくドキュメントが少ない. 英語ですらほとんど見当たらない(sparkでdeeplearningとかやってる人多そうなのになんで…)
  • 適当にやってみるとライブラリのバージョン地獄に嵌まる

動かす

あまりに動かなかったのでDL4Jのgitterで聞きつつ実装したところなんとか動かすことが出来た.

特に注意が必要だったところだけ列挙する

  • 0.4-rc3.9からnd4j-x86は不要になり, nd4j-nativeのみで良くなった
  • nd4j-nativeを利用するにはclasspathTypesの指定と実行環境に合わせたclassifierの設定が必須
  • nd4j-nativend4j-cuda-7.5は併用できない
  • jackson-databindのバージョン依存がどうしようもないのでdependencyOverridesで固定する必要がある
  • dl4j-sparkが依存しているspark-coreが古いのでexcludeする
    (dl4j-spark-cdh5-examplesを参考にしたが互換大丈夫なのか確信が持てない…がこれをしないと依存解決できない)
  • 性質上OutOfMemoryErrorが出やすいのでヒープサイズを増やす必要がある
    • スタンドアロン(sbt)を利用 => sbt run時に-memで大きめの値を指定する
    • spark-submitを利用 => spark-submit--driver-memory--executor-memoryで大きめの値を指定する

どれか一つでも欠けているとコケるという…なかなかシビアである. 以下が作ったサンプルである. テストの内容は GitHub - deeplearning4j/dl4j-spark-cdh5-examples: Examples to run on CDH5 with Spark を参考にした. なお, CNNを利用するMNISTのサンプルはかなりのマシンパワーを利用するので注意が必要である.

github.com

分からなくなったら

ライブラリの特性上DL4JはND4Jと密に関係しているのでこちらも参照されたし. ダメそうならgitterで聞いてみると良い.

gitter.im

LDAPにSSHの認証をやらせてみた(nscd版)

LDAPRadius無線LANLinuxユーザとSSHの認証まとめたろw」と思ったのが発端. とりあえずLDAPSSHの公開鍵認証は動くようになった. まとまった情報があまり見つからなかったのでメモ.

概要

実験環境

  • (VM上の)Ubuntu16.04
  • dockerやssh環境を前提とする

どこまでやるの

docker上に公開鍵の情報を含むLDAPサーバを作成し, SSHの認証でそれを参照させる. 既存LinuxユーザとLDAP上のユーザを共存させ, 初ログインのLDAPユーザには自動的にホームディレクトリを作成する.

LDAPサーバ

LDAPサーバのdockerコンテナを建てる

docker run --name ldap-server -p 389:389 --env LDAP_ORGANISATION="Example" --env LDAP_DOMAIN="example.com" --env LDAP_ADMIN_PASSWORD="password" -d osixia/openldap:1.1.2

公開鍵に対応したスキーマの設定

dockerコンテナ内. 本来ビルド時でいいが, とりあえずdocker execで.

echo "dn: cn=openssh-lpk-openldap,cn=schema,cn=config
objectClass: olcSchemaConfig
cn: openssh-lpk-openldap
olcAttributeTypes: ( 1.3.6.1.4.1.24552.500.1.1.1.13 NAME 'sshPublicKey' DES
 C 'MANDATORY: OpenSSH Public key' EQUALITY octetStringMatch SYNTAX 1.3.6.1.4.
 1.1466.115.121.1.40 )
olcObjectClasses: ( 1.3.6.1.4.1.24552.500.1.1.2.0 NAME 'ldapPublicKey' DESC
  'MANDATORY: OpenSSH LPK objectclass' SUP top AUXILIARY MUST ( sshPublicKey $
  uid ) )" > /etc/ldap/schema/openssh-lpk-openldap.ldif

ldapadd -H ldapi:/// -f /etc/ldap/schema/openssh-lpk-openldap.ldif
ldapadd -H ldapi:/// -f /etc/ldap/schema/cosine.ldif
ldapadd -H ldapi:/// -f /etc/ldap/schema/inetorgperson.ldif
ldapadd -H ldapi:/// -f /etc/ldap/schema/nis.ldif

ldifファイルを作って公開鍵の情報を持ったユーザ追加(or ldapmodで既存ユーザに追加する)

dn: uid=karen,dc=example,dc=com
objectClass: inetOrgPerson
objectClass: posixAccount
objectClass: ldapPublicKey
uid: karen
cn: karen
sn: kujo
gn: karen
uidNumber: 11111
gidNumber: 11111
loginShell: /bin/bash
homeDirectory: /home/karen
mail: karen@example.com
userPassword: password
sshPublicKey: ssh-rsa AAAA略 #コメントは消しておいたほうがいいかも
ldapadd -H ldapi:/// -f karen.ldif

LDAPクライアント(SSH)

yumを使うディストロであればopenssh-ldapというパッケージがあるため, この項目と手法が異るので注意

LDAPクライアントに必要な物をインストールし有効にする

sudo apt install -y nscd ldap-auth-client #インストール時にLDAPサーバの情報を入力
sudo pam-auth-update #LDAPとCreate home directoryを有効にする

再設定は sudo dpkg-reconfigure ldap-auth-config で可能.

pam-auth-update時にCreate home directoryが出てこなかった場合

バージョンによってはデフォルトで用意されていないようなので自作する必要がある(e.g. ubuntu14.04)

新規作成 /usr/share/pam-configs/my_mkhomedir

Name: Create home directory on login
Default: yes
Priority: 0
Session-Type: Additional
Session-Interactive-Only: yes
Session:
    optional            pam_mkhomedir.so

sudo pam-auth-update --force

nsswitchの設定

/etc/nsswitch.confに以下のようにldap追記する.

passwd:    files ldap
shadow:    files ldap
group:    files ldap
sudo serivce nscd restart

SSHの認証にLDAP上の公開鍵を利用する設定

LDAP上の公開鍵を取得するスクリプトを作成(/opt/ssh-ldap/getPublicKey)

LDAPサーバの情報を設定する.

#!/bin/bash

uri=ldap://piyo #server uri
binddn=piyo #bind user
bindpw=piyo #pwd
base=piyo #base
uid=$1
ldapsearch -LLL -H ${uri} -w "${bindpw}" -D "${binddn}" -b "${base}" "(& (objectClass=posixAccount) (uid=${uid}))" "sshPublicKey" | sed -ne '2,$p' | sed -e 's/sshPublicKey: //g' | sed -e 's/^ //g' | tr -d '\n'

ユーザから不可視にする.

sudo chmod 700 -R /opt/ssh-ldap
sudo chown root:root -R /opt/ssh-ldap

SSHの設定(/etc/ssh/sshd_config)

以下を追記する.

AuthorizedKeysCommand /opt/ssh-ldap/getPublicKey
AuthorizedKeysCommandUser root
sudo service ssh reload

注意点

  • SSSDを利用する方法もありそちらのほうがよりスマートらしいがnscdと排他的で試していない. 近々実験予定.
  • /etc/ldap/slapd.confを編集して~という情報は古いから今すぐ投げ捨てろ
  • OpenSSH6.9未満(?)の場合はAuthorizedKeysCommandが利用できないためパッチを当てる必要があるらしい(要確認). 少なくとも, Ubuntu16.04で入る7.2では問題なかった.

ところでなんでSSH-CA認証の証明書はX.501じゃないの…

ニューラルネットを実装してみた話

github.com

『深層学習』(岡谷貴之):機械学習プロフェッショナルシリーズ|講談社BOOK倶楽部 を勉強がてら, 折角なので外部ライブラリを一切使わずにScalaフルスクラッチを行った. 俗にいう車輪の再発明だ. 確率的勾配法で誤差伝播を用いる単純なFFNNである. 使い方はREADME参照.

OOP的に書いたらわかりやすくなるかと思っていたがそんなことはなかった. 適当に書いたらタプル地獄に落ちかけた. かなり雑なコードで並列化もされていなため実用的には程遠いが, とりあえずMNISTの手書きデータを学習してくれたので良しとする.

いつの日かニューラルネットが俺の代わりに働く世界に期待を込めて.

Docker native(Windows)を2週間程使ってみた所感

最近メイン環境をMacからWinへ移行したがやはりテスト・開発・実行環境として*nix系が使いたい. ちょうどDocker nativeのβ版が来ていたため試用することにした. closed-βのため, invitation codeが必要だったが申請して数時間で発行された.

降ってきたインストーラを実行し言われるがままにインストール. 結果, Hyper-V上にMobyLinuxVMというAlpineのVMが立ち上がりその上でコンテナが走る環境が作成された. その後, 例えばPowerShell上で適当にdocker run -it -p 8080:80 --rm nginxとすることで問題なくコンテナの立ち上げに成功した. docker-composeも問題なく利用できた. また, Settings -> Manage shared drivesからチェックを入れることでhost(win) <-> MobyLinuxVM(alpine)間でボリュームが共有され, host(win) <-> containerでのボリューム共有が可能になった.

ただし, 問題が全く無いわけではない. 問題の一つとして, スリープ時の挙動が挙げられる. 明確な再現性はないが, 2, 3回に1回程度と比較的高い確率でdocker daemonがスリープからの復帰に失敗し, dockerが正常に利用できなくなる. dockerを再起動することで復活するが数分かかるため非常に手間である. もう一つの問題としてサードパーティ製品が未対応であることが多いことが挙げられる. β版なので当然といえば当然だがやはり面倒. 例えばIntellijプラグインが部分的に利用できない. 具体的にはwindowsのパス文字列に含まれる:が使えず, ボリュームの接続ができない(一応docker-compose経由にすることで回避できるが, デバッグ接続を別途する必要があったりそもそもコマンドからでいいのではという). 正式リリースされて対応するのが待ち遠しい.

FYI

ちなみにMac版は少し設定を弄ることでIntellijプラグインが使えるようだ. 以下のサイト参照.

blog.dekstroza.io

まとめ

タスクトレイに常駐するクジラがかわいい

SSH-CA認証でサーバ証明書内のホスト名に大文字が含まれると嵌まる

known_hosts@cert-authorityで登録したホスト名からホスト認証を行う際に全て小文字でチェックしているらしく, サーバ証明書内のホスト名に大文字が含まれるとコケる. /bin/hostname等を使う場合は注意が必要. 調整が必要なのはサーバ証明書内のホスト名だけで, known_hosts等は気にしなくていいようだ.

環境

ito@ito-VirtualBox:~$ ssh -V
OpenSSH_6.6.1p1 Ubuntu-2ubuntu2.6, OpenSSL 1.0.1f 6 Jan 2014

実行してみる

NG

ito@ito-VirtualBox:~$ sudo ssh-keygen -s ca/ca.key -I ca-test-server -h -n ito-VirtualBox /etc/ssh/ssh_host_rsa_key.pub 
Signed host key /etc/ssh/ssh_host_rsa_key-cert.pub: id "ca-test-server" serial 0 for ito-VirtualBox valid forever
ito@ito-VirtualBox:~$ ssh-keygen -L -f /etc/ssh/ssh_host_rsa_key-cert.pub 
/etc/ssh/ssh_host_rsa_key-cert.pub:
        Type: ssh-rsa-cert-v01@openssh.com host certificate
        Public key: RSA-CERT 8f:3e:82:c9:1f:5e:90:bd:46:09:0d:1d:7c:36:f5:73
        Signing CA: RSA 2f:4b:d1:af:a9:f7:94:67:9f:b2:a1:88:d2:b0:85:55
        Key ID: "ca-test-server"
        Serial: 0
        Valid: forever
        Principals: 
                ito-VirtualBox
        Critical Options: (none)
        Extensions: (none)
ito@ito-VirtualBox:~$ ssh -i client/client.key client@ito-VirtualBox
Certificate invalid: name is not a listed principal
The authenticity of host 'ito-virtualbox (127.0.1.1)' can't be established.
RSA key fingerprint is 8f:3e:82:c9:1f:5e:90:bd:46:09:0d:1d:7c:36:f5:73.
Are you sure you want to continue connecting (yes/no)? no
Host key verification failed.

OK

ito@ito-VirtualBox:~$ sudo ssh-keygen -s ca/ca.key -I ca-test-server -h -n ito-virtualbox /etc/ssh/ssh_host_rsa_key.pub 
Signed host key /etc/ssh/ssh_host_rsa_key-cert.pub: id "ca-test-server" serial 0 for ito-virtualbox valid forever
ito@ito-VirtualBox:~$ ssh-keygen -L -f /etc/ssh/ssh_host_rsa_key-cert.pub 
/etc/ssh/ssh_host_rsa_key-cert.pub:
        Type: ssh-rsa-cert-v01@openssh.com host certificate
        Public key: RSA-CERT 8f:3e:82:c9:1f:5e:90:bd:46:09:0d:1d:7c:36:f5:73
        Signing CA: RSA 2f:4b:d1:af:a9:f7:94:67:9f:b2:a1:88:d2:b0:85:55
        Key ID: "ca-test-server"
        Serial: 0
        Valid: forever
        Principals: 
                ito-virtualbox
        Critical Options: (none)
        Extensions: (none)
ito@ito-VirtualBox:~$ ssh -i client/client.key client@ito-VirtualBox
Welcome to Ubuntu 14.04 LTS (GNU/Linux 3.13.0-24-generic x86_64)

 * Documentation:  https://help.ubuntu.com/

Last login: Tue May 10 15:25:35 2016 from localhost
client@ito-VirtualBox:~$

公開鍵認証の初回接続で出てくるような「ホストを信頼してknown_hostsに追加しますか?」が出ずに, また, 新たにknown_hostsに追加されるようなことなく接続できればホスト認証成功.