最近読んだ本
SOFT SKILLS ソフトウェア開発者の人生マニュアル
下記のようなテーマに関する書籍
- キャリアの構築
- 効率の良い学習方法
- 生産性の向上
- 資産管理
- 健康管理
- 精神状態の管理
キャリアの構築方法については結構なコミュ力、行動力を要求しており難易度が高いと感じた。コミュ障エンジニアが全部実践するのは難がある。
効率の良い学習方法、生産性を上げる方法に関する章ではかなり具体的な方法論が述べられていて、これら章だけでもこの本を読んだ価値があった。
あと文中でたくさんの書籍が紹介されているので次に読む本の指針になる。暇な時間があって本をたくさん読みたい人が最初に手を出すのに良さそう。
前処理大全
期待外れというのは言い過ぎだけど、正直言って自分にはあまり合わなかった。
エンジニアであれば知っていて当然のような知識が多いため、エンジニアである自分が読んでも得られるものは少なかった。(個人の経験に依存した話)
どちらかというと統計や分析を専門にしている人がデータ処理に手を出す際に読むと良い感じなんじゃないかと思う。
Docker/Kubernetes入門
チーム内でKubetnetesの勉強をしてみるという機運があったので読んだ。(実際に運用するかは未定)
How toが内容の中心で入門者にはとても良い本だと思った。
docker/Kubernetesという技術の成り立ちに関して最低限説明さてているのも良い。
Kubernetesはモデルが複雑で用語がとても多いのだけど、それらを日本語で説明してくれているのがありがたかった。
入門者向けなのでこの本を読んだだけでKubernetesクラスタを本番運用できるかというとそれは厳しい。(というかKubernetesの知識が豊富でも厳しいっぽい)
Kubernetesのチュートリアルをやってみる
Kubernetesのチュートリアルをやった時のメモです。
チュートリアルページをみると色々な選択肢がありますが、今回は「Kubernetesの基本を学ぶ」というチュートリアルをやりました。
Kubernetesの基本を学ぶ - Kubernetes
使用OSはMacです
HyperVisorをインストールする
VirtualBoxなど、Kubernetesを動作させるためのVMツールをインストールします。
VirtualBoxはhomebrew-caskでインストールできます。(VirtualBoxがカーネル拡張機能を含むためシステム環境設定から許可が必要になります)
$ brew cask install virtualbix
もしDockerの入ったLinux環境を使用しているのであれば、下記のオプションを指定VMではなくホスト上で直接Minikubeを動作させることができるそうです。(Minikubeがローカル環境用であることを考えると使用機会はあまりなさそうですが)
--vm-driver=none
Minikubeをインストールする
Minikubeはローカルでの開発に最適化された軽量なKubernetes環境を提供するツールです。
ローカルマシン上にVMを作成し(ここでHyperVisorが必要)、1つのNodeのみを含むKubernetesクラスタをデプロイできます。
macの場合、homebrew-caskでインストールします。
$ brew cask install minikube
起動する
下記のコマンドで(VMが未作成の場合は)VMが作成され、VM上でminikubeが起動します。
この段階ではNode上ではまだ何も起動していません。
$ minikube start
Nodoにpodを配置します。
チュートリアルの例ではgoogle private resistry(gcr)からイメージを取得しています
$ kubectl run hello-minikube --image=k8s.gcr.io/echoserver:1.10 --port=8080 deployment.apps "hello-minikube" created
先ほどと同様のコマンドでpodが起動していることが確認できます
$ kubectl get pod NAME READY STATUS RESTARTS AGE hello-minikube-56cdb79778-zzfl2 1/1 Running 0 1m
クラスタの状態確認
$ kubectl cluster-info Kubernetes master is running at https://192.168.99.100:8443 KubeDNS is running at https://192.168.99.100:8443/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy
この段階ではpod内のコンテナと通信することはできません。
exposeコマンドで外側と通信できるようにします。
$ kubectl expose deployment hello-minikube --type=NodePort service "hello-minikube" exposed
これでコンテナと通信できるようになりました。
$ curl $(minikube service hello-minikube --url) Hostname: hello-minikube-56cdb79778-zzfl2 Pod Information: -no pod information available- Server values: server_version=nginx: 1.13.3 - lua: 10008 Request Information: client_address=172.17.0.1 method=GET real path=/ query= request_version=1.1 request_scheme=http request_uri=http://192.168.99.100:8080/ Request Headers: accept=*/* host=192.168.99.100:32252 user-agent=curl/7.54.0 Request Body: -no body in request-
コンテナを終了するにはdeleteコマンドを使用します
$ kubectl delete services hello-minikube service "hello-minikube" deleted $ kubectl delete deployment hello-minikube deployment.extensions "hello-minikube" deleted
所感
minikubeを使ったチュートリアルを試しましたが、ローカルに最適化されているだけあってとっつきやすかったです。
その反面チュートリアルだけでは実際の運用との間にかなりの乖離があるとも感じました。
下記のようなことを引き続き試していきたいと思います。
- 自前で用意したDockerイメージを利用するにはどうすれば良いか
- Pod上で複数のコンテナを動かす方法
- Node上で複数のPodを動かす方法
elasticsearchがスケールする仕組み(参照編)
elastcisearchのスケール性能について調査したことをまとめました。
シャーディングとレプリケーション
elasticsearchはスケールアウトの仕組みにシャーディングとレプリケーションを採用しています。
シャーディングはデータを分割して保存することで参照を分散する仕組みです。
レプリケーションはデータ集合の複製を作成することで、同じデータにアクセスするリクエストを並列に実行したり可用性を高めたりできる仕組みです。
elasticsearchはインデックスをシャードに分割しつつ、それぞれのシャードをレプリケーションしています。
query phaseとfetch phase
elasticsearchの検索のプロセスはquery phaseとfetch phaseに別れています
query phase
elasticsearchクラスタは複数のノードで構成されますが、インデックスや検索などのリクエストはどのノードも受けることができます。
リクエストを受け取ったノードはcoodinating node
と呼ばれます。
検索リクエストを受けると、coodinating node
が各シャードのプライマリ or レプリカに検索リクエストを行います。
各シャードは size + from
件のドキュメントを検索ソートし、リクエストを受け取ったノードに返します。(この段階ではドキュメントのIDとソート対象になるvalueをのみを返します。)
、coodinating node
は各シャードから返ってきた結果をマージ、ソートします。
fetch phase
query phaseで入手した情報を利用して、リクエストを行う必要があるシャードのみに対してmulti getリクエストを行います。
各シャードはドキュメントの内容を読み込んでcoodinating node
返します。
coodinating node
が各ノードから得たドキュメント情報をマージ し、最終的な結果をクライアントに返します。
シャード数とレプリカ数について
ノード数をいくら増やしてもシャード数やレプリカ数を増やさなければ処理は分散されません。
elasticsearchの性能を引き出すにはこれらの値を適切に設定する必要があります。
プライマリ/レプリカシャードは自動的に各ノードにいい感じに分散するように配置されます。
インデックスを複数のシャードに分割しているほど、1リクエストの処理が分散され、並列に行われます。
また、シャードのレプリカ数が多ければ、複数のリクエストの並列度が上がります。
ただしレプリカ数は多ければ多いほど良いわけではなく、レプリカ数 > ノード数になるとひとつのノードにシャードが重複するため意味はなくなってきます。
ボトルネックになりそうな箇所
単純に検索処理の負荷が大きい場合(複雑なaggregationなど)以外の要因を書きます。
ヒットする件数が多すぎる
query phaseで各シャードから取得した結果をソートする処理はcoodinating node
1台で行われるためスケールアウトできません。
そのため検索結果の件数が多いことがボトルネックになってしまう可能性があります。
deep paging
query phaseにおいて各シャードでsize + from
件の検索・ソートを行うため、fromが大きくなると処理の負担が大きくなり、ボトルネックになる可能性が出てきます。
このような検索はdeep pagingと呼ばれます。
対策
インデックスを分割する
インデックス内のドキュメントが増えるほど検索時の負荷も際限なく増えることになるため、インデックスを日付毎にするなど時系列で分割するといった方法を取ることが多いです。
index templateでマッピングをあらかじめ登録しておくと、時系列で分割されたインデックスの生成がやりやすくなります。
scroll searchやsearch afterを使う
elaticsearchはscroll searchやsearch afterなど、deep paging対策の仕組みを提供しています。
search afterはほぼfromと同様のことができるので、使えないか検討するべきだと思います。
参考にしたドキュメント
古いですが基本的な処理の流れは今も変わってないと思います。
Query Phase | Elasticsearch: The Definitive Guide [2.x] | Elastic
Fetch Phase | Elasticsearch: The Definitive Guide [2.x] | Elastic
macのコマンドラインからアプリケーションを開く
macでターミナルからアプリケーションを開く方法を最近知りました。
$ open -a 'Google Chrome' #開くurlを指定することもできる $ open -a 'Google Chrome' https://google.com
普段ターミナル上で作業することが多いので、結構重宝してます。
このままではコマンドが長いしアプリケーション名を覚えるのも大変ですが、エイリアスを設定すると使いやすくなります
#使ってるシェルに応じたファイルを編集して下記を追加 $ vim .bashrc alias chrome='open -a "Google Chrome"' $ source ~/.bashrc # ブラウザが開く! $ chrome
ブラウザの例を書いてますが、ファイルをエディタで開いたりするときなんかも便利です。
一応ターミナルからアプリケーションを終了するコマンドも探してみたのですが、linuxでも使えるkill
とkillall
くらいしか見つかりませんでした。
pythonの環境を整えてjupyter notebookを動かすまで
自分は機械学習に入門したばかりの初心者なんですが、pythonの環境を整えるのにちょっと苦労したので書こうと思います。
pyenvのインストール
pyenvはpythonのバージョン切り替えが簡単に行えるようになるツールです。
$ brew update | brew install pyenv
入れたら例によってbash_profileを編集します。
一応簡単に説明すると、シェルがコマンドを探す領域にpyenvのディレクトリを追加するということをやっています。
パスとか環境変数がわかんないという人はこちらの記事が参考になると思います。
これでpyenvを使用できるようになりましたが、まだpython自体のインストールは行なっていません。 pythonのバージョンを指定してインストールを実行します。
$ pyenv install version 3.6.0
インストール可能なバージョンの一覧は下記で確認できます。
$ pyenv install --list
インストールができたら、pythonのバージョンを切り替えます。
$ pyenv global 3.6.0
現在のディレクトリだけ使用するpythonのバージョンを変えたい場合はlocalを指定します。
$ pyenv local 3.6.0
これでインストールしたバージョンのpythonが使えるようになります。
$ python --version
jupyter notebookをインストールする
pipを利用してインストールできます。 pipがpyenvでpythonをインストールするとついてきます。
$ pip install jupyter
jupyter notebookを動かす
コマンドを実行すると、ブラウザが立ち上がりjupyter notebookのページが表示されます。 コマンドを実行したディレクトリがルートディレクトリになります。
$ jupyter notebook
まとめ
pyenvをローカルにインストールする方法について紹介しました。 rubyやnodeなんかにも似たようなバージョン管理のツールがあるので、それらを使ったことがある人ならすんなりインストールできると思います。
virtualenvといったのpythonのライブラリのバージョンを環境ごとに管理するツールもあるのですが、こちらはpythonでプロダクト開発するとき向けでただ機械学習をやるだけなら必要では良さそう。
最近だったらDockerという選択肢もあるので、そちらについてもいずれ試してみたいです。