Google Cloud CDN for GCP WordPress

The more (concurrent) traffic a website receives, the more important it is for its contents to be hosted on a content delivery network (CDN). By having your site resources spread out across many servers across many regions around the world, it will take much less time (in terms of “hops”, or jumps from server to server a request needs to make) to fetch the site’s contents.

One of Google Cloud’s less-known features is its Cloud CDN which leverages Google’s global network of data centers, servers, and ISP integration to deliver content to the end user in a quick manner. Its efficiency is further increased when coupled or used with other services in Google and Google Cloud, such as Google Domains, Google DNS, and Google Compute Instances. Since 2018, this site is hosted using Google’s Click-to-Deploy WordPress deployment (tutorial) using Google Domains (tutorial) with SSL encryption (tutorial) and maintenance via SSH to instance VMs (such as updating PHP version in Google Cloud VM Instance). Thus it is natural to leverage Google Cloud CDN, with the added benefit that it won’t break with updates to WordPress since the CDN configuration happens server-side and not WordPress-side.

Follow along with me as we explore how to activate Google CDN for your Google Cloud-hosted service.

Assumptions

This guide assumes the following:

  • Your website uses Google Cloud VM instance(s) in an unmanaged instance group.
  • You have access to Google Cloud Console and SSH privileges into your VM instance(s).
  • Your website is HTTPS with a valid SSL Certificate.
  • Access to DNS settings (whether Google Cloud DNS or otherwise).

Before We Begin

Your site should experience almost no downtime (with the exception of resolving DNS to the new load balancer global IP) if everything is configured and works correctly. This guide piggybacks off of Google Cloud’s official documentation on Setting up Cloud CDN with a managed instance group, but there are quite a few changes we need to make to align with the assumptions above, namely:

  • In addition to HTTP/80, configuration for HTTPS/443 is also required.
  • We are applying CDN to an UNmanaged instance group.
  • Slightly different Health Check procedure.

Don’t worry, there will be reminders throughout this guide if we deviate from the official tutorial from Google Cloud.

Setup

Add Health Check Tag to Instance VM

The health check and firewall rules need to know which instances to apply the health check to, which can be accomplished easily by applying tags to the instance VM. Add allow-health-check as a tag to all instance VMs for your service:

Figure 1-1: Add allow-health-check tag to instance VM. This does not require you to restart the VM.

Instance Group Settings

Figure 1-2: Unmanaged instance group summary page.

If not done so already, you will need to add your VM instances into an instance group. This tutorial assumes you already have a VM instance NOT created via an instance template and therefore can only be added into an UNmanaged instance group.

Figure 1-3: Sample setting for adding existing VM Instance to unmanaged instance group. Note region and zone needs to be the same with all the VM instances to be added to the group.

One extra setting you will need to do is to add named ports for HTTP/80 and HTTPS/443 to the instance group. Follow the section here, but don’t forget to also add HTTPS/443 as well.

Figure 1-4: Sample settings for specifying named ports in an instance group.

Set Up Firewall

Follow the official guide section here to configure firewall rules for your health check. Note that our health check will use only HTTP/80 and so it is NOT necessary to add HTTPS/443. You are free to modify the name of the firewall rule but keep all other values (IP ranges and tag name) the same.

Figure 1-5: Firewall rule setting. Only HTTP/80 is configured,

Set Up Load Balancer

Google Cloud CDN operates alongside a load balancer with forwarding rule applied to a global IP address. All three settings are initialized and configured at the same time. This is the hardest part of the tutorial, but don’t fret! I will walk you through the steps as detailed as I can.

Create a Health Check Page

The default settings for a health check as indicated in the official guide has a Request path of “/” which generally points to the main page of your website. The main page contains many content and is overkill to be used for a simple ping, so it is highly advised to create a separate page with a few words of text to minimize the overhead. We can actually use the sample code in Step 11 here to create a simple page. SSH into your instance VM and execute the following code:

vm_hostname="$(curl -H "Metadata-Flavor:Google" \
http://169.254.169.254/computeMetadata/v1/instance/name)"
echo "Page served from: $vm_hostname" | \
sudo tee /var/www/html/healthcheck.html

This will create a page called “healthcheck.html” on your root site directory containing the name of the VM instance. Note this page name as you will use it when configuring health check in just a moment.

Retrieve SSL Certificate Public and Private Keys

Because we are allowing HTTPS connection through the load balancer, at some point in the below guide you will be asked to provide the SSL certificate for your website. If you have configured your SSL certificate via Certbot (the same way I have as outlined in my other post), then SSH into your VM instance (using a separate browser tab) and execute the following commands to retrieve your public and private SSL certificate keys:

sudo certbot certificates

The output should give you something similar to the following, in which you can just view its contents to find all the certificate keys you need:

# Replace ##DOMAIN## with whatever is output in the above command
sudo cat /etc/letsencrypt/live/##DOMAIN##/fullchain.pem
sudo cat /etc/letsencrypt/live/##DOMAIN##/privkey.pem
Figure 2-1: Sample certbot output. “fullchain.pem” gives the public keys (include certificate chains). “privkey.pem” yields the private key. Ignore the “^C” at the end of the sudo cat commands.

Hold onto these outputs as you will need to copy-paste them later.

Configure the Backend Service

Follow the “Setting up the load balancer” section up until you finish Step 6 in its entirety. However, note that step 6c should be changed to HTTPS, 6d to “https“, and 6f to “443“. Refer to below figure for an example.

Figure 2-2: Sample configuration for HTTPS backend service (first half)

Check “Enable Cloud CDN” so that the system will automatically configure the Cloud CDN for you. For Health Check, since we haven’t created one yet, go ahead and follow the prompt to create new. Change the protocol to HTTP and use port 80 (remember our health check uses HTTP/80 and not HTTPS). Most importantly, the “Request path” should be configured to the health check page you created above (/healthcheck.html), relative to the root of the site directory.

Figure 2-3: Sample health check setting. Note the “Request path” should be configured to a page on your site. This page can be manually created via SSH into your server.

Return to the backend settings and finish the rest of the configuration.

Figure 2-4: Sample configuration for HTTPS backend service (second half)

Configure the Frontend Service

Step 8 of the official guide assumes we already have an external IP address reserved, but I left it out until now because we can configure it here. You will need to configure TWO protocols – one for HTTP and HTTPS. When needing to specify the IP address, select “Create IP address” to create one on-the-spot.

Figure 2-5: HTTP port forwarding configuration

For configuring the forwarding rule for HTTPS, a few additional steps are required, namely providing the SSL certificate keys. For certificate section, click on “Create a new certificate” to reach the UI below.

Figure 2-6: Port Forwarding HTTPS cert configuration.

Here is where you take the outputs from “Retrieve SSL Certificate Public and Private Keys” section above and paste them here. Note that your “fullchain.pem” should actually contain TWO certificate sections, the first one should be copy pasted into the “Public key certificate” field and the second one into the “Certificate chain” field. “privkey.pem” only has one key which you can just copy the entire file contents and paste into “Private key”.

Below is a sample frontend configuration for HTTPS.

Figure 2-7: HTTPS port forwarding configuration.

Follow the rest of the official guide until you finish setting up the load balancer.

Testing Load Balancer Configurations

Take several moments break for the load balancer to finish initialization. It should look like the below figure once finished. Note that the green check mark indicates the backend is configured correctly and that the health check is working as intended. If it is NOT green then revisit the above steps (and also using the official guide as reference) to diagnose the issue. For more concrete evidence, following “Testing traffic sent to your instance” section should direct you to the homepage of your website (ignore what step 5 says).

Figure 3-1: A normal, working load balancer setting

Modify DNS Settings

If the above load balancer test is successful, it is time to change the DNS settings “A” record from your previous single VM instance IP address to the load balancer global IP address. The global IP address can be found by clicking on the name of your load balancer in the load balancer settings page (Refer to Figure 3-1).

Figure 3-2: (Google Cloud DNS) Change “A” record to load balancer global IP.

Enter your hostname into DNS Checker and verify that the global DNS servers return your load balancer’s IP address as the result. It may take a few moments for propagation. Once propagated, do a final check by accessing your site using your hostname (recommended to use incognito or private browser to test).

Congratulations! Your site is now configured for Google Cloud DNS! However, there are a few additional checks to make sure Google Cloud DNS is actually cacheing your website resources…

Test Caching Settings

Google Cloud DNS actually has a few rules on what resources can be cached, which can be found in detail here. After understanding the rules, use a caching checker such as this one, fill in your site, and look at the results. Your cached resources are listed in the “Cached Files” section, but there is a catch. Google Cloud DNS does NOT cache resources when cached via ETAG. Alternatively speaking, if you see a “Type: Cache-Control” tag with another tag specifying the expiry duration for a resources hosted on your domain, then that means your resource is properly cached using a CDN.

If you find your domain resources are not being cached, then check your WordPress Cache Settings and verify that caching settings are turned on. If the problem is still not resolved then follow the server-side guide here as well. For this site the WordPress cache settings were fine and my VM instance just did not have the mod_expires module enabled.