Skip to content

Setting up a Kubernetes Cluster with K3S on my linux server

Published:

I am currently in the initial stages of creating a “sideproject hub”, where I aim to rapidly deploy small coding projects within Docker containers on my own server. To ensure total overengineering from the very beginning, I am in the process of establishing a Kubernetes cluster on my server. This cluster will serve as the foundation for efficiently running my future side projects.
Discover the steps I took to set up a Kubernetes cluster on my Linux server using K3S, and witness the moment when I accessed my domain through a web browser for the first time, greeted by a simple NGINX “hello world” page.

Disclaimer: I’m writing these lines as I try all this stuff out for myself. This is how it worked for me, and I’m happy if I can help someone else with my notes. If anyone knows how to do it in a better way or if any information is incorrect, please let me know!

Prerequisites

Install & Run Kubernetes Cluster with K3S

The curl Command initiates a download of the K3S installation script from the specified URL. If I got it right, adding your domain as the value for --tls-san ensures that the TLS certificate includes your specific server domain as a valid identity. The entire install command is passed to the shell for execution. This triggers the installation process of K3S with the specified parameters. Loading scripts via curl and executing them directly should always be carefully considered! Only execute trustworthy scripts or those that can be checked.

After installing K3s, the Kubernetes configuration file is generated at /etc/rancher/k3s/k3s.yaml. This file contains essential information about the K3s cluster, such as the API server address and access credentials. As ~/.kube/config is the default location for the for the Kubernetes configuration file, and tools like kubectl try to look it up there, the cp command is executed.

External Access to the Cluster from Local Machine

In case you already have a config file with other clusters configured, be a smart and don’t overwrite this file

Run a Hello World Nginx Image as Test Deployment in the Cluster

kubectl create namespace test
apiVersion: apps/v1
kind: Deployment
metadata:
  name: hellohub
  namespace: test
spec:
  replicas: 1
  selector:
    matchLabels:
      app: hellohub
  template:
    metadata:
      labels:
        app: hellohub
    spec:
      containers:
        - name: hellohub
          image: dockerbogo/docker-nginx-hello-world
          ports:
            - containerPort: 80
apiVersion: v1
kind: Service
metadata:
  name: hellohub-service
  namespace: test
spec:
  selector:
    app: hellohub
  ports:
    - protocol: TCP
      port: 80
      targetPort: 80
  type: ClusterIP

The hellohub-deployment.yaml file defines a Kubernetes Deployment named “hellohub” within the “test” namespace. It specifies the use of the dockerbogo/docker-nginx-hello-world Docker image, configuring a single replica of the container, means only one instance is running. The deployment exposes port 80. It allows Kubernetes to manage the pod lifecycle, for example, if the pod crashes, it is restarted immediately.

The hellohub-service.yaml file creates a Kubernetes Service named “hellohub-service” within the “test” namespace. This service acts as an internal ClusterIP service, routing traffic to pods labeled with “app: hellohub” on port 80. The service ensures a stable endpoint for accessing the Nginx Hello World deployment. By defining this service, it allows other components within the Kubernetes cluster to communicate with the “hellohub” deployment seamlessly. With only one pod running, the concept is probably less important. But I was happy to set it up with it just because I already have a fixed name for port forwarding with which I can address the service and don’t have to look up the pod first. I still have to find out what else the services are responsible for.

Make Test Deployment Accessible via Subdomain

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: hellohub-ingress
  namespace: test
spec:
  rules:
    - host: hellohub.<yourserver.de>
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: hellohub-service
                port:
                  number: 80

In Kubernetes, an Ingress provides HTTP and HTTPS routing to services based on external hostnames and paths. It acts as a layer between the external requests and the services within the cluster. The Ingress Resource, like the one in the provided YAML, is a configuration file that defines these routing rules. In the given example, the Ingress Resource named “hellohub-ingress” within the “test” namespace is configured to route requests with the hostname “hellohub.<yourserver.de>” to the “hellohub-service” on port 80. The paths section further refines the routing, indicating that requests to the root path should be directed to the specified service. This Ingress Resource enables the Nginx Hello World application to be reachable at http://hellohub.<your-domain>/.

In case it does not work, remember that it is not necessarily the cluster itself or the Ingress configuration to blame. It may also be due to your DNS settings for the domain, for example.

Uninstalling K3S

Just in case you were also looking for this information. Fortunately, it’s quite simple.

Links to the resources I used and to information that helped me in the process.