"Error establishing a database connection" using Wordpress, MySQL, Nginx on Kubernetes

1/30/2019

I am deploying an app using Wordpress, php-fpm, nginx and mysql on Kubernetes. The steps I have taken are:

  1. deploy mysql using helm
  2. expose the pod as a clusterIP service and dump my tables onto the database
  3. deploy my wordpress/php app in the same pod with an nginx container
  4. expose clusterIP service and set up ingress / TLS

The database seems to be working, I can connect to it and see my tables using the following command: echo "mysql -pXXX" | kubectl exec -it <mysql-pod>. Step 4 (ssl cert and ingress) is also working and no problem there. Creating the two pods (my app and mysql), and adding the config files result in this message when I try to access my domain:

Error establishing a database connection

I deploy mysql pod using helm through this command:

helm install --name mysql --set \
mysqlRootPassword=xxx,mysqlUser=xxx,mysqlPassword=xxx, \
mysqlDatabase=xxx,persistence.size=50Gi \
stable/mysql

Once this is deployed, the pod runs and I can access my database successfully. This is when I dump my tables data from a local .sql file onto the created database, and when I run show tables they all exist on the persistent storage. This part seems to be working properly.

I am deploying my wordpress app and nginx containers in one pod, for mutual persistent volume use. The deployment yaml looks like this:

wordpress-deployment.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: wordpress
  labels:
    app: wordpress
spec:
  replicas: 1
  selector:
    matchLabels:
      app: wordpress
  template:
    metadata:
      labels:
        app: wordpress
    spec:
      containers:
      - image: nginx:alpine
        name: nginx
        env:
        - name: WP_HOST
          value: wordpress
        - name: DB_HOST
          value: mysql:3306
        - name: DB_NAME
          value: xxx
        - name: DB_PASSWORD
          valueFrom:
            secretKeyRef:
              name: mysql
              key: password
        ports:
        - containerPort: 443
        - containerPort: 80
        volumeMounts:
          - name: wordpress-persistent-storage
            mountPath: /var/www/html
          - name: wp-config
            mountPath: "/etc/nginx/conf.d"
      - image: my-wordpress-php-app
        name: wordpress
        env:
        - name: MY_DB_HOST
          value: mysql:3306
        - name: MY_DB_NAME
          value: xxx
        - name: MY_DB_PASSWORD
          valueFrom:
            secretKeyRef:
              name: mysql
              key: password
        - name: MY_WP_HOME
          value: "https://example.com"
        - name: MY_WP_SITEURL
          value: "https://example.com"
        - name: WP_DEBUG_LOG
          value: "true"
        - name: WP_DEBUG
          value: "true"
        ports:
        - containerPort: 9000
        volumeMounts:
        - name: wordpress-persistent-storage
          mountPath: /var/www/html
      volumes:
      - name: wordpress-persistent-storage
        persistentVolumeClaim:
          claimName: wordpress-volumeclaim
      - name: wp-config
        configMap:
          name: wp-config
          items:
          - key: wp.conf
            path: wp.conf
      imagePullSecrets:
      - name: regcred

I have confirmed that I can access my database through my wordpress pod by simply connecting to mysql:3306. I checked and confirmed that my app works through docker compose on a server, and the code seems fine, so we can assume the wordpress app's docker image is also doing what it should.

For reference, my config file is as follows: wp.conf

    listen 80;
    listen 443 ssl;
    server_name $SITE_URL;

    root /var/www/html;
    index index.php;

    access_log /var/log/nginx/access.log;
    error_log /var/log/nginx/error.log;

    gzip off;

    types {
        ...
    }

    location xxx {
        rewrite .* /index.php;
        ...
    }

    location ~ '\.php
#x27;
{ try_files $uri =404; fastcgi_split_path_info ^(.+\.php)(/.+)$; fastcgi_pass wordpress:9000; fastcgi_index index.php; include fastcgi_params; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; fastcgi_param PATH_INFO $fastcgi_path_info; ... } location / { autoindex off; ... } }

Some extra info in case it helps:

  • Both of my services (mysql and wordpress/nginx) are ClusterIP type. In my mysql service I have the following:
    - port: 3306
      targetPort: 3306

And in my wordpress service I have the following:

  - name: wordpress
    port: 9000
    targetPort: 9000
  - port: 80
    targetPort: 80
    protocol: TCP
    name: http
  - port: 443
    targetPort: 443
    protocol: TCP
    name: https

I have added the mysql password as a secret with the proper yaml file and base64 value. I have also tried using the command line instead for creating the secret, and both don't change anything in the results.

Here are some logs in case it can tell anything about the problem (I couldn't find much with that regards):

Mysql pod logs

MySQL init process in progress...
Warning: Unable to load '/usr/share/zoneinfo/Factory' as time zone. Skipping it.
Warning: Unable to load '/usr/share/zoneinfo/iso3166.tab' as time zone. Skipping it.
Warning: Unable to load '/usr/share/zoneinfo/leap-seconds.list' as time zone. Skipping it.
Warning: Unable to load '/usr/share/zoneinfo/posix/Factory' as time zone. Skipping it.
Warning: Unable to load '/usr/share/zoneinfo/right/Factory' as time zone. Skipping it.
Warning: Unable to load '/usr/share/zoneinfo/zone.tab' as time zone. Skipping it.
mysql: [Warning] Using a password on the command line interface can be insecure.
MySQL init process done. Ready for start up.

Nginx container logs

[11:15:03 +0000] "GET /robots.txt HTTP/1.1" 500 262 "-" "Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)"
10.20.0.128 - - [12:17:48 +0000] "GET / HTTP/1.1" 500 262 "-" "Python/3.6 aiohttp/3.4.4"
10.20.0.128 - - [16:04:42 +0000] "GET / HTTP/1.1" 500 262 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/x Safari/537.36"
10.20.0.128 - - [16:04:42 +0000] "GET /favicon.ico HTTP/1.1" 200 5 "https://example.com/" "Mozilla/5.0 (Macintosh; Intel Mac OS X) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/x Safari/537.36"

Wordpress container logs

127.0.0.1 - 16:04:42 +0000 "GET /index.php" 500
127.0.0.1 - 16:04:42 +0000 "GET /index.php" 200

I personally think there is something simple missing here, but I haven't been able to point it out in the past few days. Anyone know what I'm missing here?

-- cookiedough
kubernetes
mysql
nginx
wordpress

1 Answer

1/31/2019

I solved this problem by replacing the secret I used to access my database from my wordpress pod. To confirm that the secret was the issue, I created a secret and deployed mysql with a secret reference for MYSQL_ROOT_PASSWORD and giving the same secret reference as the db password in my wordpress pod. Since they were both using the same secret object this worked and fixed the db connection issue.

FIX: Helm automatically creates a db secret that includes all of your password / used / db name entries. Use the automatically created secret in the wordpress yaml file instead of the one you create:

helm install --name mysql-helm --set \
mysqlRootPassword=xxx,mysqlUser=xxx,mysqlPassword=xxx, \
mysqlDatabase=xxx,persistence.size=50Gi \
stable/mysql

Use the created password secret like this:

        - name: DB_PASSWORD
          valueFrom:
            secretKeyRef:
              name: mysql-helm
              key: password
-- cookiedough
Source: StackOverflow