Part 1 - Deploy Kubernetes with Terraform and KubeOne

Introduction

This is my first blog post on Hashnode. I hope you enjoy it ๐Ÿ™ƒ

"Oh no! Yet another blog post about setting a Kubernetes Cluster" - That's probably what most of you think when you read the headline.

And you are not wrong at all. Except that I will try to share some of my experiences and some (best) practices I learned while working with those two tools.

To make things a bit clearer about what you can expect from this series, I will give you a brief overview:

To begin with this little journey, I assume that:

  • you already have set up a Hetzner account

  • you have installed Terraform on your machine

  • you have installed KubeOne on your machine

  • you have a basic understanding of Linux and Kubernetes

In the first part of this blog series, we are focussing on deploying the basic infrastructure with Terraform.

What is Kubermatic KubeOne?

KubeOne is a small wrapper around kubeadm. kubeadm is the official tool to install Kubernetes on Virtual Machines or Bare Metal nodes. But deploying Kubernetes with kubeadm is very cumbersome.

KubeOne tries to solve this problem by providing a wrapper, which automates the operations of Kubernetes Clusters. It provides full lifecycle management of your clusters, including provisioning, upgrading and (when necessary) repairing them.

Let's get started

We begin with provisioning our needed infrastructure with Terraform on Hetzner. We clone the Kubermatic provided Terraform examples.


git clone https://github.com/kubermatic/kubeone.git

When we change the directory to examples/terraform/hetzner we find a ready to use terraform module, that provisions the basic infrastructure on our cloud provider. This includes:

  • hcloud_network

  • hcloud_network_subnet

  • hcloud_firewall

  • hcloud_server

Add Bastion Host

Currently, there will be only servers created for Kubernetes. To increase the level of security we will add another server resource and create a bastion server/jump host. This allows us to restrict ssh connections only if they are tunnel through this specific host. Of course we also have to make some adjustments on the Hetzner Firewall.

First we change the firewall configuration. Open the main.tf file with a text editor of your choice and find go to line 80. Change the rule allow SSH from any from:

  rule {
    description = "allow SSH from any"
    direction   = "in"
    protocol    = "tcp"
    port        = "22"
    source_ips = [
      "0.0.0.0/0",
    ]
  }

to:

  rule {
    description = "allow SSH via bastion"
    direction   = "in"
    protocol    = "tcp"
    port        = "22"
    source_ips = [
      format("%s/32", hcloud_server.bastion.ipv4_address)
    ]
  }

The changes make sure that only SSH connections coming from the public IP are allowed on the Kubernetes nodes. The next change is to add the code for the bastion server.

resource "hcloud_server" "bastion" {
  name               = "${var.cluster_name}-bastion-host"
  server_type        = "cx11
  image              = local.image
  location           = "nbg1"

  labels = {
    "kubeone_cluster_name" = var.cluster_name
    "role"                 = "bastion"
  }
}

The README.md in the project directory gives us a brief explanation of inputs and outputs and gives us hints about load balancers. Most of the inputs have defaults except the variable cluster_name. Create a file called terraform.tfvars in the same directory and add the following line to it:

cluster_name = "<your-cluster-name-here>"

This makes sure that the input cluster_nameis set and we are ready to go.

Apply Terraform code

Before we can run terraform to create the resources for us, we have to provide the API Token for Hetzner. There are several ways to do this but we will just export the token as an environment variable. If you take a look at the terraform provider documentation you will find the variable HCLOUD_TOKEN.

$ export HCLOUD_TOKEN="<your-hcloud-token>"

For provisioning the infrastructure we do the following:

$ terraform init
$ terraform apply

The command terraform init will initialize Terraform and download the provider. terraform apply will prompt you for confirmation and then will create the infrastructure in only a few seconds. You now should see a JSON formatted output. This output will be used for filling KubeOne with information, on where to provision Kubernetes.

Configuring KubeOne and installing Kubernetes will be in Part 2 of this blog series. So stay tuned!

To get notified on the second part make sure to follow me on my Social Media:

0
Subscribe to my newsletter

Read articles from Dominic Cardellino directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Dominic Cardellino
Dominic Cardellino