14
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have 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 まで気軽にご連絡ください!

14
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
14
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?