April 3, 2019

Deploying wordpress in google kubernetes engine (GKE) and exposing it using load balancer (http and https)

In this blog you will learn how to deploy wordpress in google kubernetes engine (GKE) using persistent volumes. Then exposing it using NodePort and google cloud http(s) load balancer.
This blog covers the following topics:

  1. Creating kubernetes cluster in google cloud.
  2. Persistent volumes in kubernetes.
  3. Deploying Mysql and Wordpess.
  4. Exposing wordpress using NodePort.
  5. Setting firewall rules for load balancer.
  6. Setting up the HTTP(S) Load Balancer.

1. Creating kubernetes cluster in google cloud

Create a new google cloud account. It comes with 300$ credit for 12 months. To learn more about free usage of google cloud click here. Then make sure that billing is enabled for the google cloud project. Google Kubernetes is only accessible if billing is enabled. Once billing is enabled, follow the steps to create a kubernetes cluster:

  1. Navigation menu -> Compute -> Kubernetes Engine -> Clusters. You can pin Kubernetes Engine for easier access.
  2. Select create cluster to create a new kubernetes cluster.
  3. Select your first cluster if you are just experimenting.
  4. Fill the name, zone, kubernetes version.
  5. Node pools are list of VM instances to be added to the kubernetes cluster.
  6. Choose the number of nodes for the cluster and the VM instance type.
  7. Select Advanced edit (More node pool options) to change the boot disk’s type and size (By default it is standard persistent disk with 100GB).
  8. Click on create

Alternatively you can create cluster using gcloud command line tool:

gcloud container clusters create wordpress --num-nodes=1 --disk-type=pd-standard --disk-size=50GB

Pictures speak better than words, so here are some snippets to creating a kubernetes cluster in google cloud:

1. Selecting kubernetes cluster
2. Select Create Cluster
3. Select cluster template and fill cluster information
4. Configure the node pool
5. Create the cluster

2. Persistent Volumes in Kubernetes

Persistent Volumes are resources just like a node in kubernetes cluster. The volumes are isolated from the nodes, thus are independent of pods. The data in the persistent volume are independent of pod’s life cycle, thus we can retain the data even if wordpress goes down for some reason. Google cloud creates persistent volumes if volume claims are created in the kubernetes cluster which does not have an existing persistent volume.
You can find the kubernetes manifest files needed for deploying wordpress in Google Kubernetes engine here:

git clone https://github.com/GoogleCloudPlatform/kubernetes-engine-samples
cd kubernetes-engine-samples/wordpress-persistent-disks

We need to create two persistent volumes for Mysql and WordPress. To create this we need two volume claims. Here is sample manifest files for mysql and wordpress volume claims.

We need to login to google kubernetes using the following command:

gcloud container clusters get-credentials wordpress --zone asia-south1-a --project bubbly-dynamo-xxx

mysql-volumeclaim.yaml:


kind: PersistentVolumeClaim
apiVersion: v1
metadata:
  name: mysql-volumeclaim
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 30Gi

wordpress-volumeclaim.yaml:


kind: PersistentVolumeClaim
apiVersion: v1
metadata:
  name: wordpress-volumeclaim
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 30Gi

Following command is used to create the volumes and volume claims.

kubectl apply -f mysql-volumeclaim.yaml
kubectl apply -f wordpress-volumeclaim.yaml

It will take few seconds to create the volumes and volume claims. You can check if it is created by using the following commands:

kubectl get pv

kubectl get pvc

3. Deploying Mysql and WordPress

3.1 Deploying Mysql application

Before deploying mysql database, the database password needs to be set. Kubernetes provides secrets which can store confidential information or environmental variables required. Following command is used to create password secret for Mysql. Replace {password} with your password.

kubectl create secret generic mysql \
--from-literal=password={password}

Once it is created, we need to create manifest file for mysql app with the secret created. The manifest file will look like this:

mysql.yaml:


apiVersion: apps/v1
kind: Deployment
metadata:
  name: mysql
  labels:
    app: mysql
spec:
  replicas: 1
  selector:
    matchLabels:
      app: mysql
  template:
    metadata:
      labels:
        app: mysql
    spec:
      containers:
        - image: mysql:5.6
          name: mysql
          env:
            - name: MYSQL_ROOT_PASSWORD
              valueFrom:
                secretKeyRef:
                  name: mysql
                  key: password
          ports:
            - containerPort: 3306
              name: mysql
          volumeMounts:
            - name: mysql-persistent-storage
              mountPath: /var/lib/mysql
      volumes:
        - name: mysql-persistent-storage
          persistentVolumeClaim:
            claimName: mysql-volumeclaim

This will create a deployment for Mysql app with one pod. The password for Mysql server is obtained from the secret created. Mysql will also consume the volume that we have created to store data.
Following command is used to deploy the Mysql app:

kubectl create -f mysql.yaml

Once the Mysql app is deployed, it will take some time for the app to be up and running. You can check if the pods are in running state using the following command.

kubectl get pod -l app=mysql

3.2 Exposing Mysql internally using service

Now that the app is up and running, we need to expose the app inside the cluster so that wordpress can access it. To do that we need to create a service which exposes it as ClusterIP. It means that the app is only accessible inside the cluster. The manifest file required to create the service is as follows:

mysql-service.yaml:


apiVersion: v1
kind: Service
metadata:
  name: mysql
  labels:
    app: mysql
spec:
  type: ClusterIP
  ports:
    - port: 3306
  selector:
    app: mysql

This will expose mysql app using 3306 port to the cluster. The following command is used to create the service:

kubectl create -f mysql-service.yaml

This will expose the app to the cluster. A cluster IP is assigned to the service which can used to access mysql app internally. Alternatively you can use the name of service to access mysql (mysql:3306). Use the following command to check whether the service is created:

kubectl get service mysql

3.3 Deploying wordpress application

Next step is to deploy the wordpress app in the cluster. This is similar to how mysql app was deployed. The manifest for wordpress app deployment is as follows:

wordpress.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: wordpress
          name: wordpress
          env:
          - name: WORDPRESS_DB_HOST
            value: mysql:3306
          - name: WORDPRESS_DB_PASSWORD
            valueFrom:
              secretKeyRef:
                name: mysql
                key: password
          ports:
            - containerPort: 80
              name: wordpress
          volumeMounts:
            - name: wordpress-persistent-storage
              mountPath: /var/www/html
      volumes:
        - name: wordpress-persistent-storage
          persistentVolumeClaim:
            claimName: wordpress-volumeclaim

The manifest file specifies that the wordpress application will use the persistent volume that was created earlier. It also connects to Mysql database created by using the mysql service which is exposed to the cluster. The password for connecting to the database is obtained from the secret we have created. It also species that one replica/pod is created for the wordpress app.

Following command is used to deploy the application in the cluster:

kubectl create -f wordpress.yaml

It will take some time for the application to be up and running. Following command is used to check if the application pods are running:

kubectl get pod -l app=wordpress

4. Exposing wordpress using NodePort

Now that we have deployed the wordpress application. We need to expose it to the outside world. You can either do it by LoadBalancer service or NodePort with google cloud load balancer. We will now be exposing the application using NodePort + Google Cloud Load Balancer. The manifest file for NodePort will look like this:

wordpress-nodeport.yaml:


apiVersion: v1
kind: Service
metadata:
  name: wordpress
spec:
  type: NodePort
  selector:
    app: wordpress
  ports:
  - name: wordpress-port
    protocol: TCP
    port: 80
    targetPort: 80

Use the following command to deploy the NodePort service:

kubectl create -f wordpress-nodeport.yaml

This will expose the wordpress application in each of the cluster’s node. You can get the port from the following command:

kubectl get service

wordpress    NodePort    4.4.2.1           3001:32133/TCP   2d

From the following output we can see that the wordpress application is exposed in each node via port 32133.

5. Setting firewall rules for load balancer

Now we need to create a firewall rule which allows the google cloud loadbalancer and healthchecker to access the nodes (VM instances). The steps to configure the firewall rule are:

  1. Navigation Menu -> Networking -> VPC network -> Firewall rules.
  2. Select create firewall rule.
  3. Set the firewall rule name, ensure that the firewall rule’s target points to the VM group of the kubernetes cluster.
  4. In the source filter select IP Ranges and Source IP ranges as 35.191.0.0/16, 130.211.0.0/22.
  5. This will allow the load balancers and health checker to access the nodes in the Kubernetes cluster.
  6. In Protocols and ports, select tcp: 32133. Or you can allow all ports in tcp.
  7. Create the firewall rule.

6. Setting up the HTTP(S) Load Balancer

6.1 Exposing it using port 80 (HTTP)

Steps to create a http loadbalancer:

  1. Navigation Menu -> Networking -> Network services -> Load Balancing.
  2. Select Create Load Balancer.
  3. Select HTTP(S) Load Balancing -> Start Configuring.
  4. Configure the load balancer:
    1. Backend configuration – Create a backend service. Set the name, select instance group and port number (32133) and create a health check.
    2. Configure the Host and path rules.
    3. Frontend Configuration – Set the name, select http as protocol, Create a new static IP.
  5. Then create the load balancer.

It will take some time for the load balancer to be provisioned. Once it is done an external IP is assigned to the Load Balancer’s Frontend. You can use the ip address to access wordpress. Your map the IP address with your domain name in you DNS provider. Generally it a A record which maps the IP Address with the domain name (sub-domain).

6.2 Exposing it using 443 (HTTPS)

Now that we have exposed the application to the world using http. But http is not secure, many browsers have started deprecated http websites. So, it is time for us to expose it using https. It is simple to expose using https using google load balancer. Steps to expose https in the existing load balancer is as follows:

  1. Navigation Menu -> Networking -> Network services -> Load Balancing.
  2. Select the load balancer we have created already.
  3. Select Edit -> Frontend configuration.
  4. Select Add Frontend IP and port.
  5. Set the name, select https protocol.
  6. When selecting IP address, select the already created static IP address. This will allow http and https to be routed through same IP address and easy to include in DNS record.
  7. Now we need to select the SSL certificate. If you already have one add them using steps provided here.
  8. Alternatively, you can let google cloud manage your SSL certificate. Google Cloud will take care of renewing your certificate. To use google managed certificate follow these steps:
    1. Select create new certificate -> provide name for the certificate -> Select Create Google-managed certificate.
    2. Provide the domain name for which certificate needs to be issued for.
    3. Make sure that the Domain is associated with the IP address.
    4. It will take some time for the certificate to be Active. Once it is active you can visit your site as https://example.domain.com.