Testing MySQL Router Deployments on Kubernetes with InnoDB ClusterSet

Testing <a target="_blank" href="https://www.google.com/search?ved=1t:260882&q=MySQL+Router&bbid=7230617179850026054&bpid=2704764887795526747" data-preview>MySQL Router</a> Deployments on <a target="_blank" href="https://www.google.com/search?ved=1t:260882&q=Kubernetes&bbid=7230617179850026054&bpid=2704764887795526747" data-preview>Kubernetes</a> with <a target="_blank" href="https://www.google.com/search?ved=1t:260882&q=InnoDB+ClusterSet&bbid=7230617179850026054&bpid=2704764887795526747" data-preview>InnoDB ClusterSet</a>

Testing MySQL Router Deployments on Kubernetes

Once your MySQL Router is deployed and configured to handle read/write routing between InnoDB ClusterSet primary and secondary clusters, the next critical step is verifying that the routing behaves as expected.

In this post, we’ll walk through a simple Kubernetes-native testing strategy using a minimal Python application to validate Router behavior across ports 6446 (RW) and 6447 (RO).

The Goal

We want to:

  • Write to MySQL via Router port 6446 every 2 seconds.
  • Read via Router port 6447 every 2 seconds.
  • Log RW operation metadata to a dedicated table (rw_log).
  • Print RO query responses in the pod logs.

This lets us monitor which router handled the request and from which pod, helping validate traffic direction and router/cluster availability in a live environment.

RW Logging Schema

CREATE TABLE rw_log (
    id INT AUTO_INCREMENT PRIMARY KEY,
    created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
    connected_host VARCHAR(255),
    pod_host VARCHAR(255),
    router_role VARCHAR(10)
);

This will track connection source (connected_host), calling pod (pod_host), and whether it's a read or write request.

Kubernetes Secrets

apiVersion: v1
kind: Secret
metadata:
  name: mysql-router-secret
  namespace: mysql-router
type: Opaque
stringData:
  MYSQL_USER: conntest
  MYSQL_PASSWORD: examplepass

ConfigMap – The Python App

apiVersion: v1
kind: ConfigMap
metadata:
  name: mysql-logger-script
  namespace: mysql-router
data:
  connect_loop.py: |
    import os
    import time
    import mysql.connector
    import socket
    from datetime import datetime

    def connect_db(role):
        host = os.environ['MYSQL_RW_HOST'] if role == 'RW' else os.environ['MYSQL_RO_HOST']
        port = int(os.environ['MYSQL_RW_PORT']) if role == 'RW' else int(os.environ['MYSQL_RO_PORT'])
        conn = mysql.connector.connect(
            host=host,
            port=port,
            user=os.environ['MYSQL_USER'],
            password=os.environ['MYSQL_PASSWORD'],
            database='test'
        )
        return conn

    def write_log():
        conn = connect_db('RW')
        cursor = conn.cursor()
        cursor.execute(
            "INSERT INTO rw_log (connected_host, pod_host, router_role) VALUES (%s, %s, %s)",
            (conn.server_host, socket.gethostname(), 'RW')
        )
        conn.commit()
        cursor.close()
        conn.close()

    def read_log():
        conn = connect_db('RO')
        cursor = conn.cursor()
        cursor.execute("SELECT COUNT(*) FROM rw_log")
        result = cursor.fetchone()
        print(f"[RO] Row Count: {result[0]}")
        cursor.close()
        conn.close()

    while True:
        try:
            write_log()
        except Exception as e:
            print(f"[RW ERROR] {e}")
        try:
            read_log()
        except Exception as e:
            print(f"[RO ERROR] {e}")
        time.sleep(2)

Kubernetes Deployment

apiVersion: apps/v1
kind: Deployment
metadata:
  name: mysql-router-test
  namespace: mysql-router
spec:
  replicas: 1
  selector:
    matchLabels:
      app: mysql-router-test
  template:
    metadata:
      labels:
        app: mysql-router-test
    spec:
      containers:
      - name: logger
        image: python:3.9
        command: ["python"]
        args: ["/app/connect_loop.py"]
        env:
        - name: MYSQL_RW_HOST
          value: "mysql-router.mysql-router.svc.cluster.local"
        - name: MYSQL_RW_PORT
          value: "6446"
        - name: MYSQL_RO_HOST
          value: "mysql-router.mysql-router.svc.cluster.local"
        - name: MYSQL_RO_PORT
          value: "6447"
        - name: MYSQL_USER
          valueFrom:
            secretKeyRef:
              name: mysql-router-secret
              key: MYSQL_USER
        - name: MYSQL_PASSWORD
          valueFrom:
            secretKeyRef:
              name: mysql-router-secret
              key: MYSQL_PASSWORD
        volumeMounts:
        - name: app-code
          mountPath: /app
      volumes:
      - name: app-code
        configMap:
          name: mysql-logger-script

Observing Results

kubectl logs deploy/mysql-router-test -n mysql-router

You should see alternating logs like:

[RW] Inserted into rw_log via mysql-router1
[RO] Row Count: 23
[RW] Inserted into rw_log via mysql-router2
[RO] Row Count: 24

Meanwhile, query the rw_log table from MySQL to confirm inserts are correctly registered:

SELECT * FROM rw_log ORDER BY created_at DESC LIMIT 5;

Wrap-Up

This test setup provides a quick and effective way to validate your MySQL Router deployment under InnoDB ClusterSet architecture. It ensures:

  • Routing through RW/RO ports behaves as expected.
  • Failovers and redirection can be tracked.
  • Kubernetes-native validation is streamlined.

Comments

  1. This blog is a goldmine of insights! Your deep understanding of MySQL development truly shines through each section. I appreciate the clarity with which you explain complex concepts—it’s evident how much effort and expertise went into crafting this content. For anyone seeking reliable MySQL development services, this blog is a fantastic starting point. Keep up the great work—your contributions are incredibly valuable to developers and businesses alike. Looking forward to more of your brilliant posts!

    ReplyDelete

Post a Comment

Popular posts from this blog

Oracle Multitenant - Create new service for PDB using DBMS_SERVICE

ORA-16433: The database or pluggable database must be opened in read/write

ORA-27103 [ ] and ORA-6544 [pevm_peruws_callback-1] [27103] in Alert log