CLOVER🍀

That was when it all began.

OKD/Minishift上に、Node.jsとMySQL(Image)を使ったアプリケーションを作る

OKD(旧名OpenShift Origin)上に、データベースを使用したアプリケーションを作ってみようかなと。
※名称自体はOKDになりましたが、今は検索の都合上、エントリのどこかに"OpenShift"という単語は入れておこうかなぁと…

OKD: Renaming of OpenShift Origin with 3.10 Release – Red Hat OpenShift Blog

まずは、Templateではなく、Dockerイメージを使ってデータベースを立ててみる方向でやってみます。Templateは、まだ今度。

MySQL

MySQL / Images

環境

今回の環境は、こちら。

## Minishift
$ minishift version
minishift v1.23.0+91235ee


## OKD
$ oc version
oc v3.10.0+dd10d17
kubernetes v1.10.0+b81c8f8
features: Basic-Auth GSSAPI Kerberos SPNEGO

Server https://xxx.xxx.xx.xxx:8443
openshift v3.10.0+ddf284b-16
kubernetes v1.10.0+b81c8f8

OKD自体のバージョンも、3.10.0です。

Minishift 1.23.0から、利用するOKDが3.10.0になったようです。

Make openshift 3.10 as the default version

用意するアプリケーション

単純に、Node.jsからMySQLに接続するアプリケーションを用意します。

データベースへの接続情報や、アカウントなどは環境変数から取得する感じで。

ライブラリのインストール。

$ npm i --save express promise-mysql
  "dependencies": {
    "express": "^4.16.3",
    "promise-mysql": "^3.3.1"
  },

作成したソースコードは、こちら。
src/server.js

const express = require('express');
const mysql = require('promise-mysql');

const os = require('os');

const app = express();

app.get('/select-now', async (req, res) => {
    const connection = await mysql.createConnection({
        host: process.env.SIMPLE_MYSQL_SERVICE_HOST,
        port: process.env.SIMPLE_MYSQL_SERVICE_PORT,
        user: process.env.SIMPLE_MYSQL_USER,
        password: process.env.SIMPLE_MYSQL_PASSWORD,
        database: process.env.SIMPLE_MYSQL_DATABASE
    });

    const rows = await connection.query('select now() as message');

    res.send(`${rows[0]['message']} from ${os.hostname()}`);
});

app.listen(8080);

OKD上では、MySQLを「simple-mysql」という名前で動かすことにするので、それを前提とした環境変数名(ホストとポートはServiceより自動で決まる)にしておきます。

あとは、ホスト名も返すようにしておきます。

「npm start」で起動するように、package.jsonに設定。

  "scripts": {
    "start": "node src/server.js",
    "test": "echo \"Error: no test specified\" && exit 1"
  },

これで作成したアプリケーションを、Gitリポジトリに登録しておきます。

OKDに、MySQLイメージを突っ込む

では、MySQLのイメージをOKDに突っ込んでみましょう。

以下のドキュメントを参考に

MySQL / Images

CentOS 7、MySQL 5.7のイメージを突っ込んでみます。名前は「simple-mysql」、データベース名は「practice」、アカウントは「kazuhira / password」とします。

$ oc new-app -e MYSQL_USER=kazuhira -e MYSQL_PASSWORD=password -e MYSQL_DATABASE=practice centos/mysql-57-centos7 --name=simple-mysql

Docker Hub上だと、こちらのイメージです。

centos/mysql-57-centos7

今回は環境変数を3つ指定しましたが、それ以外のものを指定する場合は、OKDのドキュメント、もしくはDocker Hubに記載してあるものを参照してください。

しばらく待つと、MySQLが起動します。

$ oc get all
NAME                       READY     STATUS    RESTARTS   AGE
pod/simple-mysql-1-nt85t   1/1       Running   0          59s

NAME                                   DESIRED   CURRENT   READY     AGE
replicationcontroller/simple-mysql-1   1         1         1         1m

NAME                   TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)    AGE
service/simple-mysql   ClusterIP   172.30.189.116   <none>        3306/TCP   1m

NAME                                              REVISION   DESIRED   CURRENT   TRIGGERED BY
deploymentconfig.apps.openshift.io/simple-mysql   1          1         1         config,image(simple-mysql:latest)

NAME                                          DOCKER REPO                              TAGS      UPDATED
imagestream.image.openshift.io/simple-mysql   172.30.1.1:5000/myproject/simple-mysql   latest    About a minute ago

確認。

$ oc rsh dc/simple-mysql
sh-4.2$ mysql -ukazuhira -p practice
Enter password: 
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 2
Server version: 5.7.21 MySQL Community Server (GPL)

Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql>

OKそうです。

アプリケーションを突っ込む

それでは、先程作成したNode.jsのアプリケーションを突っ込んでみましょう。この時、環境変数

$ oc new-app -e SIMPLE_MYSQL_USER=kazuhira -e SIMPLE_MYSQL_PASSWORD=password -e SIMPLE_MYSQL_DATABASE=practice [GitリポジトリのURL]

Routesをexpose。

$ oc expose svc/node-mysql

アクセス。

$ curl node-mysql-myproject.192.168.42.201.nip.io/select-now
Wed Aug 29 2018 06:50:13 GMT+0000 (UTC) from node-mysql-1-82qwg

スケールアウト。

$ oc scale dc/node-mysql --replicas=3

しばらくすると、アクセスするごとに返ってくるホスト名が変わるようになります。

なんとか、動かせました、と。

YAMLで書く

では、ここまでの内容をYAMLで書いてみましょう。

MySQLとアプリケーションを、それぞれまとめたYAMLファイル(計2個)で作るのですが、DeploymentConfigとかServiceを「kind: List」でまとめるのではなく、
YAMLで「---」で区切ることにしました。

いろいろ迷った結果、後に単品でも使いやすいように…?

MySQL
mysql-resources.yml

---
## ImageStream
apiVersion: v1
kind: ImageStream
metadata:
  labels:
    app: simple-mysql
  name: simple-mysql
spec:
  tags:
  - from:
      kind: DockerImage
      name: centos/mysql-57-centos7
    name: latest

---
## DeploymentConfig
apiVersion: v1
kind: DeploymentConfig
metadata:
  labels:
    app: simple-mysql
  name: simple-mysql
spec:
  replicas: 1
  selector:
    app: simple-mysql
    deploymentconfig: simple-mysql
  template:
    metadata:
      labels:
        app: simple-mysql
        deploymentconfig: simple-mysql
    spec:
      containers:
      - name: simple-mysql
        image:
          centos/mysql-57-centos7
        imagePullPolicy: Always
        ports:
        - containerPort: 3306
          protocol: TCP
        env:
        - name: MYSQL_DATABASE
          value: practice
        - name: MYSQL_PASSWORD
          value: password
        - name: MYSQL_USER
          value: kazuhira
      restartPolicy: Always
  triggers:
  - type: ConfigChange
  - type: ImageChange
    imageChangeParams:
      automatic: true
      containerNames:
      - simple-mysql
      from:
        kind: ImageStreamTag
        name: simple-mysql:latest

---
## Service
apiVersion: v1
kind: Service
metadata:
  labels:
    app: simple-mysql
  name: simple-mysql
spec:
  ports:
  - name: 3306-tcp
    port: 3306
    protocol: TCP
    targetPort: 3306
  selector:
    deploymentconfig: simple-mysql

作成。

$ oc create -f mysql-resources.yml
imagestream.image.openshift.io "simple-mysql" created
deploymentconfig.apps.openshift.io "simple-mysql" created
service "simple-mysql" created

アプリケーション。
application-resources.yml

---
## ImageStream
apiVersion: v1
kind: ImageStream
metadata:
  labels:
    app: node-mysql
  name: node-mysql

---
## BuildConfig
apiVersion: v1
kind: BuildConfig
metadata:
  labels:
    app: node-mysql
  name: node-mysql
spec:
  triggers:
    - type: ConfigChange
    - imageChange: {}
      type: ImageChange
  source:
    git:
      uri: [GitリポジトリのURL]
      ref: master
    type: Git
  strategy:
    type: Source
    sourceStrategy:
      from:
        kind: ImageStreamTag
        name: nodejs:8
        namespace: openshift
  output:
    to:
      kind: ImageStreamTag
      name: node-mysql:latest

---
## DeploymentConfig
apiVersion: v1
kind: DeploymentConfig
metadata:
  labels:
    app: node-mysql
  name: node-mysql
spec:
  replicas: 3
  selector:
    app: node-mysql
    deploymentconfig: node-mysql
  template:
    metadata:
      labels:
        app: node-mysql
        deploymentconfig: node-mysql
    spec:
      containers:
      - name: node-mysql
        image: node-mysql:latest
        imagePullPolicy: Always
        ports:
        - containerPort: 8080
          protocol: TCP
        env:
          - name: SIMPLE_MYSQL_USER
            value: kazuhira
          - name: SIMPLE_MYSQL_PASSWORD
            value: password
          - name: SIMPLE_MYSQL_DATABASE
            value: practice
      restartPolicy: Always
  triggers:
  - type: ConfigChange
  - type: ImageChange
    imageChangeParams:
      automatic: true
      containerNames:
      - node-mysql
      from:
        kind: ImageStreamTag
        name: node-mysql:latest

---
## Service
apiVersion: v1
kind: Service
metadata:
  labels:
    app: node-mysql
  name: node-mysql
spec:
  ports:
  - name: 8080-tcp
    port: 8080
    protocol: TCP
    targetPort: 8080
  selector:
    app: node-mysql
    deploymentconfig: node-mysql

---
## Route
apiVersion: v1
kind: Route
metadata:
  labels:
    app: node-mysql
  name: node-mysql
spec:
  port:
    targetPort: 8080-tcp
  to:
    kind: Service
    name: node-mysql

作成。

$ oc create -f application-resources.yml
imagestream.image.openshift.io "node-mysql" created
buildconfig.build.openshift.io "node-mysql" created
deploymentconfig.apps.openshift.io "node-mysql" created
service "node-mysql" created
route.route.openshift.io "node-mysql" created

こんな感じで。