前回、OKD(OpenShift Origin)上にNode.jsとMySQLのImageを使ったアプリケーションをデプロイしてみました。
OKD/Minishift上に、Node.jsとMySQL(Image)を使ったアプリケーションを作る - CLOVER🍀
今度は、MySQLをTemplateを使ってデプロイして、Node.jsで作成したアプリケーションと組み合わせて動かしてみます。
環境
今回の環境は、こちら。
## 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です。
MySQLのTemplateを使う
このエントリでは、以下のエントリで作成したNode.jsのソースコードを少し修正して、OKDのMySQL Templateを使ってアプリケーションを作ってみます。
OKD/Minishift上に、Node.jsとMySQL(Image)を使ったアプリケーションを作る - CLOVER🍀
MySQLのTemplateについては、こちら。
Creating a Database Service from a Template
今回は、MySQLのEphemeralなTemplateを使ってみます。デフォルトではOKDに入っていないので、こちらから取得。
https://github.com/openshift/origin/blob/v3.10.0/examples/db-templates/mysql-ephemeral-template.json
取り込み先は、自namespaceとしました。
$ oc create -f https://raw.githubusercontent.com/openshift/origin/v3.10.0/examples/db-templates/mysql-ephemeral-template.json template.template.openshift.io "mysql-ephemeral" created
Templateでどのようなパラメータが使えるかは、「oc process」で確認できます。
$ oc process --parameters mysql-ephemeral NAME DESCRIPTION GENERATOR VALUE MEMORY_LIMIT Maximum amount of memory the container can use. 512Mi NAMESPACE The OpenShift Namespace where the ImageStream resides. openshift DATABASE_SERVICE_NAME The name of the OpenShift Service exposed for the database. mysql MYSQL_USER Username for MySQL user that will be used for accessing the database. expression user[A-Z0-9]{3} MYSQL_PASSWORD Password for the MySQL connection user. expression [a-zA-Z0-9]{16} MYSQL_ROOT_PASSWORD Password for the MySQL root user. expression [a-zA-Z0-9]{16} MYSQL_DATABASE Name of the MySQL database accessed. sampledb MYSQL_VERSION Version of MySQL image to be used (5.5, 5.6, 5.7, or latest). 5.7
もとのJSONファイル(もしくはYAMLファイルなど)から、直接確認してもよいでしょう。
$ oc process --parameters -f https://raw.githubusercontent.com/openshift/origin/v3.10.0/examples/db-templates/mysql-ephemeral-template.json NAME DESCRIPTION GENERATOR VALUE MEMORY_LIMIT Maximum amount of memory the container can use. 512Mi NAMESPACE The OpenShift Namespace where the ImageStream resides. openshift DATABASE_SERVICE_NAME The name of the OpenShift Service exposed for the database. mysql MYSQL_USER Username for MySQL user that will be used for accessing the database. expression user[A-Z0-9]{3} MYSQL_PASSWORD Password for the MySQL connection user. expression [a-zA-Z0-9]{16} MYSQL_ROOT_PASSWORD Password for the MySQL root user. expression [a-zA-Z0-9]{16} MYSQL_DATABASE Name of the MySQL database accessed. sampledb MYSQL_VERSION Version of MySQL image to be used (5.5, 5.6, 5.7, or latest). 5.7
「oc describe」でもOKです。
$ oc describe template mysql-ephemeral Name: mysql-ephemeral Namespace: myproject Created: 2 minutes ago Labels: <none> Description: MySQL database service, without persistent storage. For more information about using this template, including OpenShift considerations, see https://github.com/sclorg/mysql-container/blob/master/5.7/root/usr/share/container-scripts/mysql/README.md. WARNING: Any data stored will be lost upon pod destruction. Only use this template for testing Annotations: iconClass=icon-mysql-database openshift.io/display-name=MySQL (Ephemeral) openshift.io/documentation-url=https://docs.openshift.org/latest/using_images/db_images/mysql.html openshift.io/long-description=This template provides a standalone MySQL server with a database created. The database is not stored on persistent storage, so any restart of the service will result in all data being lost. The database name, username, and password are chosen via parameters when provisioning this service. openshift.io/provider-display-name=Red Hat, Inc. openshift.io/support-url=https://access.redhat.com tags=database,mysql Parameters: Name: MEMORY_LIMIT Display Name: Memory Limit Description: Maximum amount of memory the container can use. Required: true Value: 512Mi Name: NAMESPACE Display Name: Namespace Description: The OpenShift Namespace where the ImageStream resides. Required: false Value: openshift Name: DATABASE_SERVICE_NAME Display Name: Database Service Name Description: The name of the OpenShift Service exposed for the database. Required: true Value: mysql Name: MYSQL_USER Display Name: MySQL Connection Username Description: Username for MySQL user that will be used for accessing the database. Required: true Generated: expression From: user[A-Z0-9]{3} Name: MYSQL_PASSWORD Display Name: MySQL Connection Password Description: Password for the MySQL connection user. Required: true Generated: expression From: [a-zA-Z0-9]{16} Name: MYSQL_ROOT_PASSWORD Display Name: MySQL root user Password Description: Password for the MySQL root user. Required: true Generated: expression From: [a-zA-Z0-9]{16} Name: MYSQL_DATABASE Display Name: MySQL Database Name Description: Name of the MySQL database accessed. Required: true Value: sampledb Name: MYSQL_VERSION Display Name: Version of MySQL Image Description: Version of MySQL image to be used (5.5, 5.6, 5.7, or latest). Required: true Value: 5.7 Object Labels: template=mysql-ephemeral-template Message: The following service(s) have been created in your project: ${DATABASE_SERVICE_NAME}. Username: ${MYSQL_USER} Password: ${MYSQL_PASSWORD} Database Name: ${MYSQL_DATABASE} Connection URL: mysql://${DATABASE_SERVICE_NAME}:3306/ For more information about using this template, including OpenShift considerations, see https://github.com/sclorg/mysql-container/blob/master/5.7/root/usr/share/container-scripts/mysql/README.md. Objects: Secret ${DATABASE_SERVICE_NAME} Service ${DATABASE_SERVICE_NAME} DeploymentConfig ${DATABASE_SERVICE_NAME}
Template?
と、ここまでTemplateというものが、なんなのかに触れないまま進んできました。
TemplateについてのOKDのドキュメントは、こちら。
Templateというのは、以下の説明にあるようにOKDによって作成されるオブジェクト(のリスト)を、パラメータ化して定義したものです。
A template describes a set of objects that can be parameterized and processed to produce a list of objects for creation by OKD. A template can be processed to create anything you have permission to create within a project, for example services, build configurations, and deployment configurations. A template may also define a set of labels to apply to every object defined in the template.
https://docs.okd.io/3.10/dev_guide/templates.html
ServiceやBuildConfig、DeploymentConfigなどを作成したり、各オブジェクトに付与するラベルを事前に定義したりできます。これをテンプレートにして、
「oc new-app」でパラメータを設定して実行すると、定義してあるオブジェクト群が一式できあがります、と。
例えば、先のMySQL Ephemeralについて言うと
https://github.com/openshift/origin/blob/v3.10.0/examples/db-templates/mysql-ephemeral-template.json
Secret、Service、DeploymentConfigが定義されており、先程「oc process」などで見たパラメータを使ってテンプレートとして構成されています。
MySQLをデプロイする
それでは、まずはMySQLをデプロイしてみましょう。以下のコマンドで、MySQLをデプロイします。名前は、「simple-mysql」としました。
$ oc new-app mysql-ephemeral --name=simple-mysql -p MYSQL_USER=kazuhira -p MYSQL_PASSWORD=password -p MYSQL_DATABASE=practice -p MYSQL_VERSION=5.7 -p DATABASE_SERVICE_NAME=simple-mysql
Secretは、こんな感じになっています。
$ oc get secret/simple-mysql -o yaml apiVersion: v1 data: database-name: cHJhY3RpY2U= database-password: cGFzc3dvcmQ= database-root-password: dmZkR3BUdE5yQWZqUzhCTw== database-user: a2F6dWhpcmE= kind: Secret metadata: annotations: openshift.io/generated-by: OpenShiftNewApp template.openshift.io/expose-database_name: '{.data[''database-name'']}' template.openshift.io/expose-password: '{.data[''database-password'']}' template.openshift.io/expose-root_password: '{.data[''database-root-password'']}' template.openshift.io/expose-username: '{.data[''database-user'']}' creationTimestamp: 2018-09-01T10:23:34Z labels: app: simple-mysql template: mysql-ephemeral-template name: simple-mysql namespace: myproject resourceVersion: "25403" selfLink: /api/v1/namespaces/myproject/secrets/simple-mysql uid: 14cbcec3-add1-11e8-9b07-5254000c2420 type: Opaque
Node.jsのアプリケーションをデプロイする
アプリケーションは、こちらのエントリとほぼ同じものを使います。
OKD/Minishift上に、Node.jsとMySQL(Image)を使ったアプリケーションを作る - CLOVER🍀
アプリケーションのデプロイ。名前は、「node-mysql」としています。
$ oc new-app [GitリポジトリのURL]
環境変数は、Secretから取り込むことにします。
$ oc set env --from=secret/simple-mysql dc/node-mysql
このSecretとTemplateのMySQLから作成したServiceによる環境変数を使うソースコードは、こちら。
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.DATABASE_USER, password: process.env.DATABASE_PASSWORD, database: process.env.DATABASE_NAME }); const rows = await connection.query('select now() as message'); res.send(`${rows[0]['message']} from ${os.hostname()}`); }); app.listen(8080);
あとは、Routeを作成。
$ oc expose svc/node-mysql
スケールアウト。
$ oc scale dc/node-mysql --replicas=3
確認。アクセスごとに、ホスト名が切り替わっていきます。
$ curl node-mysql-myproject.192.168.42.215.nip.io/select-now Sat Sep 01 2018 10:48:37 GMT+0000 (UTC) from node-mysql-2-nhzzm
アプリケーションに対して、Secretからの環境変数はこんな感じに入っています。
$ oc get dc/node-mysql -o jsonpath='{.spec.template.spec.containers[0].env}'
出力結果(ちょっと整形)。
[ map [name:DATABASE_ROOT_PASSWORD valueFrom:map[secretKeyRef:map[name:simple-mysql key:database-root-password]] ] map [name:DATABASE_USER valueFrom:map[secretKeyRef:map[name:simple-mysql key:database-user]] ] map [name:DATABASE_NAME valueFrom:map[secretKeyRef:map[name:simple-mysql key:database-name]] ] map [name:DATABASE_PASSWORD valueFrom:map[secretKeyRef:map[name:simple-mysql key:database-password]] ] ]
Secretの内容が、環境変数にちょっと名前を変えて入ったみたいですね。
これで、やりたいことはできました、と。
Web Consoleで一括でSecretを取り込んだ場合
こういう定義になるようです。
$ oc get dc/node-mysql -o jsonpath='{.spec.template.spec.containers[0].envFrom}' [map[secretRef:map[name:simple-mysql]]]
YAMLだと、こんな感じ。
spec: ... template: metadata: ... spec: containers: - envFrom: - secretRef: name: simple-mysql
ただ、この方法で取り込むと、環境変数名としては微妙な名前のまま取り込まれてしまうものがあるので、その点には注意です。
例えば、今回のMySQL Ephemeralから取り込んだSecretは、こんな感じに環境変数に展開されます。
$ oc rsh dc/node-mysql sh-4.2$ env | grep database database-root-password=xxxxx database-name=xxxxx database-user=xxxxx database-password=xxxxx
さっきの例みたいな、「DATABASE_USER」とかとはちょっと違いますね。
YAMLで書こう
最後に、ここまでの定義をYAMLで書いてみようと思います。
が、Templateの部分って、これをYAML化するんだったら、それぞれ個別に定義するに他ならない気が…。
というわけで、Node.jsのアプリケーションの方だけ。
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: DATABASE_USER valueFrom: secretKeyRef: key: database-user name: simple-mysql - name: DATABASE_PASSWORD valueFrom: secretKeyRef: key: database-password name: simple-mysql - name: DATABASE_NAME valueFrom: secretKeyRef: key: database-name name: simple-mysql 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
ほぼ前回のエントリと同じ内容なのですが、環境変数の定義だけが違いますね。
spec: containers: - name: node-mysql image: node-mysql:latest imagePullPolicy: Always ports: - containerPort: 8080 protocol: TCP env: - name: DATABASE_USER valueFrom: secretKeyRef: key: database-user name: simple-mysql - name: DATABASE_PASSWORD valueFrom: secretKeyRef: key: database-password name: simple-mysql - name: DATABASE_NAME valueFrom: secretKeyRef: key: database-name name: simple-mysql
こんな感じで。