skip to Main Content

I try to deploy a MySQL service with a database named ‘main’ with a table named ‘configs’. Below are my Kubernetes resources, which includes an SQL init script within a ConfigMap resource. After deploying, I use a forward port to access the MySQL pod, and communicate with the pod via the Python console using the PyMySQL library. The code I use for such communication is indicated below, where I try to insert an item into the ‘main.configs’ table. The problem is that, I get an error from PyMySQL saying that the table ‘main.configs’ doesn’t exist (error 1146), although the ‘main’ database does. Note that when I use PyMySQL to create a table ‘configs’, it works perfectly. Something seems to prevent the the creation of ‘main.configs’ table in my SQL init script in the ConfigMap (but the ‘main’ database is created without any issue).

Kubernetes resources:

apiVersion: v1
kind: Secret
metadata:
  name: mysql-secret
type: Opaque
stringData:
  mysql-root-password: abcd1234567
  mysql-user: batman
  mysql-database: main
  mysql-password: abcd1234567
---
apiVersion: v1
kind: ConfigMap
metadata:
  name: mysql-initdb-config
data:  # store initial SQL commands
  init.sql: |
    CREATE USER 'batman'@'%' IDENTIFIED BY 'abcd1234567';
    GRANT ALL PRIVILEGES ON *.* TO 'batman'@'%';
    FLUSH PRIVILEGES;
    
    CREATE DATABASE IF NOT EXISTS main;
    USE main;
    CREATE TABLE configs(
        task_id VARCHAR(124) NOT NULL,
        PRIMARY KEY (task_id)
    ) ENGINE=InnoDB;
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: mysql-pv-claim
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 100Mi
---
apiVersion: v1
kind: Service
metadata:
  name: mysql
spec:
  ports:
  - port: 3306
  selector:
    app: mysql
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: mysql
spec:
  selector:
    matchLabels:
      app: mysql
  strategy:
    type: Recreate
  template:
    metadata:
      labels:
        app: mysql
    spec:
      containers:
      - image: mysql:5.6
        name: mysql
        env:
          - name: MYSQL_ROOT_PASSWORD
            valueFrom:
              secretKeyRef:
                name: mysql-secrets
                key: mysql-root-password
          - name: MYSQL_USER
            valueFrom:
              secretKeyRef:
                name: mysql-secrets
                key: mysql-user
          - name: MYSQL_DATABASE
            valueFrom:
              secretKeyRef:
                name: mysql-secrets
                key: mysql-database
          - name: MYSQL_PASSWORD
            valueFrom:
              secretKeyRef:
                name: mysql-secrets
                key: mysql-password
        ports:
          - containerPort: 3306
            name: mysql

        volumeMounts:
          - name: mysql-persistent-storage
            mountPath: /var/lib/mysql
            subPath: "mysql"
          - name: mysql-initdb
            mountPath: /docker-entrypoint-initdb.d  # used to configure our database

      volumes:
        - name: mysql-persistent-storage
          persistentVolumeClaim:
            claimName: mysql-pv-claim
        - name: mysql-initdb
          configMap:
            name: mysql-initdb-config

PyMySQL code:

import pymysql

host = 'localhost'
port = 8080  # The port you forwarded with kubectl
user = 'batman'
password = 'abcd1234567'
database = 'main'

# Establish a connection
connection = pymysql.connect(
    host=host,
    port=port,
    user=user,
    password=password,
    database=database
)
cursor = connection.cursor()

query = """
        INSERT INTO
          configs (task_id)
        VALUES
          ('{}')
        """.format(*['id001'])
cursor.execute(query)
connection.commit()

2

Answers


  1. Chosen as BEST ANSWER

    I just solve my own issue by changing the init SQL query that was defined in the ConfigMap. Since the user 'batman' is already defined in the Secret resource (see below), there is no need to create it in the SQL query. Nevertheless, we can create a new one e.g. 'robin' via CREATE USER, and this can be written before or after creating a database/table. However, granting privileges via GRANT ALL ON to 'batman' and 'robin' must be stated at the end of the script (this was causing my issue with error 1146).

    Also, there is no need to define the database 'main' via this Secret resource (i.e. mysql-database: main, as originally written in my previous code) if it is created in the init SQL query (i.e. CREATE DATABASE IF NOT EXISTS main;).

    ConfigMap resource (updated):

    apiVersion: v1
    kind: ConfigMap
    metadata:
      name: mysql-initdb-config
    data:  # store initial SQL commands
      init.sql: |
        CREATE USER 'robin'@'%' IDENTIFIED BY 'abcd1234567';
        CREATE DATABASE IF NOT EXISTS main;
        USE main;
        
        CREATE TABLE configs(
            task_id VARCHAR(124) NOT NULL,
            PRIMARY KEY (task_id)
        ) ENGINE=InnoDB;
        
        GRANT ALL ON main.* TO 'batman'@'%';
        GRANT ALL ON main.* TO 'robin'@'%';
    

    Secret resource (updated):

    apiVersion: v1
    kind: Secret
    metadata:
      name: mysql-secret
    type: Opaque
    stringData:
      mysql-root-password: abcd1234567
      mysql-user: batman
      mysql-password: abcd1234567
    

  2. There is a minor issue with the Secret definition, where the secret name should match the one used in the Deployment environment variables. The actual issue seems to be in the Python code, specifically in the way you’re establishing the connection and forwarding the port.

    1 – The ‘secretKeyRef‘ in the Deployment should match the secret name defined in the Secret. In your ‘ConfigMap‘, you’ve defined the secret as ‘mysql-secret‘. Update your Deployment script to this:

    env:
      - name: MYSQL_ROOT_PASSWORD
        valueFrom:
          secretKeyRef:
            name: mysql-secret
            key: mysql-root-password
      - name: MYSQL_USER
        valueFrom:
          secretKeyRef:
            name: mysql-secret
            key: mysql-user
      - name: MYSQL_DATABASE
        valueFrom:
          secretKeyRef:
            name: mysql-secret
            key: mysql-database
      - name: MYSQL_PASSWORD
        valueFrom:
          secretKeyRef:
            name: mysql-secret
            key: mysql-password
    

    2 – In your Python code, you’re using port ‘8080‘ for the MySQL connection, but in your Kubernetes resources, the MySQL service is exposed on port ‘3306‘. Update the port variable in your Python code to match the correct port:

    port = 3306  # The port you forwarded with kubectl
    

    3 – Ensure that you have properly port-forwarded the MySQL service from your local machine to the Kubernetes cluster using this command:

    kubectl port-forward service/mysql 3306:3306
    

    Make sure you are running this command while your Python code is trying to connect to MySQL.

    4 – After making these changes, test the connection to MySQL and table creation again. If everything is configured correctly, your Python code should be able to connect to the MySQL database and execute the SQL statements from your ‘init‘ script.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search