In the new era of enormous internet services development, we are hearing the “microservice” term too many times. Unlike monolith applications, we are creating lots of individual maintainable and testable mini-applications that empower us to create a scalable service. This new era brought with it new needs – infrastructure as a code and container orchestration are two big ones. I don’t want to explain these words but we are going to get down to business and create a simple example to get some real ideas about them.
I always wanted to find an easy, independent, and low-cost solution to have my own container orchestration that empowers me to test lots of cloud technologies like Prometheus, Fluentd, Traefik. Also, I was thinking I should do this with a standard approach in order to make that knowledge useful for my career path which in this case is infrastructure as code.
In this tutorial, we are going to build our own one-node low-cost Kubernetes cluster from scratch. If you don’t have any knowledge about any of the components – don’t worry, I am trying to create a step-by-step brief guide that provides you with some basic ideas. We will not dive into details but we will create the big picture as fast as possible, and after having something meaningful we can continue to play and learn more. After all, it is just a lab to experience some popular technologies and is not supposed to be used in a real production situation.
To create a new server we are going to use Terraform, Terraform is an open-source infrastructure as a code software tool created by HashiCorp. Users define and provision data center infrastructure using a declarative configuration language. To use the terraform command I prefer to install tfswitch which empowers me to switch between different versions of terraform. If you want to install terraform directly, please install version 0.13.
Terraform uses Providers to communicate with services like AWS, Cloudflare, and we are going to use Hetzner Cloud Provider because they are providing a decent and simple service with a really low price that suits our goal. Let’s start our journey: in an empty folder, we should create four files:
versions.tf
terraform { required_providers { hcloud = { source = “hetznercloud/hcloud” } } required_version = “>= 0.13” } |
variables.tf
variable “hcloud_token” {}
variable “private_ssh_key_path” { default = “~/.ssh/id_rsa” } |
main.tf
# Configure the Hetzner Cloud Provider provider “hcloud” { token = var.hcloud_token }
# Add main ssh key resource “hcloud_ssh_key” “default” { name = “main ssh key” public_key = file(“${var.private_ssh_key_path}.pub”) }
# Create a server resource “hcloud_server” “node1” { name = “node1” image = “ubuntu-16.04” ssh_keys = [hcloud_ssh_key.default.name] server_type = “cx11” } |
outputs.tf
output “public_ip4” { value = “${hcloud_server.node1.ipv4_address}” }
output “status” { value = “${hcloud_server.node1.status}” } |
You may wonder what are these files, don’t worry, the main.tf will add a ssh key and also a server in the hetzner Cloud. You might wonder, how do I find out about them? by checking the provider documentation: https://registry.terraform.io/providers/hetznercloud/hcloud/latest/docs/resources/server
Now it is time for initializing the terraform provider and checking the correct format of the files, we can do that by the below commands inside of our folder:
CLI
tfswitch
terraform init
terraform fmt |
If you didn’t see any problem it means you are ready to move to the next step, but if you’d like to learn more about terraform, please read this: https://kubernetes.io/docs/tutorials/
Now we are ready to provision our server via code, in order to make that happen we should get help from a cloud service provider – in our case, Hetzner cloud. The benefit of Hetzner is that it avoids lots of complexity that may confuse us at the beginning. Alongside providing a fair quality, the monthly price of their servers could be as cheap as a Doener kebab!
Please go to https://www.hetzner.com/cloud to sign up and verify your account, and then create a new project. Go to your new project -> Security tab -> API Tokens and generate a new one with Read & Write permission level:
Copy the generated token and put it into a new file in your folder like this:
terraform.tfvars
hcloud_token = “yourHetznerToken” |
It is better to generate a dedicated ssh key for our lab without any passphrase, we can generate that by:
CLI
ssh-keygen -f ~/.ssh/myPersonalCloudLab |
Let’s define it to our terraform.tfvars file like this:
terraform.tfvars
hcloud_token = “yourHetznerToken” private_ssh_key_path=”~/.ssh/myPersonalCloudLab” |
Now you are ready to create your very first server, please run:
CLI
terraform plan |
Here you can see an execution plan that will add two items, an ssh key, and a server. Remember you can always see more detail about arguments by a command like this:
CLI
terraform plan –help |
and now it’s time to make your dreams real, and create them on the Hetzner:
CLI
terraform apply |
Wonderful, we’ve created our first server with the help of terraform. It’s time to move to the third and last section of this article, but in case you are wondering what else you can put in your server configuration values – you can check out the examples below and play with them:
CLI
brew install jq export API_TOKEN=yourHetznerToken # https://docs.hetzner.cloud/#images
curl \ -H “Authorization: Bearer $API_TOKEN” \ ‘https://api.hetzner.cloud/v1/images’ | jq “.images[].name” # https://docs.hetzner.cloud/#server-types-get-all-server-types
curl \ -H “Authorization: Bearer $API_TOKEN” \ ‘https://api.hetzner.cloud/v1/server_types’ | jq “.server_types[] | .name, .prices” | less |
Nowadays the most popular container orchestration tool is Kubernetes, which was developed originally at Google. To learn it, the usual suggestion is to use a local program name minikube. However, it is not designed for running on servers. instead, we are going to use k3s project. K3s is a widely available, certified Kubernetes distribution, designed for production workloads in unattended, resource-constrained, remote locations or inside IoT appliances.
Remember that we are using Terraform to manage our infrastructure, which is good for provisioning. However, regarding configuration management, the usual suggestion would be to use something like Ansible alongside Terraform. Luckily the installation process of k3s is very simple and we can manage it easily via Terraform itself. For this purpose, please change node1 in the main.tf like this::
main.tf
# Configure the Hetzner Cloud Provider provider “hcloud” { token = var.hcloud_token }
# Add main ssh key resource “hcloud_ssh_key” “default” { name = “main ssh key” public_key = file(“${var.private_ssh_key_path}.pub”) }
# Create a server resource “hcloud_server” “node1” { name = “node1” image = “ubuntu-16.04” ssh_keys = [hcloud_ssh_key.default.name] server_type = “cx11”
connection { type = “ssh” user = “root” private_key = file(var.private_ssh_key_path) host = self.ipv4_address agent = “true” }
provisioner “remote-exec” { inline = [ “curl -sfL https://get.k3s.io | sh -“, ] }
} |
As you can see we’ve added two new sections – connection and remote-exec. The idea is to automatically connect to our server and install k3s on that, provisioner and connection blocks are considered only during the “create” action, therefore we have to destroy our server and rebuild it:
CLI
terraform destroy terraform apply |
Nice, it seems like we are almost done! We have k3s on our server. To work with our Kubernetes cluster, we should use the kubectl command. You can follow this official documentation to install that command on your os. After installing it, we should download our k3s config file and change the server ip address:
CLI
scp -i ~/.ssh/myPersonalCloudLab root@yourServerIP:/etc/rancher/k3s/k3s.yaml . sed -i.backUp ‘s,127.0.0.1,yourServerIP,g’ k3s.yaml export KUBECONFIG=$PWD/k3s.yaml |
Now you should be able to see one node via kubectl command:
CLI
kubectl get node |
Congratulations, we have our Kubernetes and we can be proud that we created it via terraform. We learned a lot and it is time to learn more by playing with Kubernetes commands. If you’d like to deploy a weblog system on your Kubernetes, you can look at my GitHub repository where I’ve already created the whole chain of having WordPress on k3s: https://github.com/pesarkhobeee/wp-k3s
I hope this article is a useful first step to getting familiar with Infrastructure as code and container orchestration concepts. ^_^