How to connect to mysql inside a Kubernetes cluster?

48 views Asked by At

I have a java app that needs to connect to a MySQL instance running inside a Kubernetes cluster. The MySQL instance comes up just fine and I can log into the container from the shell. The configuration looks like:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: mysql
spec:
  selector:
    matchLabels:
      app: mysql
  strategy:
    type: Recreate
  template:
    metadata:
      labels:
        app: mysql
    spec:
      containers:
        - name: mysql
          image: mysql:latest
          env:
            # Use secret in real usage
            - name: MYSQL_ROOT_PASSWORD
              value: password
          ports:
            - containerPort: 3306
              name: mysql
          volumeMounts:
            - name: mysql-persistent-storage
              mountPath: /var/lib/mysql
      volumes:
        - name: mysql-persistent-storage
          persistentVolumeClaim:
            claimName: mysql-pv-claim
---

apiVersion: v1
kind: PersistentVolume
metadata:
  name: mysql-pv-volume
  labels:
    type: local
spec:
  storageClassName: manual
  capacity:
    storage: 1Gi
  accessModes:
    - ReadWriteOnce
  hostPath:
    path: "/mnt/data"
    
---

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: mysql-pv-claim
spec:
  storageClassName: manual
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 1Gi
      
---

  apiVersion: v1
  kind: Service
  metadata:
    name: mysql
  spec:
    type: NodePort
    selector:
      app: mysql
    ports:
      - protocol: TCP
        port: 3306
        nodePort: 30000
        targetPort: 3306
                

My java application is build using Docker and I can run it just fine on localhost; I'm wondering how I can pass in the db.url when running the application container?

The YML for the application is as follows:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: directory-deployment
spec:
  replicas: 1
  selector:
    matchLabels:
      app: directory
  template:
    metadata:
      labels:
        app: directory
    spec:
      containers:
          - name: directory-container
            image: directory:latest
            imagePullPolicy: Always
            ports:
              - containerPort: 8080
            env:
              - name: SPRING_DATASOURCE_URL
                value: jdbc:mysql://${DB_HOST}/temp?useSSL=false
                
---

apiVersion: v1
kind: Service
metadata:
  name: directory-service
spec:
  selector:
    app: directory
  ports:
      - protocol: TCP
        port: 8080
        targetPort: 8080
  type: LoadBalancer
                
---


apiVersion: apps/v1
kind: Deployment
metadata:
  name: directory-deployment
spec:
  selector:
    matchLabels:
      app: directory-mysql
  replicas: 1
  template:
    metadata:
      labels:
        app: directory-mysql
    spec:
      containers:
        - name: directory
          image: directory:latest
          ports:
            - containerPort: 8080
          env:   # Setting Enviornmental Variables
            - name: DB_HOST   # Setting Database host address from configMap
              valueFrom :
                configMapKeyRef :
                  name : db-config
                  key :  host

            - name: DB_NAME  # Setting Database name from configMap
              valueFrom :
                configMapKeyRef :
                  name : db-config
                  key :  dbName
            - name: DB_USERNAME  # Setting Database username from Secret
              valueFrom :
                secretKeyRef :
                  name : mysql-secrets
                  key :  username
            - name: DB_PASSWORD # Setting Database password from Secret
              valueFrom :
                secretKeyRef :
                  name : mysql-secrets
                  key :  password

---

apiVersion: v1 # Kubernetes API version
kind: Service # Kubernetes resource kind we are creating
metadata: # Metadata of the resource kind we are creating
  name: directory
spec:
  selector:
    app: mysql
  ports:
    - protocol: "TCP"
      port: 8080 # The port that the service is running on in the cluster
      targetPort: 8080 # The port exposed by the service
  type: NodePort # type of the service.

What I'm looking to do is to pass in the correct db.url to the application container to connect to the MySQL pod.

kubectl get svc

NAME         TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)          AGE
directory    NodePort    10.101.234.92   <none>        8080:30561/TCP   5m11s
kubernetes   ClusterIP   10.96.0.1       <none>        443/TCP          38m
mysql        NodePort    10.96.238.113   <none>        3306:30000/TCP   32m

kubectl get deployments

NAME                   READY   UP-TO-DATE   AVAILABLE   AGE
directory-deployment   0/1     1            0           5m18s
mysql                  1/1     1            1           34m

As I launch the service; the JDBC connector is trying to use jdbc:mysql://mysql/temp but as you can see, it won't connect

java -jar ./target/Test.jar
[main] INFO org.eclipse.jetty.util.log - Logging initialized @56ms
[main] INFO org.test.db.DatabaseConfig - DB url: jdbc:mysql://mysql:3306
[main] INFO org.test.db.DatabaseConfig - Loaded the db file correctly!!!
[main] INFO org.test.db.DatabaseConfig - DB url: jdbc:mysql://mysql:3306
[main] ERROR org.test.handlers.Directory - The database does now exist!!!!
Exception in thread "main" com.google.inject.ProvisionException: Unable to provision, see the following errors:

1) [Guice/ErrorInjectingConstructor]: RuntimeException: Cannot connect to DB; Communications link failure

0

There are 0 answers