LoginSignup
2
2

More than 5 years have passed since last update.

初めてのkubernetes(Minikube) Pod連携とデータの永続化編

Last updated at Posted at 2018-10-01

概要

前回の「初めてのkubernetes(Minikube) Windows環境でチュートリアル+α」に続き、アプリケーションサーバ用PodとDBサーバ用Podの連携をやってみたので理解したことをメモとして残したいと思います

※minikubeコマンドを実行する際は管理者権限で実行してください

実行環境

  • Windows 10 pro
  • Minikube v0.28.0
  • Docker Version 18.06.1-ce-win73 (19507)

さっそく手順

1. サンプルアプリケーションの取得

今回はNode.jsのアプリケーションからRedisのデータを取得して表示する簡単なサンプルアプリケーションを使っていきますので、ソースをローカルにクローンしてください

ローカルで事前に動作確認できるようにdocker-composeも用意していますので、適宜に活用してください

server.js
const http = require('http');
const redis = require('redis');
let redis_host = 'redis';
let redis_port = 6379;

// k8s環境の場合は、redisの接続先とポートは環境変数から取得
if (process.env.MODE && process.env.MODE == 'k8s') {
    redis_host = process.env.SAMPLE_REDIS_SERVICE_HOST;
    redis_port = process.env.SAMPLE_REDIS_SERVICE_PORT;
}
const client = redis.createClient({
    host: redis_host,
    port: redis_port
});

// 表示用の変数をredisに保存する
client.set('sample', 'hello world');
client.set('sample2', 'hello Qiita');

// 表示用の変数
let redis_val = '';
client.get('sample', function (err, data) {
    redis_val += '<li>' + data + '</li>';
});
client.get('sample2', function (err, data) {
    redis_val += '<li>' + data + '</li>';
});

const handleRequest = function (request, response) {
    console.log('Received request for URL: ' + request.url);
    response.writeHead(200);
    response.end('<h1>redis value:</h1><ul>' + redis_val + '</ul>');
};

// echo env
const envs = process.env;
console.log(envs);

const www = http.createServer(handleRequest);
www.listen(3000);

2. Dockerクライアントの接続先の変更

前回同様Dockerクライアントの向き先を予めMinikubeに変更してください

powershell
> minikube docker-env --shell powershell | Invoke-Expression

> docker images

# kubernetes関連のイメージが表示されればOK

3. イメージのビルド

サンプルアプリケーションのDockerイメージをMinikubeにビルドします

powershell
> docker build -t sample-app:v1 --no-cache ./app

4. Deployment

Minikubeにデプロイします

powershell
> kubectl apply -f ./deployment_k8s_sample_app.yml
deployment_k8s_sample_app.yml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: sample-redis
  labels:
    app: sample-redis
    type: db
spec:
  replicas: 1
  selector:
    matchLabels:
      app: sample-redis
      type: db
  template:
    metadata:
      labels:
        app: sample-redis
        type: db
    spec:
      containers:
      - name: sample-redis
        image: redis:4
        ports:
        - containerPort: 6379
        # redis-volumeボリュームとredisのデータ領域の/data
        volumeMounts:
        - mountPath: /data
          name: redis-volume
      # データ永続化するためのボリューム
      volumes:
      - name: redis-volume
        # ボリュームの種別はhostPath
        hostPath:
          path: /home/docker/redis-data
          # ディレクトリがなければ作る
          type: DirectoryOrCreate
---
apiVersion: v1
kind: Service
metadata:
  name: sample-redis
  labels:
    app: sample-redis
    type: db
spec:
  type: LoadBalancer
  selector:
    app: sample-redis
    type: db
  ports:
  - port: 6379
    targetPort: 6379
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: sample-app
  labels:
    app: sample-app
    type: app
spec:
  replicas: 1
  selector:
    matchLabels:
      app: sample-app
      type: app
  template:
    metadata:
      labels:
        app: sample-app
        type: app
    spec:
      containers:
      - name: sample-app
        image: sample-app:v1
        ports:
        - containerPort: 3000
        # k8s環境用で稼働しているかどうかの環境変数
        env:
        - name: MODE
          value: k8s
---
apiVersion: v1
kind: Service
metadata:
  name: sample-app
  labels:
    app: sample-app
    type: app
spec:
  type: LoadBalancer
  selector:
    app: sample-app
    type: app
  ports:
  - port: 3000

5. 確認

Podの確認

powershell
> kubectl get po

NAME                            READY     STATUS    RESTARTS   AGE
sample-app-694d9bf49f-66b7b     1/1       Running   0          37m
sample-redis-55c5b46859-n7pnt   1/1       Running   0          42m

Serviceの確認

powershell
> kubectl get svc

NAME           TYPE           CLUSTER-IP       EXTERNAL-IP   PORT(S)          AGE
kubernetes     ClusterIP      10.96.0.1        <none>        443/TCP          20d
sample-app     LoadBalancer   10.101.237.112   <pending>     3000:32482/TCP   43m
sample-redis   LoadBalancer   10.111.4.116     <pending>     6379:32400/TCP   43m

アプリケーションの確認

powershell
> minikube service sample-app

ブラウザで以下のように表示されればOKです

redis value:

hello world
hello Qiita

説明

Dockerと同じようにDB Pod(redis)接続情報を記す環境変数を取得することができる
その代わりにServiceとして公開しないといけないようです
Serviceを利用することにより、トラフィックの負荷分散、サービスディスカバリー、クラスタ内のDNSを利用できるようになります
なので、アプリケーションのredisの接続先を環境変数から取得しています

server.js

server.js

// k8s環境の場合は、redisの接続先とポートは環境変数から取得
// MODEはDeploymentで環境変数として設定しています
if (process.env.MODE && process.env.MODE == 'k8s') {
    redis_host = process.env.SAMPLE_REDIS_SERVICE_HOST;
    redis_port = process.env.SAMPLE_REDIS_SERVICE_PORT;
}

環境変数を確認してみましょう

powershell
kubectl logs sample-app-694d9bf49f-66b7b

{ KUBERNETES_SERVICE_PORT: '443',
  KUBERNETES_PORT: 'tcp://10.96.0.1:443',
  SAMPLE_APP_PORT_3000_TCP_ADDR: '10.97.74.141',
  NODE_VERSION: '6.9.2',
  HOSTNAME: 'sample-app-565db6587d-xtblr',
  MODE: 'k8s',
  SAMPLE_APP_PORT_3000_TCP_PORT: '3000',
  SAMPLE_APP_PORT_3000_TCP_PROTO: 'tcp',
  HOME: '/root',
  SAMPLE_REDIS_SERVICE_HOST: '10.103.205.192',
  SAMPLE_APP_PORT_3000_TCP: 'tcp://10.97.74.141:3000',
  SAMPLE_APP_SERVICE_HOST: '10.97.74.141',
  SAMPLE_REDIS_PORT: 'tcp://10.103.205.192:6379',
  SAMPLE_REDIS_SERVICE_PORT: '6379',
  SAMPLE_REDIS_PORT_6379_TCP_ADDR: '10.103.205.192',
  KUBERNETES_PORT_443_TCP_ADDR: '10.96.0.1',
  PATH: '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin',
  SAMPLE_REDIS_PORT_6379_TCP_PORT: '6379',
  KUBERNETES_PORT_443_TCP_PORT: '443',
  SAMPLE_REDIS_PORT_6379_TCP_PROTO: 'tcp',
  SAMPLE_APP_PORT: 'tcp://10.97.74.141:3000',
  SAMPLE_APP_SERVICE_PORT: '3000',
  NPM_CONFIG_LOGLEVEL: 'info',
  KUBERNETES_PORT_443_TCP_PROTO: 'tcp',
  SAMPLE_REDIS_PORT_6379_TCP: 'tcp://10.103.205.192:6379',
  KUBERNETES_PORT_443_TCP: 'tcp://10.96.0.1:443',
  KUBERNETES_SERVICE_PORT_HTTPS: '443',
  KUBERNETES_SERVICE_HOST: '10.96.0.1',
  PWD: '/' }

データの永続化

データの永続化するために、ボリュームをhostPathとして定義しています
hostPathはNode上の任意のパスをボリュームとして作ることができます
MinikubeのようにシングルNodeの場合は問題ないが、複数Node構成の場合は、データの整合性を考慮しなければならないため、他のボリューム種別を利用すること

以下ではデータの永続化の動作検証手順になります

1. Deployment、サービスの削除

データが永続化しているかどうかを確認するために、一度削除します

powershell
> kubectl delete -f ./deployment_k8s_sample_app.yml

2. server.jsを修正

redisに値を保存するコードをコメントアウトします

server.js

// 表示用の変数をredisに保存する
// client.set('sample', 'hello world');
// client.set('sample2', 'hello Qiita');

3. イメージをリビルド

タグはv2でビルド

powershell
> docker build -t sample-app:v2 --no-cache ./app

4. deployment_k8s_sample_app.ymlを編集

デプロイするイメージをv2に変更

deployment_k8s_sample_app.yml
~中略~
      containers:
      - name: sample-app
        image: sample-app:v2
~中略~

5. 再Deployment

powershell
> kubectl apply -f ./deployment_k8s_sample_app.yml

deployment.apps "sample-redis" created
service "sample-redis" created
deployment.apps "sample-app" created
service "sample-app" created

5. 動作確認

前述と同様に値を確認できる

powershell

> minikube service sample-app

2
2
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
2
2