Edited at

minikubeを使ったnodejs開発環境構築

More than 1 year has passed since last update.

「DeNA IPプラットフォーム事業部 Advent Calendar 2017」15日目の記事です


はじめに

GoogleKubernetesEngineなどKubernetes環境を採用している場合、ローカルの開発環境においてもKubernetes+minikubeを採用することがあるかと思います

今回はそのminikube上でのNode.js開発環境の構築手順とポイントをかんたんに解説します

※Mac前提で進めます、その他のOSをご利用の方ごめんなさい!🙇


必要なもの


  • minikube

  • kubectl

  • docker

  • nodejs(Mac上)

基本的なインストール手順はこちらを参考にしてください

https://kubernetes.io/docs/tutorials/stateless-application/hello-minikube/

Node.js(npm)を利用するのでインストールしてください

https://nodejs.org/ja/download/

※バイナリ以外の方法でも問題ありません


環境構築


hyperkitドライバーでminikubeを起動する

hyperkitはvirtualboxなどと比べ動作が高速でした

※参考nodejs起動時間 virtualbox:3sec hyperkit:1sec

# hyperkitドライバーをインストール

$ curl -LO https://storage.googleapis.com/minikube/releases/latest/docker-machine-driver-hyperkit && chmod +x docker-machine-driver-hyperkit && sudo mv docker-machine-driver-hyperkit /usr/local/bin/ && sudo chown root:wheel /usr/local/bin/docker-machine-driver-hyperkit && sudo chmod u+s /usr/local/bin/docker-machine-driver-hyperkit
# minikubeを起動
$ minikube start --vm-driver=hyperkit --cpus 4 --memory 8192
# dockerのホストを設定する
$ eval $(minikube docker-env)

cpu,memoryは必要に応じて変えてください


Dockerfile


FROM node:8.6.0
ENV APP_ROOT /opt/node
WORKDIR $APP_ROOT
RUN npm install pm2 -g
EXPOSE 3000 3002
CMD ["npm", "run", "start"]

pm2をインストールしていますが目的は後ほど


アプリケーションコード

npmスクリプトを使用するため以下のようなファイルにします


package.json

{

"name": "k8s-node-dev",
"version": "0.0.0",
"private": true,
"scripts": {
"start": "pm2-docker start ./pm2.json"
},
"dependencies": {
},
"devDependencies": {
"gulp": "^3.9.1"
}
}

起動設定はpm2.jsonでおこないます


pm2.json

{

"apps": [
{
"name": "k8s-node-dev",
"script": "./app.js",
"node_args": "--inspect=0.0.0.0:3002"
}
]
}

node_argsにデバッグポートの設定をしています


ソースコードNFSマウントする

mac上のソースコードをminikube上にマウントし、mac上で編集→kubernetes上で実行させます

minikube mountではなくnfsを利用したほうが高速なため、nfsを使います

※参考 minikube mountの場合、nodeの起動に10秒以上要しました

$ cd project_dir

$ echo "$(pwd) -network 192.168.0.0 -mask 255.255.0.0 -alldirs -maproot=root:wheel" | sudo tee -a /etc/exports
$ sudo nfsd restart
$ minikube ssh -- sudo busybox mount -v -t nfs 192.168.99.1:$(pwd) /home/docker/shared_volumes/ -o rw,async,noatime,rsize=32768,wsize=32768,proto=tcp


podを作成する


k8s-node.yaml

apiVersion: v1

kind: Service
metadata:
name: k8s-node-dev
spec:
selector:
app: k8s-node-dev
role: app
env: local
ports:
- protocol: TCP
name: app
port: 8081
targetPort: 3000
nodePort: 30082
- name: debug
port: 3002
targetPort: 3002
nodePort: 30089
type: NodePort
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: k8s-node-dev
spec:
replicas: 1
template:
metadata:
labels:
app: k8s-node-dev
role: app
env: local
spec:
containers:
- name: k8s-node-dev
image: "node-dev:v1"
tty: true
stdin: true
ports:
- containerPort: 3000
- containerPort: 3002
volumeMounts:
- mountPath: "/opt/node"
name: "node-src-volume"
volumes:
- name: "node-src-volume"
hostPath:
path: "/home/docker/shared_volumes/project_dir"

Dockerイメージをビルドしpodを起動します

$ docker build -f ./Dockerfile -t node-dev:v1 .

$ kubectl create -f ./k8s-node.yaml

動作の確認を行います

$ minikube service k8s-node-dev

ここまでで準備は完了です


ファイルの変更を即時に反映する

nodejsは再起動しないと変更を反映させることができません

毎回手動で実行するのは辛いのでファイルの変更を監視し自動で再起動するようにしたいところ

通常、nodemonやnode-devなどで起動すればいいだけなのですが、今回の環境ではnfsマウント押している関係上ファイルの更新を検知することができません

(ポーリングで解決もできますがちょっと…


mac上で監視を行う

pod上でだめなら大元のmac側で監視しましょう

今回はgulpを使います


mac上でgulpをインストール

$ npm install -g gulp

$ npm install gulp


監視と再起動を行う


gulpfile.js

let gulp = require('gulp');

let exec = require('child_process').exec;

gulp.task('watch', function(){
gulp.watch('./**/*.*', ['reload']);
});
gulp.task('reload', function(){
console.log('reload');
exec('kubectl exec -it $(kubectl get pod | grep node | awk -F" " \'{print $1}\') -- pm2 reload all', {shell: '/bin/bash'}, function(error, stdout, stderr) {
console.log(stdout);
});
});


$ gulp watch


何をしているのか



  1. gulp.watchでファイルを監視し、execでbashに処理を渡す


  2. $(kubectl get pod | grep node | awk -F" " \'{print $1}\')でpodのIDを取得


  3. kubectl exec -it $ID -- $scriptで$scriptを実行


  4. pm2 reload allで再起動

pm2を採用したのはこのように外部から再起動を実行可能なためです

これで、スムーズに修正を反映する環境が整いました


デバッグがしたい

すでにpm2.jsonにデバッグポート3002を指定し、k8s-node.yamlに3002にアクセスするnodePort:30089を開けているためかんたんにデバッグが可能です


Chromeでデバッグ



  1. minikube service tama-bff-service --format "{{.IP}}"でIPを確認する


  2. chrome://inspect/#devicesを開く

  3. Open dedecated ...をクリック

  4. Connectionタブを開き、${1で取得したIP}:30089を登録する

  5. 2の画面のRemote Targetにinspect対象が現れるので開く

これで、デバッグ可能になりました


まとめ

minikubeを使ったnodejs環境構築ついてまとめました

NFSやgulpを組み合わせることで、ローカルでNode.jsを起動した場合と大差ないスムーズな開発が実現できました

また、Dockerfileやyamlに設定がまとまっているので他のメンバーへの導入も非常にかんたんにできます

現在エブリスタの開発において手探りで運用している環境なのでご質問・ご意見等ございましたらよろしくお願いします!


宣伝

エブリスタでは一緒に働くメンバーを熱烈に募集しています


  • アーキテクチャ設計や言語選定から関わるエンジニアリングをしたい方

  • 最新技術に触れたい方

  • 小説やUGCに関わる仕事に興味がある方

  • 出版業界・コンテンツ業界に変革を起こしたい方

などなど、「ちょっと興味ありそう」「もっと色々聞いてみたい」という方も

是非こちらから応募頂くか、 @daponta まで気軽にご連絡ください!