0

I have a MySQL pod up and running. I opened a terminal for this pod and created a database and a user.

create database demodb;
create user demo identified by 'Passw0rd';
grant all on demodb.* to 'demo';

I have this Deployment to launch a NodeJs client for the MySQL pod. This is on my local minikube installation.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: demos
spec:
  selector:
    matchLabels:
      app: demos
  template:
    metadata:
      labels:
        app: demos
    spec:
      containers:
      - name: demo-db
        image: 172.30.1.1:5000/demo/db-demos:0.1.0
        resources:
          limits:
            memory: "128Mi"
            cpu: "200m"
        ports:
        - containerPort: 4000
          name: probe-port
---
apiVersion: v1
kind: Service
metadata:
  name: demos
spec:
  selector:
    app: demos
  ports:
  - name: probe-port
    port: 4001
    targetPort: probe-port

The Dockerfile for the image passes the environment variables for the NodeJs client to use.

FROM node:alpine
ADD . .
RUN npm i

WORKDIR /app

ENV PROBE_PORT 4001

ENV MYSQL_HOST "mysql.demo.svc"
ENV MYSQL_PORT "3306"
ENV MYSQL_USER "demo"
ENV MYSQL_PASSWORD "Passw0rd"
ENV MYSQL_DATABASE "demodb"

CMD ["node", "index.js"]

And, the NodeJs client connects as follows.

const mysql = require('mysql')

const connection = mysql.createConnection({
    host: process.env.MYSQL_HOST,
    port: process.env.MYSQL_PORT,
    user: process.env.MYSQL_USER,
    password: process.env.MYSQL_PASSWORD,
    database: process.env.MYSQL_DATABASE
});

connection.connect((err) => {
    if (err) {
        console.log('Database connection failed. ' + err.message)
    } else {
        console.log('Database connected.')
    }
});

The database connection keeps failing with a message as Database connection failed. connect ENOENT tcp://172.30.88.64:3306. The TCP/IP address shown in this message is correct i.e. it matches with the service mysql.demo.svc of the running MySQL pod.

In the MySQL configuration files, I don't see bind-address. This should mean that, MySQL should accept connections from 'every where'. I am creating the user without the location qualifier i.e. the user is 'demo'@'%'. The connection is, obviously, not through sockets as I am passing the host and port values for connection.

What am I missing?

cogitoergosum
  • 2,309
  • 4
  • 38
  • 62
  • How did you deploy the database; are you sure the `mysql` Service is actually connected to its underlying Pod? – David Maze Jan 31 '20 at 01:34
  • MySQL was deployed with this YAML - https://pastebin.com/h6YtMgPC – cogitoergosum Jan 31 '20 at 01:47
  • BTW, on `minikube`, I used service as `mysql.demo.svc.cluster.local`. On `minishift`, I tried with `mysql.demo.svc`; same error in both cases. – cogitoergosum Jan 31 '20 at 01:49
  • Are you using the mysql deployment and nodejs client on the same namespace `demo`? Are you able to reach mysql 3306 port from your node-client port using telnet for example? You could make this test using a busybox image, see [this link](https://kubernetes.io/docs/tasks/administer-cluster/dns-debugging-resolution/), just to make sure your problem isn't dns resolution or network issues.... – Mr.KoopaKiller Jan 31 '20 at 09:56
  • Yes, they are in the same namespace `demo`. I followed [this example](https://kubernetes.io/docs/concepts/services-networking/connect-applications-service/#dns) and the `nslookup` works successfully. – cogitoergosum Jan 31 '20 at 10:02
  • The connection goes through if a connection string `mysql://user:pass@host:port/db` is passed to `createConnection` and password is set with `mysql_native_password` option. When does one use the connection string vs the standard JS object option? – cogitoergosum Jan 31 '20 at 12:30

1 Answers1

0

I got it working as follows.

const mysql = require('mysql')

const connection = mysql.createConnection({
    host: process.env.MYSQL_HOST,
//    port: process.env.MYSQL_PORT,
    user: process.env.MYSQL_USER,
    password: process.env.MYSQL_PASSWORD,
    database: process.env.MYSQL_DATABASE
});

connection.connect((err) => {
    if (err) {
        console.log('Database connection failed. ' + err.message)
    } else {
        console.log('Database connected.')
    }
});

That's right; I removed the port number from the option. :rolleyes: This example from RedHat is closest I have seen.

Also, I created the user with mysql_native_password as that is the only plugin mechanism that is supported by NodeJs client. See here.

cogitoergosum
  • 2,309
  • 4
  • 38
  • 62