This post provides you with detailed and advanced steps to setup HTTP(S) Layer 7 Load Balancer for your web application on Google Cloud Platform.

Here we will set up WordPress, Nginx, PHP, Cloud SQL, and Cloud Storage for your Load Balancer.

Carefully follow this tutorial without missing any steps for a successful setup.

HTTP(S) Load Balancing can be configured and updated through three different interfaces:

  • gcloud command-line tool
  • Google Cloud Platform Console
  • Rest API

Steps to setup Load Balancing on Google Cloud

  1. Enable APIs and create a Service account
  2. Nginx configuration for Load Balancer
  3. Create Health Check
  4. Create Instance Template
  5. Create a Managed Instance Group
  6. Reserve Global Region IPv4 and IPv6 addresses
  7. Create Load Balancer
  8. Install LetsEncrypt SSL Certificate
  9. Configure DNS and setup Cloud CDN

Prerequisites

If you have all the above mentioned required requisites done and in place, you can proceed to setup Load Balancing.

Enable APIs and create a Service account

Go to APIs and Services and click Enable APIs and Services and enable Cloud SQL API and Cloud SQL Admin API

Now go to IAM & Admin >> Service accounts and click Create service account

In step 1

Enter Service account Name

Click Create

In step 2

Select Role

Cloud SQL >> Cloud SQL Client
Project >> Editor

Click Continue

In step 3

Click Create Key

Choose Key type as JSON

Click Create

Nginx Configuration for Load Balancer

If you have followed the WordPress setup above

Go to Compute Engine >> Instances and SSH into your instance. You must have a Nginx configuration file in your /etc/nginx/sites-available directory named as yourdomainname.com

Now you need to modify your Nginx configuration file to accept connections from Load Balancer, so edit the file

sudo nano /etc/nginx/sites-available/yourdomainname.com

and replace the contents with the following configuration and hit Ctrl+X followed by Y to save it. Make sure you replaced the yourdomainname.com with your domain name.

fastcgi_cache_path /home/username/yourdomainname.com/cache levels=1:2 keys_zone=yourdomainname.com:100m inactive=60m;

server {
    listen [::]:80;
    listen 80;

    server_name yourdomainname.com www.yourdomainname.com;

    if ($http_x_forwarded_proto != "https") {
        return 301 https://www.yourdomainname.com$request_uri;
    }

    error_log /home/username/yourdomainname.com/logs/error.log;

    root /home/username/yourdomainname.com/public/;
    index index.htm index.html index.php;

    set $skip_cache 0;

    if ($request_method = POST) {
        set $skip_cache 1;
    }

    if ($query_string != "") {
        set $skip_cache 1;
    }    

    if ( $cookie_woocommerce_items_in_cart = "1" ){
        set $skip_cache 1;
    }

    if ($request_uri ~* "/wp-admin/|wp-.*.php|/feed/|index.php|sitemap(_index)?.xml") {
        set $skip_cache 1;
    }
    
    if ($request_uri ~* "/(cart|checkout|my-account)/*$") {
        set $skip_cache 1;
    }

    if ($http_cookie ~* "comment_author|wordpress_[a-f0-9]+|wp-postpass|wordpress_no_cache|wordpress_logged_in") {
        set $skip_cache 1;
    }

    location = /favicon.ico {
        log_not_found off;
        access_log off;
    }
    location = /robots.txt {
        allow all;
        log_not_found off;
        access_log off;
    }

    location / {
        try_files $uri $uri/ /index.php?$args;
    }

    location ~ \.php$ {
        try_files $uri =404;
        fastcgi_split_path_info ^(.+\.php)(/.+)$;
        fastcgi_pass unix:/run/php/php7.2-fpm.sock;
        fastcgi_index index.php;
        include fastcgi_params;

        fastcgi_cache_bypass $skip_cache;
        fastcgi_no_cache $skip_cache;

        fastcgi_cache yourdomainname.com;

        fastcgi_cache_lock on;
        fastcgi_cache_use_stale error timeout invalid_header updating http_500;
        fastcgi_cache_valid 200 302 60m;
        fastcgi_cache_valid 301 1h;
        fastcgi_cache_valid any 1m;
        fastcgi_pass_header Set-Cookie:Set-Cookie;
        fastcgi_pass_header Cookie;
        fastcgi_ignore_headers Cache-Control Expires Set-Cookie;
        fastcgi_cache_background_update on;

        add_header X-Cache $upstream_cache_status;

        add_header Content-Security-Policy "img-src * 'self' data: blob: https:; default-src 'self' https://www.googletagmanager.com https://*.google-analytics.com https://www.yourdomainname.com https://*.googleapis.com https://*.gstatic.com https://*.gravatar.com https://*.w.org data: 'unsafe-inline' 'unsafe-eval';" always;
        add_header X-Xss-Protection "1; mode=block" always;
        add_header X-Frame-Options "SAMEORIGIN" always;
        add_header X-Content-Type-Options "nosniff" always;
        add_header Access-Control-Allow-Origin "https://www.yourdomainname.com";
        add_header Referrer-Policy "origin-when-cross-origin" always;
        add_header Strict-Transport-Security "max-age=31536000; includeSubdomains; preload";
    }

    location ~*  \.(jpg|jpeg|png|gif|ico)$ {
        expires 365d;
        add_header Cache-Control "public";
    }

    location ~* \.(?:css|js)$ {
        expires 7d;
        add_header Cache-Control "public";
    }

    location ~* \.(?:eot|woff|woff2|ttf|svg|otf) {
        expires 30d;
        add_header Cache-Control "public";

        types     {font/opentype otf;}
        types     {application/vnd.ms-fontobject eot;}
        types     {font/truetype ttf;}
        types     {application/font-woff woff;}
        types     {font/x-woff woff2;}  
    }
}

Now edit the /etc/nginx/nginx.conf file and change the value of keepalive_timeout directive to 650s and save the file.

Connect to Cloud SQL

Next edit the WordPress config file by issuing the following command

sudo nano ~/yourdomainname.com/public/wp-config.php

As the instances are created dynamically you ned to connect to Cloud SQL using Cloud SQL proxy or with Private IP.

Using Cloud SQL proxy

Change hostname to 127.0.0.1

Using Private IP

Go to your Cloud SQL Instance and enable Private IP.

Change hostname to PRIVATE_IP_ADDRESS

While using Private IP, make sure you are using the same VPN network.

Below define('DB_COLLATE', ''); add the following

define('FORCE_SSL_ADMIN', true);
if (strpos($_SERVER['HTTP_X_FORWARDED_PROTO'], 'https') !== false)
    $_SERVER['HTTPS']='on';

Create Instance Template

Next, stop the VM Instance and go to Compute Engine >> Images and click Create Image.

In Name enter a unique name

In Source select Disk

In Source Disk select the disk of your VM Instance

Click Create

Load Balancing Create Image

Once the Image is created go to Compute Engine >> Instance templates and click Create instance template

In Name enter name of the template

In Machine type choose 1 vCPU 3.75 GB RAM

In the Boot Disk click Change and click the Custom images tab.

Choose the Image that you created earlier

In the Boot disk type select SSD persistent disk

Click Select

In Identity and API access choose Allow full access to all Cloud APIs

In Firewall check both Allow HTTP traffic and Allow HTTPS traffic

Cloud SQL Proxy connection

If you are using the Private IP address to connect to Cloud SQL, you can skip the startup script.

In the Management tab find the Startup script and enter the following

#! /bin/bash
sudo apt-get update
sudo apt-get install mysql-client
wget https://dl.google.com/cloudsql/cloud_sql_proxy.linux.amd64 -O cloud_sql_proxy
chmod +x cloud_sql_proxy
sudo mkdir /cloudsql; sudo chmod 777 /cloudsql
./cloud_sql_proxy -instances=INSTANCE_CONNECTION_NAME=tcp:3306

Replace the INSTANCE_CONNECTION_NAME with your Cloud SQL connection name

In the Networking tab make sure Premium is selected in Network Service Tier

Click Create

Load Balancing Create Instance Template

Create a Managed Instance Group

Goto Compute Engine >> Instance groups and click Create instance group

In Name enter name

In Location choose Single-zone

In Region choose your preferred region

Click Specify port name mapping

In Port name enter http and in Port numbers enter 80

In Group type choose Managed instance group

In Instance template select the instance template you just created

Leave everything to default and click Create

Load Balancing Create Instance Group

Reserve Global Region IPv4 and IPv6 Address

Go to VPC network >> External IP addresses and click Reserve Static IP Address

In Name enter a name for IPv4 address

In Network Service Tier choose Premium

In IP version choose IPv4

In Type choose Global

Click Reserve

Again click Reserve Static IP Address

In Name enter a name for IPv6 address

In Network Service Tier choose Premium

In IP version choose IPv6

In Type choose Global

Click Reserve

Create Load Balancer

Go to Network Services >> Load Balancing and Click Create Load Balancer

In the HTTP(S) Load Balancing click Start Configuration

Create Load Balancer

Backend configuration

Enter a name for your Load Balancer and click Backend configuration

In Backend services & backend buckets select Backend service >> Create backend service

Enter a name for your backend service

In Backend Type choose Instance group

In Backends select the Instance group you created

In Port numbers enter 80

In Balance mode choose Utilization

Click Done

Check Enable Cloud CDN

Load balancing create backend service

Create Health Check

In Health Check click create health check

In Name enter a health check name

In Protocol select TCP

In Port enter 80

In Proxy protocol select None

In Check Interval enter 10

In Timeout enter 5

In Healthy threshold enter 2

In Unhealthy threshold enter 3

Click Save and Continue

Load Balancing Health Check

Frontend Configuration

Enter a name for your IPv4 frontend configuration

In Protocol select HTTPS

In IP version select IPv4

In IP address select the IP4 address you reserved

Load balancing Frontend configuration

In Certificate select Create Certificate

Enter a name for your certificate

In Create mode choose to Create Google-managed certificate

In Domains enter *.yourdomainname.com

Load Balancing Google Managed SSL Certificate

This setting will issue a Google managed Let’sEncrypt Certificate.

Attention: Once you have created a certificate it will be in the PROVISION status. Once the certificate is ACTIVE, you’ll have SSL issues for a few minutes with the error message ERR_SSL_VERSION_OR_CIPHER_MISMATCH. It took 15 minutes for mine to have everything up and running.

Uploading your own Certificate

To upload your own certificate, In Create mode choose to Upload my certificate

Here we use the Let’s Encrypt SSL certificate as an example

If you haven’t setup SSL in your VM instance, please check Installing SSL in Google Cloud Platform

SSH your VM Instance and enter the following commands and copy all contents

sudo nano /etc/letsencrypt/live/yourdomainname.com/fullchain.pem

In Public key certificate copy and paste the contents of fullcahain.pem file

sudo nano /etc/letsencrypt/live/yourdomainname.com/cert.pem

In Certificate chain copy and paste the contents of cert.pem file

sudo nano /etc/letsencrypt/live/yourdomainname.com/privkey.pem

In Private key  copy and paste the contents of privkey.pem file

Click Create

Load Balancing Upload SSL Certificate

Now in Frontend configuration click Done

Click Add Frontend IP and Port

Enter a name for your IPv6 frontend configuration

In Protocol select HTTPS

In IP version select IPv6

In IP address select the IPv6 address you reserved

In Certificate select the certificate you just created

Click Done

That’s all now your Backend and Frontend are configured

Configure DNS and Setup Cloud CDN

Click Create

Now Goto Network services >> Cloud DNS and click your domain name

Edit the A record and replace the IPv4 address with your newly reserved IPv4 address.

Click Add record set

In Resource record type select AAAA record

Enter the IPv6 address that you reserved

Goto Goto Network services >> Cloud CDN and click Add origin

In Origin select the Load balancer you just created.

Click Add

Now go to Network services >> Load Balancing and wait for 10 – 15 minutes for the Load Balancing settings to propagate. Once done you will see a green checkmark which indicates everything is fine.

Next you can set up Cloud Armor to secure your application.

That’s all, now your Load Balancer is configured to scale your website horizontally with Nginx web server

4 Comments

  1. I have a nginx bitnami application. did not succeed with your tutorial, could you do one specifically for bitnami?

    • Cloudbooklet Reply

      Bitnami configuration does not support this Load Balancing setup, because for this setup to work the database and media files must be separated from the VM instance to Cloud Storage and Cloud SQL.

Write A Comment

This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.

Where Writing Meets Entrepreneurship!

Get FREE Google Cloud Tutorials.
GET NOW
close-link
Please help us get 1000 likes in Facebook. Thank You!
LIKE NOW

Stay Connected!

Get latest tutorials on Google Cloud and Open Source topics
SUBSCRIBE
close-link