A WordPress on Linode LKE, Part 2

Introduction

In the previous post, I showed how to create the basic infrastructure on the linode.com provider. To follow along, you will need a Kubernetes cluster, and your workstation configured to manage that cluster via kubectl.

Cloning the repository

To start, clone my github public repository. You will find it here. I like to use git from the command line, and this command will clone the repo.

git clone https://github.com/brunzefb/linode_public.git

Nginx Ingress intro

We then need a reverse proxy to handle the ingress. I don’t want to get into the details too much, as this could be a very long blog post indeed. It’s good to know how the ingress actually happens, and it goes like this:

DNS -> NodeBalancer IP-> nginx ingress (reverse proxy) -> WordPress Service ->Wordpress pod

A user types in the web address of your new site. DNS does a lookup, and resolves to the NodeBalancer IP. The browser sends the GET request to this to initiate the https connection. The NodeBalancer is aware of the nginx ingress, as the latter has registered itself with the node balancer. The traffic now ends up at the nginx ingress, which is aware of Cert-mangers’ certificate,and will now terminate TLS properly. Once actual requests come in over the secure link, nginx forwards the requests to the WordPress service. The service then forwards the traffic to the WordPress pod and container.

Setup nginx

1. cd [repo-root]/helm/nginx
2. edit the install.sh file, replacing username, password, hostname.
3. bash install.sh
4. Enter a password - this is the password you will use to log in as administrator to the site.

The script will install nginx for you. The values file for the nginx has some non-default security and header-size related items, which are beneficial. There is also an annotation that links nginx to the cert-manager.

#!/bin/bash
echo "Enter WP password:"
read -s password

helm upgrade \
  wordpress \
  ./ \
  --set wordpressUsername="brunzefb" \
  --set wordpressPassword="$password" \
  --set wordpressEmail="brunzefb@gmail.com" \
  --set wordpressLastName="Brunzema" \
  --set wordpressFirstName="Friedrich" \
  --set wordpressBlogName="Friedrich's Blog" \
  --set mariadb.auth.rootPassword="$passworddb" \
  --set mariadb.auth.password="$passworddb" \
  --set ingress.enabled=true \
  --set ingress.hostname="blog.brunzema.com" \
  --set ingress.annotations."cert-manager\.io/cluster-issuer"="letsencrypt-prod" \
  --set ingress.tls=true \
  --set ingress.ingressClassName="nginx" \
  --install \
  --namespace apps \

One can check to make sure things worked by running:

$ kubectl get svc | grep nginx                                                                                       (lke75938-ctx/apps)
nginx-nginx-ingress-controller                   LoadBalancer   10.128.7.181     172.105.1.76     80:32296/TCP,443:30127/TCP   8h
nginx-nginx-ingress-controller-default-backend   ClusterIP      10.128.221.1     <none>           80/TCP                       8h

$ kubectl get po | grep nginx                                                                                        (lke75938-ctx/apps)
nginx-nginx-ingress-controller-746dd9cf68-v57x7                   1/1     Running   0              4h17m
nginx-nginx-ingress-controller-default-backend-869b658bcc-kqdpg   1/1     Running   0              8h

Note the 172.105.1.76 is the external IP address, the one of the nodebalancer.

Cert-manager

Now that nginx is up, we need to worry about certificates. Since we want our site TLS-protected, we need a certificate for its DNS name. While one can buy a certificate from a commercial provider, these cost money . The ACME (automatic certificate management engine, the company where Wiley the coyote shops!) certbot, and this wrapper, cert-manager offer automatic certificate issuance and automatic renewal once set up. Let’s get going. In a terminal do the following:

1. kubectl create ns apps
2. cd [repo-root]/helm/certmgr 
3. bash install.sh
4. Edit the acme-issuer.yaml file and add your email.
5. kubectl apply -f acme-issuer.yaml

Did I mention that one needs to have helm installed for step 3 to work? To see if things worked, list the pods, and look for one named cert-manager, and one named cert-manager-webhook. They should be running. Get the certificate by running:

$ k get Certificate                                                                                                  (lke75938-ctx/apps)
NAME                    READY   SECRET                  AGE
blog.brunzema.com-tls   True    blog.brunzema.com-tls   5h1m

If things worked correctly, the TLS secret is also present.

WordPress

Now that we have nginx and cert-manager running, and a brand-new TLS certificate for our domain, we can install WordPress. One can install it by navigating to the helm/wordpress folder and editing and running bash install.sh

#!/bin/bash
echo "Enter WP password:"
read -s password

helm upgrade \
  wordpress \
  ./ \
  --set wordpressUsername="brunzefb" \
  --set wordpressPassword="$password" \
  --set wordpressEmail="brunzefb@gmail.com" \
  --set wordpressLastName="Brunzema" \
  --set wordpressFirstName="Friedrich" \
  --set wordpressBlogName="Friedrich's Blog" \
  --set mariadb.auth.rootPassword="$passworddb" \
  --set mariadb.auth.password="$passworddb" \
  --set ingress.enabled=true \
  --set ingress.hostname="blog.brunzema.com" \
  --set ingress.annotations."cert-manager\.io/cluster-issuer"="letsencrypt-prod" \
  --set ingress.tls=true \
  --set ingress.ingressClassName="nginx" \
  --install \
  --namespace apps \

The script will ask for a password, and then install the WordPress software on your cluster. Ensure you change the relevant values, such as the ingress, hostname, email and username

The install will take a few minutes. It will take time for the pods to become ready. The chart provisions 2 volumes that hold the MariaDB filesystem, and the WordPress files. Keeping the database and WordPress uploads in a persistent volume means that no data loss will happen if a container restarts.

$ k get po | grep wordpress                                                                                          (lke75938-ctx/apps)
wordpress-bd76d8db5-qxh9w                                         1/1     Running   0              5h37m
wordpress-mariadb-0                                               1/1     Running   0              5h54m
$ k get ing | grep wordpress (lke75938-ctx/apps)
wordpress nginx blog.brunzema.com 139.144.110.147 80, 443 5h54m

If the pod is running and the ingress is available, the installation likely works.

DNS setup

The last piece of the puzzle is the DNS setup. The DNS name must point to the Node Balancer IP address. I showed how to do this in the previous post. Use the command kubectl get svc | grep nginx. This will get one an external IP one needs to enter in Linode DNS manager. Once enough time passes for DNS propagation, and nslookup [name] returns the IP address of the NodeBalancer, we can take the site for a spin, and navigate to the new address.

Logging into the admin interface

The site, if it loads, will show a boring theme, and basically no content. It is time to log into the WordPress Management interface to set things up. Navigate to https://yoururl.com/wp-admin. Enter the username/password as configured in the previous step.

WordPress plugins I use:

Here is a subset of useful plugins I use on my site.

Plugin Comment
Advanced WordPress reset To completely wipe the database. Careful with that one.
AntiSpam Bee Detect spam in comments.
Classic Editor Use this if you need code snippets.
Enlighter – Customizable Syntax Highlighter For syntax -aware code snippets.
UpdraftPlus – Backup/Restore For Backup.
Wordfence Security Because there are lots of evil hackers out there.
WP Activity Log Provides logs, just in case.
WP Super Cache Faster access.
Yoast SEO Provides good writing tips.

Restoring to a newly named domain

If you had a previously running site, you will want to restore a backup of the database, the uploads, the themes and other files. One cannot restore the old backup, since there are a multitude internal links that have the old URL, and now there is a new URL. One can gunzip the .db file, and do a careful search/replace in the file. Replacing https://oldsite.com with https://newsite.com does the trick. Save the file, gzip it back to the original filename. Then upload the backup files via the settings on the updraft plugin, and hit restore. Be mindful of the database password the old site used, and use the same password for the new site. If one does not take care, the WordPress pod will not work, since you are restoring all the old configuration. This includes the password for the database.

Leave a Reply