Hugo on Kubernetes - How to Deploy A Blogging website - Hands-on Lab

Hugo On Kubernetes

To learn how to deploy a blogging website using Hugo on Kubernetes

11 March 2022
Container
hugo
kubernetes

Hugo is one of the most popular  open-source Static Site Generator (SSG) frameworks written in Go.  It allows developers to build fast HTML websites by combining content and templates. Visit the official documentation of Hugo to know more about it.


In this Hands-on lab, we will see how to deploy a simple HTML website using Hugo on Kubernetes. However, to understand the whole process clearly, we will first set up Hugo's website on a simple VM and then try to set up in a Docker container. Lastly we deploy the Hugo site on Kubernetes. After setting up, we will also try to make some changes to the website and ensure that the website is updated.

About Lab Setup

Our lab has been set up with necessary tools like base OS (Ubuntu), developer tools like Git, Vim, wget and others. 

You can bring this setup on by clicking on the Lab Setup on the right side of the screen. Note that there are two app specific URLs exposed specifically for the hands-on lab purpose.

NOTE: This hands-on lab is focused on the deployment of Hugo’s website on Kubernetes rather than the framework itself.

Hugo on VM

In this step, we will see how to deploy Hugo Extended version on a simple VM. The following steps should also work in the desktop environment as well.

Install and extract the tarball

curl -L https://github.com/gohugoio/hugo/releases/download/v0.115.4/hugo_extended_0.115.4_Linux-64bit.tar.gz -o hugo_extended_0.115.4_Linux-64bit.tar.gz && tar -xzf hugo_extended_0.115.4_Linux-64bit.tar.gz

Make the binary executable and move inside /usr/local/bin/

chmod +x hugo && mv hugo /usr/local/bin/hugo

Our installation is done. Confirm by checking the version by running command `hugo version`. 

hugo version

Now we will proceed with setting up a simple website.

Create a new Hugo site

Run the following command to bring a Hugo site with the name “hugosite”. Note that you can give any desired name to your site.

hugo new site hugosite

Initializing the Git repository

cd hugosite && git init 

For the demo purpose, we will be using one of Hugo’s beautiful themes, Anake. There are many ways to set up Hugo’s theme. However, we will use a simple approach of adding a theme as “Git Submodule”. Perform the following steps to add “Anake” theme as Git submodule to our website repository and set the theme to configuration file.

git submodule add https://github.com/theNewDynamic/gohugo-theme-ananke.git themes/ananke && echo theme = \"ananke\" >> hugo.toml

Create your first blog post

It is quite easy to create a blog in Hugo. The `hugo new` command will create a blog post with a default template which we can modify as per our need. Run the following command to get started with your first blog post.

 hugo new posts/my-first-post.md

Now, edit the post via `vim` editor or with an IDE provided in this lab which can be opened after clicking on the button “Open IDE” on the right hand side of the page. 

Now, start the Hugo Server. Make sure that you are inside the hugosite directory where hugo.toml file is present.

hugo server -D -p 30000 --bind 0.0.0.0

By default Hugo application binds with the localhost (127.0.0.1),  but to access this application from the internet we have to bind the Hugo application to all network interfaces i.e. 0.0.0.0.

Once the server is running, you can access your website through the `app-port-30000` URL on the right side of the page under the `lab-urls` section.

NOTE: Anake is one simple Hugo theme. Hugo has many different themes for the website which you can find in the documentation of Hugo.

Hugo on Docker container

In the previous section, we have seen how to deploy a Hugo based website on a VM, now in this section, we will try to deploy the same website inside a Docker container.

For that, we will need to create a  Dockerfile as below:

Following are few key points from the Dockerfile:

  • Using ubuntu:latest as a base image.
  •  Running a docker container as a 'root' user.
  • Updating the package lists and installing required packages. 
  • Installing Hugo from tarball.
  • In the last command , we specify an instruction that is to be executed when a Docker container starts. The command will start the Hugo Server in the container at port 30000, and use the content and templates from the /root/hugosite directory to render a website.

Now, build the Docker image from the Dockerfile and start the container by performing following steps:

docker build -t <DOCKERHUB_USERNAME>/ubuntu:hugo /root/.

The above command will create a docker image from the Dockerfile with a tag. Replace the <DOCKERHUB_USERNAME> with your docker hub username and push the image to the docker registry. 

docker run -dit -v /root/hugosite:/root/hugosite -p 30000:30000 --name hugo <DOCKERHUB_USERNAME>/ubuntu:hugo 

The other command will create a container with a name hugo from the Docker image we have created. It will also mount the host directory(/root/hugosite) to the container directory and map port 30000 of the Hugo server to 30000 of our base VM. We can now use this port of the Base VM along with an IP address to connect to the Hugo Server.  

Now you can access the Hugo application through app-port-30000 URL.

After accessing the website remove the container.

docker stop hugo && docker rm hugo

Setting Up Hugo on K8s

So far, we have seen how to deploy the Hugo website on Base VM and Docker containers. In this section we will deploy the website on Kubernetes.

One of the important questions that arises in the Kubernetes environment is “How can we serve the content and templates to the Hugo server that is running inside the pod?”

The solution to this problem is “Persistent Volume (PV)”.

Pod will use PersistentVolumeClaim to request physical storage. We will specify the hostpath as /root/hugosite ( a directory in the host machine) while creating PV . After installing the Hugo in the base VM, we will keep the contents and templates required for the website inside the /root/hugosite directory . By using PVC, pods can access the host directory. This way, the Hugo server which is running inside the container can access the content as well as templates and will render the web pages.

Create hostPath PersistentVolume

hostPath PersistentVolume uses a file or directory on the Node to emulate network-attached storage.

In the above yaml file, we have specified the hostPath as “/root/hugosite” which is the directory with contents and templates on the Base VM that is required by the Hugo Server to render a full HTML website.

Now, apply the above yaml file to create a PV and also verify in the list of persistent volumes.

kubectl apply -f pv.yaml && kubectl get pv

Create a PersistentVolumeClaim

The yaml file for PersistentVolumeClaim looks like below:

Two key points about above yaml file are:

  • It requests a volume of at 1 gibibytes that can provide read-write access for at least one Node.
  • This PVC is using the PV “task-pv” that we have created in the previous step.

Now, apply the above yaml file to create a PVC and also verify in the list of persistent volume claims.

kubectl apply -f pvc.yaml && kubectl get pvc

Creating a Deployment

The following is a yaml file for the deployment of our website. 

Apply the above yaml file to create a deployment and verify it in the list of deployments.

kubectl apply -f deploy.yaml && kubectl get deployment

Now, wait for some time for the deployment to finish. 

Create Service

Once the deployment of the app is ready, create a service yaml file. In this file, we are asking the cluster load balancer that we want your service to expose to the public world so everyone can see the application running. For this use case we take the help of a NodePort. It exposes the service on each Node's IP. 

Apply the above service yaml file to create a service and verify it in the list of services.

kubectl apply -f svc.yaml && kubectl get svc

Now, access the Hugo application through app-port-30000 URL. You will see the exact same web page as in previous cases while deploying in a base VM or Docker container. 

Updating the Hugo Website

In this section, we will see how to update our website content. Create another markdown file with the name “my-second-post.md”.

cd /root/hugosite/content/posts/

Now add the new content to “my-second-post.md” file.

vim my-second-post.md

Copy and paste the below content:

After copying the code use Shift + Insert to paste the code in the terminal. Lastly, use Ctrl + D to save the markdown file.

Verify the contents of markdown file as:

cat my-second-post.md

Now, if you open app-port-30000 URL, you will see the newer version of Hugo website with two blog posts.

Conclusion

In this hands-on-lab we have seen how to deploy websites using Hugo on Base VM, on Docker and on Kubernetes. We made changes in websites using markdown files and see the newer version of the website is being displayed.

How likely are you going to recommend this lab to your friends or colleagues?

Unlikely
Likely

Leave a comment:

About the Authors

Ayush Bhat

Ayush Bhat

Intern at CloudYuga

Ayush Bhat is passionate about cloud-native technologies. He is Certified Kubernetes Administrator, Linux Foundation Certified System Administrator, Ex294 Red Hat Certified and AWS Community Builder. He is currently doing internship at CloudYuga

Oshi Gupta

Oshi Gupta

DevOps Engineer & Technical Writer, CloudYuga

Oshi Gupta works as a DevOps Engineer and Technical Writer at CloudYuga Technologies. She is a CKA certified and has been selected for LFX mentorship in Spring 2022 for CNCF Kyverno. She loves writing blogs and is keen to learn about various cloud-native technologies. Besides this, she loves cooking, badminton, traveling, and yoga.