Kennisbank › Docker Containers › Kubernetes basics for small teams
docker containers expert 08 September 2026

Kubernetes basics for small teams

You want to run an application that doesn't fall over when a process stops, and that scales along without you having to buy a server at three o'clock at night.

You want to run an application that doesn't fall over when a process stops, and that scales along without you having to buy a server at three in the morning. Kubernetes does that, but it charges an entry fee in complexity that you have to pay before you get anything back from it.

This article explains how to take those first six steps — creating a cluster, deploying an app, exposing it, scaling, updating — and what each step costs you. For teams of two to ten developers running containers without a dedicated platform team.

Prerequisites

You need a machine with at least 4 GB RAM and 2 CPU cores. All commands work on Linux, macOS, or Windows (via WSL2).
  • Docker (for running the cluster node images)
  • `kubectl` version 1.28 or newer
  • Minikube version 1.31 or newer, or Kind version 0.20 or newer
  • Basic knowledge of YAML and the command line
Check your versions:

kubectl version --client
minikube version
docker --version

Step 1: Create a local cluster

A Kubernetes cluster consists of a control plane that manages the state and worker nodes that run the workloads. In production, these are separate machines; locally, everything runs on one machine in a virtual environment.

Minikube is the fastest start:

minikube start --cpus=2 --memory=4096

This downloads a node image and starts a cluster. It takes five to ten minutes the first time; after that, it goes faster.

If you choose Kind, you run Kubernetes in Docker containers instead of a VM:

kind create cluster --name pixzo-test

Kind starts faster than Minikube and uses less memory, but you miss some features such as load balancers that do work in Minikube. Start with Minikube if you want to keep it simple; choose Kind if you have little RAM.

Why this costs what it costs: you learn cluster management on a machine you can throw away. Make mistakes — and you will — then you restart the cluster instead of repairing a production server.

Step 2: Deploy an application

A Deployment is a manifest that describes which container image should run and how many replicas. Kubernetes reads this file and ensures reality matches what is in it.

Create a file `deployment.yaml`:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-demo
spec:
  replicas: 2
  selector:
    matchLabels:
      app: nginx-demo
  template:
    metadata:
      labels:
        app: nginx-demo
    spec:
      containers:
      - name: nginx
        image: nginx:1.27
        ports:
        - containerPort: 80

Deploy it with:

kubectl apply -f deployment.yaml

Kubernetes now starts two Pods on the available worker nodes. A Pod is the smallest unit Kubernetes manages — a wrapper around one or more containers that work together and share the same network and storage resources.

The key point: Kubernetes continuously checks whether the number of running Pods matches `replicas`. If a Pod crashes, Kubernetes starts a new one. You don't need to intervene yourself.

Step 3: Explore the application

`kubectl` is your only interface to the cluster. Almost everything you do goes through this command.

Look at the status of your Pods:

kubectl get pods

The output shows the name of each Pod, the status (`Running`, `Crashing`, `Pending`), and how often it has restarted. If you see `CrashLoopBackOff`, something is wrong with the container itself — check the logs:

kubectl logs deployment/nginx-demo

If you want details about a specific Pod, for example why it is running on a particular node or which events preceded it:

kubectl describe pods

Take the time to learn these three commands. They make up ninety percent of your daily interaction with the cluster.

Step 4: Expose the application

Pods are by default only reachable within the cluster. They get an internal IP address that changes as soon as the Pod restarts. For external access, you define a Service — a stable access point that points to the Pods behind a label.

Create `service.yaml`:

apiVersion: v1
kind: Service
metadata:
  name: nginx-service
spec:
  type: NodePort
  selector:
    app: nginx-demo
  ports:
<ul><li>port: 80</li></ul>
    targetPort: 80
    nodePort: 30080

And activate it:

kubectl apply -f service.yaml

NodePort makes the application reachable via port 30080 on the IP address of your Minikube node:

minikube service nginx-service --url

This opens your browser to the correct address.

There are three Service types. ClusterIP is only reachable internally — useful for communication between microservices. NodePort works for testing but is not suitable for production. LoadBalancer gives you an external IP address via your cloud provider, but does not work in Minikube without extra configuration.

Start with NodePort. It is ugly but functional, and you learn the concept with it without cloud-vendor-specific settings.

Step 5: Scale the application

With `kubectl scale` you adjust the number of replicas:

kubectl scale deployment/nginx-demo --replicas=5

Kubernetes now starts three extra Pods — or stops two if you scale back to three. This works manually, but you can also set up horizontal autoscaling based on CPU usage:

kubectl autoscale deployment/nginx-demo --min=2 --max=10 --cpu-percent=70

This costs an extra component: the metrics-server. It collects CPU and memory data from the nodes. Without the metrics-server, the autoscale command does nothing.

Don't scale automatically too early. Manual scaling teaches you how many resources your application actually needs. Automatic scaling based on traffic you don't understand leads to costs you don't expect — especially if you later move to a cloud provider.

Step 6: Update the application

When you have a new version of your image, you update the manifest and apply it again:

kubectl set image deployment/nginx-demo nginx=nginx:1.28

Kubernetes performs a rolling update: it gradually replaces old Pods with new ones, without interrupting the service. Check the progress:

kubectl rollout status deployment/nginx-demo

If something goes wrong, you roll back the update:

kubectl rollout undo deployment/nginx-demo

These three commands — set, status, undo — form your deployment workflow. It's less advanced than GitOps tools like ArgoCD, but for a small team it's often enough.

Verification

Check that everything is running as it should:

kubectl get pods,deployments,services

The output should show five running Pods (if you scaled to five), a Deployment with the desired status, and a Service with an assigned port.

Finally: fetch the application via the Service:

curl $(minikube service nginx-service --url)

You should see the default nginx page.

Common problems

Pod stays stuck in `Pending` status. The node has insufficient resources. Check with `kubectl describe pod` whether a resource limit is being exceeded, and increase Minikube's memory: `minikube stop`, then `minikube start --memory=6144`.

`CrashLoopBackOff` with nginx. The container starts and crashes repeatedly. Check the logs with `kubectl logs deployment/nginx-demo`. Often it's a wrong image tag or a configuration error in a mounted volume.

`kubectl` cannot connect to the cluster. Your local `kubectl` is talking to a different context than your Minikube cluster. Set the context with:

kubectl config use-context minikube

The official Kubernetes documentation is divided into Concepts, Tasks, Tutorials, and References. The Concepts section explains how things work, Tasks give step-by-step instructions, Tutorials combine both into scenarios, and References contain the dry API details. Start with the Concepts about Pods and Services, not with the References — you only read those when you need to look up something specific.

Kubernetes doesn't reduce complexity, it moves it. You trade manual deployment scripts for a system you need to learn to understand before it pays off. The question isn't whether you can run it — anyone can with a tutorial — but whether you can maintain it as your application grows and the first unexplained error message appears. That's the moment when the investment pays off, or not.

← Back to knowledge base
← Terug naar kennisbank