1

I'm trying to deploy MySQL on my Kubernetes cluster. I have Traefik v2 ingress controller and I'm using IngressRouteTCP CRD.

Here is my Deployment:

apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: db
  name: db
spec:
  replicas: 1
  selector:
    matchLabels:
      app: db
  template:
    metadata:
      labels:
        app: db
    spec:
      containers:
        - image: mariadb:10.5
          name: db
          env:
            MYSQL_ROOT_PASSWORD: foobar
          ports:
            - containerPort: 3306
              name: mysql

Here is my Service:

apiVersion: v1
kind: Service
metadata:
  name: db
spec:
  selector:
    app: db
  ports:
    - name: mysql
      port: 3306

Here is my IngressRouteTCP:

apiVersion: traefik.containo.us/v1alpha1
kind: IngressRouteTCP
metadata:
  name: db
spec:
  entryPoints:
    - mysql
  routes:
    - match: HostSNI(`*`)
      kind: Rule
      services:
        - name: db
          port: 3306

I have created an entrypoint mysql for port 3306.

When I deploy those objects, I test the connection from within the cluster:

$ kubectl exec -it ubuntu -- mysql -h db -p -e 'SHOW DATABASES'
Enter password: 
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| performance_schema |
+--------------------+
$

So everything is working correctly, but when it comes to exposing the server via Traefik ingress, it doesn't.

From outside the cluster:

$ nmap -Pn -p 3306 db.myserver
Starting Nmap 7.80 ( https://nmap.org ) at 2020-07-25 09:13 GMT
Nmap scan report for db.myserver ([CENSORED])
Host is up (0.063s latency).

PORT     STATE SERVICE
3306/tcp open  mysql

Nmap done: 1 IP address (1 host up) scanned in 0.24 seconds

The port is open, but the listener is not picking up a connection...

$ mysql -h db.myserver --connect-timeout=10 -p -e 'SHOW DATABASES'
Enter password: 
ERROR 2013 (HY000): Lost connection to MySQL server at 'handshake: reading inital communication packet', system error: 110

Any ideas?

Edit 2020-07-25 17:46

I replaced mariadb:10.5 with containous/whoamitcp:latest and set targetPort: 8080 on the Service object, to check if I got it working with a simple TCP echo server. It works perfectly.

$ nc db.myserver 3306
FOO
Received: FOO

Edit 2020-07-25 18:30

Replaced containous/whoamitcp:latest again with mariadb:10.5 and I saw something strange. If I do a netcat externally, it hangs but if I type in something, it prints out appropriate MySQL/MariaDB jargon. See below:

$ nc db.myserver 3306
SOME INPUT
m
5.5.5-10.5.4-MariaDB-1:10.5.4+maria~focal`9:Y0#_5-+v24Ptvvk9xpmysql_native_password!#08S01Got packets out of order

Edit 2020-07-25 19:06

I set up Minikube on my machine, set up Traefik and deployed it there. It works perfectly. So this seems to be an issue with Scaleway, the cloud provider I'm running my Kubernetes cluster on (Kapsule).

$ nc 172.17.0.3 31269
m
5.5.5-10.5.4-MariaDB-1:10.5.4+maria~focal   e}d\!/e1-`tGFgVY<^DxQmysql_native_password
Gaui
  • 169
  • 7

1 Answers1

1

After thorough investigation it seems the problem boils down to MySQL/MariaDB not supporting Host SNI. So it's not possible to utilise TCP routing in Traefik or other ingress controllers.

Gaui
  • 169
  • 7
  • 1
    Your example didn't use TLS, so there will be no such thing as "Host SNI" in a normal TCP handshake; if you enable TLS on your MySQL, it increases the chances of success – mdaniel Jul 26 '20 at 17:42
  • @mdaniel https://bugs.mysql.com/bug.php?id=84849 – Gaui Jul 26 '20 at 18:23