Prestashop Media Server on Google Cloud Platform with auto-healing capabilities

In my previous post How to setup a media server for Prestashop on Google Cloud Platform I explained how to create a media server for Prestashop using the Cloud Load Balancer, Cloud CDN using unmanaged instance group.

I used this configuration in production and it worked very well until the backend machine freeze and did not responded to requests anymore. After I rebooted the machine everything was working again, but that means that I have to manually reboot the machine every time gets stuck. So, I start looking for a better solution and after a little research I found that the GCP Managed Instance Group has a very nice feature called “Auto-healing”.

Now, in this blog post I will show how to create a media server for Prestashop with auto-healing capabilities.

If you want to understand high level architecture it is recommended to read the previous blog post first How to setup a media server for Prestashop on Google Cloud Platform.

Setup

Prerequisites:

  • GCP project with billing enabled. If you don’t have one then sign-in to Google Cloud Platform Console and create a new project
  • Access to a standard internet browser

First sign-in to your GCP Console and activate the Cloud Shell.

Setup the environment variables:

INSTANCE_NAME=ps-media
ZONE=europe-west3-c
PRESTASHOP_WEBSITE=http://www.example.com
MEDIA_SERVER_NAME=cdn.example.com

A managed instance group lets you create multiple identical VM based on a template. Managed Instance Groups offer the following advantages: (1) High availability, (2) Scalability, (3) Automated updates, (4) Support for stateful workloads. The Autohealing feature is part of the high availability and lets you set up a policy that relies on an application-based health check, which periodically verifies that your app responds as expected on each of the MIG’s instances. If an app is not responding on a VM, that VM is automatically recreated. Find out more here GCP Managed instance groups.

Fist, create the instance template.

# download vm-stratup-script.sh
curl https://gist.githubusercontent.com/gabihodoroaga/43731b8ad9c63f3fe54913acff5e79c2/raw \
    --output vm-stratup-script.sh

# replace our variables inside the script
sed -i 's/PRESTASHOP_WEBSITE/'"$PRESTASHOP_WEBSITE"'/g' vm-stratup-script.sh
sed -i 's/MEDIA_SERVER_NAME/'"$MEDIA_SERVER_NAME"'/g' vm-stratup-script.sh

# create the instance template
gcloud compute instance-templates create-with-container $INSTANCE_NAME-template \
    --container-image gcr.io/cloud-marketplace/google/nginx1:1.15 \
    --machine-type f1-micro \
    --tags $INSTANCE_NAME-http \
    --metadata-from-file startup-script=vm-startup-script.sh \
    --container-mount-host-path host-path=/var/nginx.conf,mount-path=/etc/nginx/nginx.conf,mode=ro

For this setup I will use “Containers on VM” feature on GCP, and nginx 1.15 as the reverse proxy. You can find more info about how to deploy container on virtual machines from the official documentation. Deploying containers on VMs

I order to configure nginx to proxy the request back to the original Prestashop website the instance template must be configured with a startup script (–metadata-from-file startup-script=vm-startup-script.sh) that create , and mount the configuration file inside de container (–container-mount-host-path host-path=/var/nginx.conf,mount-path=/etc/nginx/nginx.conf,mode=ro).

You can find out more about how instance templates work from the official documentation GCP Instance templates

Next, create the managed instance group

gcloud compute instance-groups managed create $INSTANCE_NAME-instance-group \
    --template $INSTANCE_NAME-template \
    --size 1 \
    --zone $ZONE

Create the health check

gcloud compute health-checks create http $INSTANCE_NAME-health-check \
    --request-path / \
    --port 80 \
    --check-interval 60s \
    --healthy-threshold 1 \
    --timeout 5s \
    --unhealthy-threshold 5 \
    --host $MEDIA_SERVER_NAME

Create the firewall rule to allow the health check to be performed

gcloud compute firewall-rules create $INSTANCE_NAME-allow-health-check \
    --allow tcp:80 \
    --source-ranges 130.211.0.0/22,35.191.0.0/16 \
    --target-tags $INSTANCE_NAME-http

In order to add application based auto-healing capabilities to an instance group we need to setup the health check. You can find more about how auto-healing works in detail from the official documentation Setting up health checking and auto-healing.

So. Let’s update the instance group accordingly

gcloud compute instance-groups managed update $INSTANCE_NAME-instance-group \
    --health-check $INSTANCE_NAME-health-check \
    --initial-delay 300 \
    --zone $ZONE

Now let’s create the load balancer and the required components

# create a backend service
gcloud compute backend-services create $INSTANCE_NAME-lb-backend \
  --http-health-checks $INSTANCE_NAME-health-check \
  --port-name http \
  --global \
  --enable-cdn \
  --connection-draining-timeout 300

# add the instance group to the backend
gcloud compute backend-services add-backend $INSTANCE_NAME-lb-backend \
  --instance-group $INSTANCE_NAME-instance-group \
  --instance-group-zone $ZONE \
  --balancing-mode UTILIZATION \
  --max-rate-per-instance 100 \
  --capacity-scaler 1.0 \
  --global

# create the url-map
gcloud compute url-maps create $INSTANCE_NAME-url-map \
  --default-service $INSTANCE_NAME-lb-backend

# create the http proxy
gcloud compute target-http-proxies create $INSTANCE_NAME-http-proxy \
  --url-map $INSTANCE_NAME-url-map

# create a global forwarding rule a.k.a. frontend
gcloud compute forwarding-rules create $INSTANCE_NAME-forwarding-rule \
  --global \
  --ports 80 \
  --target-http-proxy $INSTANCE_NAME-http-proxy

That’s it. Our global load balance is ready to be used and can receive traffic.
To check if the load balancer and proxy works as expected run the following commands

# get the public ip address
IP_ADDRESS=$(gcloud compute forwarding-rules describe $INSTANCE_NAME-forwarding-rule --global --format="value(IPAddress)")
# print the public ip address
echo $IP_ADDRESS
# make a request to the service
curl -s -I http://$IP_ADDRESS/

and the output should be similar to this

HTTP/1.1 200 OK
Server: nginx/1.15.12
.....

Next you need to configure Prestashop to use the new media server.

Login to your Prestashop Admin page and navigate to

ADVANCED PARAMETERS -> PERFORMANCE -> MEDIA SERVERS

add there the ip address or subdomain name of the load balancer.

PS Media Servers

You have now all your static content served from the media server. Open up your browser developer tools and check the urls of your images, javascript and css files.

To troubleshot any issues related to the caching you can try

To test if the auto-healing is working you need to ssh into the machine and stop the nginx container. Wait 5 minutes and then see if the VM si recreated.

Clean up

Run the following script to remove all the resource used in this tutorial.

# download the file
curl https://gist.githubusercontent.com/gabihodoroaga/b4d9270e83a146e9be01c4e01c7e7a71/raw \
    --output cleanup.sh
# adjust the values for INSTANCE_NAME and ZONE variables
# make the script executable
chmod +x cleanup.sh
# run the script
./cleanup.sh

Conclusion

Using a managed instance group with application based auto-healing improves the availability of the online shop.