11 KiB
+++ title = "Intro to kubernetes" weight = 0 date = "2025-07-22" +++
Problem in learning kubernetes
Lots of people are considering learning Kubernetes but are struggling to take the first steps because the official docs are complete dogshit for beginners. Don't get me wrong, the docs are great, but they serve a different purpose and are mostly used by experienced developers as a reference for things they are about to build or for explanations of some concepts that Kubernetes leverages.
Also official docs are mostly focus on how to deploy a big-ass production-ready system. Which is not something that you will target as a beginner. So instead I'm gonna show you how to deploy a single app.
Another problem is that people who don't use Kubernetes or are not familiar with all the problems it solves say that for medium and small projects, it is overkill. Which is actually complete bullshit as well. Because of the fact that Kubernetes automates a lot of things, it makes it easier to use than to not use it. And it is not that hard to start.
What is Kubernetes? And how is better than Docker?
People that are aquite good with docker might ask, like why should I care? Because I can run docker in cluster mode with docker-swarm!
Weeeeell, here's my response to you. The main problem with docker swarm is that it
might run applications on multiple nodes, but nothing more than that.
What about ingress management, automated certificate issuing, DNS updates, distributed volume provisioning? Docker swarm doesn't have it,
and won't have unless they change their approach for declaring workloads. Kubernetes on the other hand is easily extendable, is adopted by big-tech companies and
supported by a lot of cloud providers, which makes it a de-facto standard for container orchestration. Sad to admit,
but docker swarm is silently dying from the day it was born.
What's inside of Kubernetes?
Since I wanted to give high-level overview of Kubernetes, I won't go into details about each component, and networking, but I will give you a brief overview of the main components that make up Kubernetes.
- Container
- Pod
- Deployment
- Service
- Ingress
- Namespace
- Secret
- ConfigMap
Now let's take a look at each of these components in more detail.
Container
Containers are not really something unique to Kubernetes. You might be familiar with containers from other systems like Docker. In context of kubernetes, containers are exactly same containers as they are in docker or containerd. Nothing brand new in here.
Pod
Pods are the smallest deployable units in Kubernetes.
It's a logically connected group of containers.
You can think of them as a virtual machines running some applications. And there are several reasons for that. First of all, pods share same network and you can go from one container to another using localhost. Also, you can attach volumes to pod and then share it to multiple containers. Which seems a lot like a virtual machine, right?
Deployment
Pods are cool, but there are some limitations to them. First of all, the pod objects are immutable, which means that you can't change them after they are created.
It might be a problem if you want to update your application, because you will have to delete the pod and create a new one. Also, scaling pods by yourself sounds weird. Of couese you can manually create ReplicaSet, but on average it's not something you would want to do.
So that's why we have Deployments. It allows you to describe a template for a pod and then Kubernetes will take care of creating, updating, and scaling pods for you. It will implicitly create a ReplicaSet for you, and will be maintaining it for you as well.
Deployment is a higher-level abstraction that allows you to manage pods more easily, scale them up and down, and update them without downtime.
There are some policies that you can set for deployments, like how many pods to keep running at the same time, update strategies, and so on.
Generally speaking, use deployments to manage your pods, and don't create pods directly unless you have a good reason to do so.
Service
Service is a resource that allows you to set a single IP address and DNS name for a set of pods.
By default you can reach to service by it's name from the same namespace. But if you're in a different namespace, you can reach it by using domain name such as this:
<service-name>.<namespace-name>.svc.cluster.local
.
You can think of services as a load balancer that distributes traffic to a set of pods.
Ingress
Ingress is a resource that allows you to expose your services to the outside world with a single IP address and DNS name.
You can think of it as a reverse proxy that routes traffic to different services based on the request path or host. In order to use ingress, you need to have an ingress controller running in your cluster. K3S by default has Traefik ingress controller installed, which is a great choice for beginners. But for more control and features, I personally prefer to use NGINX Ingress Controller.
Ingress works this way: you create an ingress resource that defines the rules for routing traffic to different services, based on the request path or host.
Then the ingress controller will take care of routing the traffic to the appropriate service.
Namespace
I mentioned namespaces in the beginning, but I didn't explain what they are. Actually it's a very simple concept. It's a way to group resources in Kubernetes and manage access. Most of the time you can think of namespaces as just a way to organise resources in your cluster.
I prefer using different namespaces for different apps. For example my mailserver is deployed in namespace mailserver
. But my blog is deployed in namespace s3rius
for personal projects.
Telegram bots, CI/CD pipelines, and other applications that I deploy in my cluster are also deployed in their own namespaces. Which makes it easier to manage resources and access control.
About access control, you can use Role-Based Access Control (RBAC) to manage access to resources in a namespace. It will only be useful if you have multiple users or teams working in the same cluster.
You can create roles and role bindings to grant permissions to users or groups in a namespace. But I won't cover RBAC in this blog post. Just because it's too complex and we're only discussing basics.
ConfigMap and Secret
These two resources are used to store configuration data and sensitive information, respectively. For example, you can use ConfigMap to store environment variables, configuration files, or any other non-sensitive data that your application needs to run. And then mount them as files to your pod, or populate environment variables from it, etc.
In secrets you can store sensitive information like passwords, API keys, or any other data that you don't want to expose in plain text. But please keep in mind that by default k8s encodes all secrets using base64, which is completely insecure. To make secrets actually secret, you better use Vault or External secrets operator or something similar. But for now let's just use default base64 encoded secrets.
How to deploy kubernetes
For local development you have several options:
- K3D - k3s in Docker.
- Minikube - k8s in docker.
- Kind - Kubernetes in Docker, but with a focus on testing Kubernetes itself.
For production:
- Kubeadm - raw and barebones way to deploy Kubernetes.
- Kubespray - Ansible-based tool to deploy Kubernetes.
- K3S - Lightweight Kubernetes distribution that is easy to deploy and maintain.
- Rancher - A complete Kubernetes management platform
- DeckHouse - A complete Kubernetes management platform that is easy to deploy and maintain.
My personal recommendation is to use K3D for local development and K3S for production. For deploying K3S you can use k3sup, which is a simple script that allows you to deploy K3S on any Linux server with a single command.
Learning environment
Let's use Docker-packed Kubernetes to start off. We're going to use k3d to spin up a cluster. It's an amazing tool that allows you to create a Kubernetes cluster and everything you need with a single command. Additionally, it spins up k3s instead of Google's Kubernetes, which is a lightweight version of Kubernetes that is perfect for beginners.
It has all the features you need to get started and is much easier to set up than other distributions. I'm using this k3d configuration to create a cluster:
# yaml-language-server $schema=https://raw.githubusercontent.com/k3d-io/k3d/main/pkg/config/v1alpha5/schema.json
apiVersion: k3d.io/v1alpha5
kind: Simple
metadata:
name: default
servers: 1
volumes:
- volume: /tmp/k3d-udev:/run/udev # For openebs
ports:
- port: 80:80 # HTTP ports mapping for cluster
nodeFilters:
- loadbalancer
- port: 443:443 # HTTPS ports mapping for cluster.
nodeFilters:
- loadbalancer
registries:
create:
name: registry.localhost # Registry for containers
host: "0.0.0.0" # Host for registry
hostPort: "5000" # Local port for registry
With this configuration, you can create a cluster with a single command:
k3d cluster create --config "k3d.yaml"
Connecting to the cluster
After you install kubectl you should be able to locate file ~/.kube/config
. This file contains all required infomration to connect to clusters. Tools like minikube, k3d or kind will automatically update this file when you create a cluster.
Let's take a look at the contents of this file:
apiVersion: v1
kind: Config
preferences: {}
# Here's list of clusters that you can connect to.
# In this case we have only one cluster, which is k3d-default.
clusters:
- cluster:
certificate-authority-data: DATA+OMITTED
server: https://0.0.0.0:44755
name: k3d-default
# Users is a list of users that you can use to connect to clusters.
# Most of the time you will have each user for each cluster.
# But in some cases you might have multiple users for the same cluster.
users:
- name: admin@k3d-default
user:
client-certificate-data: DATA+OMITTED
client-key-data: DATA+OMITTED
# Context is a combination of cluster and user that you can use to connect to a cluster.
# You can create any combination of cluster and user,
# but most of the time you will have only one context for each cluster.
contexts:
- context:
cluster: k3d-default
user: admin@k3d-default
name: k3d-default
# Currently selected context. It will be used as a default one
# for all kubectl commands.
current-context: k3d-default