How to deploy WordPress and MySQL on OKE using MySQL Operator for Kubernetes

October 12, 2023 | 8 minute read
Frederic Descamps
MySQL Community Manager
Text Size 100%:

Let’s see how to deploy WordPress and MySQL on a Kubernetes Cluster. The Kubernets cluster we are using is OKE (Oracle Kubernetes Engine) in OCI (Oracle Cloud Infrastructure):

OKE architecture

OKE Cluster

We start by creating a Kubernetes Cluster on OCI using the Console:

OKE Cluster

We select the Quick create mode:

Quick Create

We need to name our cluster and make some choices:

Create Cluster

Creat Cluster (2)

When created, we can find it in the OKE Clusters list:
List of Clusters


And we can see the pool of workers nodes and the workers:

Cluster details

Pool details

Workers

kubectl

I like to use kubectl directly on my latop to manage my K8s Cluster.

On my Linux Desktop, I need to install kubernetes-client package (rpm).

Then on the K8s Cluster details, you can click on Access Cluster to get all the commands to use:

Access Cluster

Access Cluster Commands

We need to copy them on our terminal and then, I like to also enable the bash completion for kubectl in my environment:

Copied to Clipboard
Error: Could not Copy
Copied to Clipboard
Error: Could not Copy
$ source <(kubectl completion bash)
$ echo "source <(kubectl completion bash)" >> $HOME/.bashrc

And now, we can easily test it:

Copied to Clipboard
Error: Could not Copy
Copied to Clipboard
Error: Could not Copy
$ kubectl get nodes
NAME          STATUS   ROLES   AGE     VERSION
10.0.10.155   Ready    node    21s     v1.27.2
10.0.10.193   Ready    node    21s     v1.27.2
10.0.10.216   Ready    node    21s     v1.27.2

MySQL Operator Deployment

To deploy MySQL, we use the mysql-operator for Kubernetes that manages the deployment of an InnoDB Cluster (including MySQL Router).

This is an overview of the architecture:

MySQL-Operator Architecture

We start by installing the operator using manifest files:

Copied to Clipboard
Error: Could not Copy
Copied to Clipboard
Error: Could not Copy
$ kubectl apply -f https://raw.githubusercontent.com/mysql/mysql-operator/trunk/deploy/deploy-crds.yaml
customresourcedefinition.apiextensions.k8s.io/innodbclusters.mysql.oracle.com created
customresourcedefinition.apiextensions.k8s.io/mysqlbackups.mysql.oracle.com created
customresourcedefinition.apiextensions.k8s.io/clusterkopfpeerings.zalando.org created
customresourcedefinition.apiextensions.k8s.io/kopfpeerings.zalando.org created

$ kubectl apply -f https://raw.githubusercontent.com/mysql/mysql-operator/trunk/deploy/deploy-operator.yaml
clusterrole.rbac.authorization.k8s.io/mysql-operator created
clusterrole.rbac.authorization.k8s.io/mysql-sidecar created
clusterrolebinding.rbac.authorization.k8s.io/mysql-operator-rolebinding created
clusterkopfpeering.zalando.org/mysql-operator created
namespace/mysql-operator created
serviceaccount/mysql-operator-sa created
deployment.apps/mysql-operator created

We can verify that the mysql-operator for Kubernetes has been successfully deployed and that it’s reay:

Copied to Clipboard
Error: Could not Copy
Copied to Clipboard
Error: Could not Copy
$ kubectl get deployment mysql-operator --namespace mysql-operator
NAME             READY   UP-TO-DATE   AVAILABLE   AGE
mysql-operator   1/1     1            1           35s

MySQL InnoDB Cluster

For our architecture, we will create two namespaces:

  • web-database: for everything related to MySQL
  • web-frontend: for the webservers

This is how we create them:

Copied to Clipboard
Error: Could not Copy
Copied to Clipboard
Error: Could not Copy
$ kubectl create ns web-database
$ kubectl create ns web-frontend

We need to create the password for the root MySQL user. We use K8s Secret resource to store the credentials:

Copied to Clipboard
Error: Could not Copy
Copied to Clipboard
Error: Could not Copy
$ kubectl -n web-database create secret generic mypwds \
        --from-literal=rootUser=root \
        --from-literal=rootHost=% \
        --from-literal=rootPassword="Passw0rd!"

We can verify that the credentials were created correctly:

Copied to Clipboard
Error: Could not Copy
Copied to Clipboard
Error: Could not Copy
$ kubectl -n web-database get secret mypwds
NAME     TYPE     DATA   AGE
mypwds   Opaque   3      112s

Just for fun, you can try to decode the password (or in case you forgot it):

Copied to Clipboard
Error: Could not Copy
Copied to Clipboard
Error: Could not Copy
$ kubectl -n web-database get secret mypwds -o yaml | \
> grep rootPassword | cut -d: -f 2 | xargs | base64 -d
Passw0rd!

To deploy our first MySQL InnoDB Cluster, we need to create a YAML file (mycluster.yaml):

Copied to Clipboard
Error: Could not Copy
Copied to Clipboard
Error: Could not Copy
apiVersion: mysql.oracle.com/v2
kind: InnoDBCluster
metadata:
  name: mycluster
spec:
  secretName: mypwds
  tlsUseSelfSigned: true
  instances: 3
  router:
    instances: 1

And we deploy it in the web-database namespace:

Copied to Clipboard
Error: Could not Copy
Copied to Clipboard
Error: Could not Copy
$ kubectl -n web-database apply -f mycluster.yaml    
innodbcluster.mysql.oracle.com/mycluster created

We can verify the status of the pods:

Copied to Clipboard
Error: Could not Copy
Copied to Clipboard
Error: Could not Copy
$ kubectl -n web-database get pods
NAME          READY   STATUS            RESTARTS   AGE
mycluster-0   2/2     Running           0          80s
mycluster-1   0/2     PodInitializing   0          80s
mycluster-2   0/2     Init:2/3          0          80s

After a while, we can check several resources that have been deployed by the operator:

kubectl

We will deploy a new pod to connect to our MySQL instances using MySQL Shell. We connect through the router (port 6446):

Copied to Clipboard
Error: Could not Copy
Copied to Clipboard
Error: Could not Copy
$ kubectl run --rm -it myshell \
--image=container-registry.oracle.com/mysql/community-operator -n web-database -- \
 mysqlsh root@mycluster.web-database.svc.cluster.local:6446
If you don't see a command prompt, try pressing enter.
********

And in MySQL Shell, we create the wordpress database and a dedicated user:

Copied to Clipboard
Error: Could not Copy
Copied to Clipboard
Error: Could not Copy
SQL> create database wordpress;

SQL> create user wordpress identified by 'W0rdPress';

SQL> grant all privileges on wordpress.* to wordpress;

WordPress

It’s time to deploy WordPress. Once again, we create a new YAML file (wordpress.yaml):

Copied to Clipboard
Error: Could not Copy
Copied to Clipboard
Error: Could not Copy
apiVersion: v1
kind: Service
metadata:
  name: wordpress
  labels:
    app: wordpress
spec:
  ports:
    - port: 80
  selector:
    app: wordpress
    tier: frontend
  type: LoadBalancer
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: wp-pv-claim
  labels:
    app: wordpress
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 20Gi
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: wordpress
  labels:
    app: wordpress
spec:
  replicas: 1
  selector:
    matchLabels:
      app: wordpress
      tier: frontend
  strategy:
    type: Recreate
  template:
    metadata:
      labels:
        app: wordpress
        tier: frontend
    spec:
      containers:
      - image: wordpress:latest
        name: wordpress
        env:
        - name: WORDPRESS_DB_NAME
          value: wordpress
        - name: WORDPRESS_DB_HOST
          value: mycluster.web-database.svc.cluster.local:6446
        - name: WORDPRESS_DB_PASSWORD
          valueFrom:
            secretKeyRef:
              name: mysql-pass
              key: password
        - name: WORDPRESS_DB_USER
          value: wordpress
        - name: WORDPRESS_CONFIG_EXTRA # enable SSL connection for MySQL
          value: |
            define('MYSQL_CLIENT_FLAGS', MYSQLI_CLIENT_SSL);
        ports:
        - containerPort: 80
          name: wordpress
        volumeMounts:
        - name: wordpress-persistent-storage
          mountPath: /var/www/html
      volumes:
      - name: wordpress-persistent-storage
        persistentVolumeClaim:
          claimName: wp-pv-claim

It’s very important to force the usage of client SSL for mysqli. If not, WordPress won’t work with a MySQL user using the recommended authentication plugin: caching_sha2_password

The deployment is easy:

Copied to Clipboard
Error: Could not Copy
Copied to Clipboard
Error: Could not Copy
$ kubectl -n web-frontend apply -f wordpress.yaml

And we can even scale the WordPress web servers very easily:

Copied to Clipboard
Error: Could not Copy
Copied to Clipboard
Error: Could not Copy
$ kubectl scale deployment wordpress --replicas=3 -n web-frontend
deployment.apps/wordpress scaled

Everything is deployed and ready to use:

kubctl -n web-frontend

If we use the external public IP, we join the last step of the WordPress installation:

WordPress

I’ve installed a PHP code snipped to see which of the 3 web servers I’m reaching when visiting the website:

WordPress 1

WordPress 2

WordPress 3

We can see that we are load balancing the requests accross the 3 web servers.

This is what we have deployed:

web-database

web-frontend

Conclusion

In this post, we have walked through the comprehensive steps to successfully deploy WordPress and MySQL on Oracle Kubernetes Engine (OKE) using the official mysql-operator for Kubernetes. This process simplifies the complex task of managing databases, automating many of complicated steps involved to setup High Availability.

Happy MySQL deployments in OKE using MySQL Operator for Kubernetes!

Frederic Descamps

MySQL Community Manager

lefred has been consulting OpenSource and MySQL for almost 20 years. After graduating in Management Information Technology, Frédéric started his career as a developer for an ERP under HPUX. He will then opt for a career in the world of open-source by joining one of the first Belgian start-up dedicated 100% to free projects around GNU/Linux. It is in 2011 that lefred joined Percona, one of the leading MySQL-based specialists. He decided to join the MySQL Community Team in 2016 as a MySQL Community Manager for EMEA & APAC. Frédéric is also a regular speaker of OpenSource Conferences. His blog mostly dedicated to MySQL is https://lefred.be Fred is also the devoted father of three adorable daughters: Wilhelmine, Héloïse & Barbara.

Show more

Previous Post

Introducing Data Import from Amazon S3 in MySQL HeatWave on AWS

Mandy Pang | 7 min read

Next Post


Machine learning with recommender system models in MySQL Heatwave AutoML

Sanjay Jinturkar | 6 min read
Oracle Chatbot
Disconnected