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
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 viaGRANT 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):
Secret resource (updated):
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:
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:
3 – Ensure that you have properly port-forwarded the MySQL service from your local machine to the Kubernetes cluster using this command:
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.