Setting Up a Local Single-Node Kubernetes Cluster with Docker

This guide details the process of deploying a minimal, single-node Kubernetes cluster directly on your local machine using Docker containers. This setup is ideal for development, testing, and learning Kubernetes concepts without needing a full-fledged cloud environment or dedicated virtual machines.

Prerequisites

Before proceeding, ensure your system meets the following requirements:

  • Docker Engine: You must have Docker installed and running on your machine.
  • Kernel Configuration for Cgroups: The Linux kernel must support memory and swap accounting for proper container resource management. Verify these configurations by checking your kernel's build options. For example, confirm your kernel includes: ``` CONFIG_RESOURCE_COUNTERS=y CONFIG_MEMCG=y CONFIG_MEMCG_SWAP=y CONFIG_MEMCG_SWAP_ENABLED=y CONFIG_MEMCG_KMEM=y
    
    Additionally, you need to enable memory and swap accounting at boot time by modifying your GRUB configuration. For GRUB2 systems, edit `/etc/default/grub` and add the following to the `GRUB_CMDLINE_LINUX` variable:
    
    
    GRUB_CMDLINE_LINUX="cgroup_enable=memory swapaccount=1"
    
    After updating GRUB, regenerate your GRUB configuration (e.g., `sudo update-grub` on Debian/Ubuntu or `sudo grub2-mkconfig -o /boot/grub2/grub.cfg` on Fedora/CentOS) and reboot your system. You can verify the parameters were successfully passed to the kernel by inspecting `/proc/cmdline`:
    
    
    cat /proc/cmdline
    
    The output should include `cgroup_enable=memory swapaccount=1`.
    
    

Deploying Kubernetes Core Components

We will start by launching the essential Kubernetes components as individual Docker containers.

1. Launching Etcd

Etcd serves as Kubernetes' distributed key-value store, holding all cluster data. Execute the following command to run an Etcd instance:

docker run \
    --name etcd-server \
    --publish 4001:4001 \
    --network host \
    --detach \
    gcr.io/google_containers/etcd:2.0.12 \
    /usr/local/bin/etcd \
    --addr=127.0.0.1:4001 \
    --bind-addr=0.0.0.0:4001 \
    --data-dir=/var/etcd/data

This command starts Etcd, binds it to port 4001, and runs it in the background.

2. Initializing the Kubernetes Control Plane (Master)

The Kubernetes control plane components, including the API Server, Controller Manager, and Scheduler, will be managed by a Kubelet instance. The Kubelet itself will run as a Docker container and be responsible for creating and managing static pods for the control plane.

docker run \
    --name kube-master-node \
    --volume /:/rootfs:ro \
    --volume /sys:/sys:ro \
    --volume /dev:/dev \
    --volume /var/lib/docker/:/var/lib/docker:ro \
    --volume /var/lib/kubelet/:/var/lib/kubelet:rw \
    --volume /var/run:/var/run:rw \
    --net=host \
    --pid=host \
    --privileged=true \
    --detach \
    gcr.io/google_containers/hyperkube:v1.0.1 \
    /hyperkube kubelet \
    --containerized \
    --hostname-override="127.0.0.1" \
    --address="0.0.0.0" \
    --api-servers=http://localhost:8080 \
    --config=/etc/kubernetes/manifests \
    --v=2

This command launches the Kubelet. Notice the extensive volume mounts, which provide the Kubelet access to the host's filesystem and Docker daemon necessary for its operations. The --config flag points to the directory where Kubelet expects to find static pod manifests for the control plane components.

3. Running Kube-Proxy

Kube-Proxy maintains network rules on nodes, enabling network communication to your Pods from outside or inside the cluster. It ensures services are accessible.

docker run \
    --name kube-proxy-service \
    --detach \
    --net=host \
    --privileged=true \
    gcr.io/google_containers/hyperkube:v1.0.1 \
    /hyperkube proxy \
    --master=http://127.0.0.1:8080 \
    --v=2

This starts the Kube-Proxy container, connecting it to the master's API server.

Verifying Cluster Status

At this point, your Kubernetes cluster should be operational. You can interact with it using the kubectl command-line tool. If you don't have kubectl installed, please refer to the official Kubernetes documentation for installation instructions for your operating system.

For macOS users running Docker via a VM (like older Boot2Docker setups), you might need to forward the Kubernetes API server port:

boot2docker ssh -L 8080:localhost:8080

To confirm the cluster's health, list the nodes:

kubectl get nodes

You should see output similar to this, indicating your local node is ready:

NAME        STATUS    ROLES     AGE       VERSION
127.0.0.1   Ready     <none>    ...       ...

If you're managing multiple Kubernetes contexts or clusters, you might need to explicitly specify the local master's API server URL for kubectl commands:

kubectl --server=http://localhost:8080 get nodes

Deploying a Sample Application

Let's deploy a simple Nginx web server to test our cluster's functionality. We'll create a Deployment named nginx-app that runs a single Nginx pod.

kubectl --server=http://localhost:8080 create deployment nginx-app --image=nginx --port=80

It might take a few moments for the Nginx image to be pulled and the pod to start. You can verify the Nginx container is running on your host's Docker daemon:

docker ps | grep nginx

You should see a Docker container for Nginx managed by Kubernetes.

Exposing the Application as a Service

To make our Nginx application accessible, we'll expose it via a Kubernetes Service.

kubectl --server=http://localhost:8080 expose deployment nginx-app --port=80 --type=ClusterIP

Now, retrieve the details of the created service, including its ClusterIP:

kubectl --server=http://localhost:8080 get service nginx-app

This command will display information about the service, including its internal ClusterIP. To specifically extract just the ClusterIP, you can use a JSON path template:

kubectl --server=http://localhost:8080 get service nginx-app --output=jsonpath='{.spec.clusterIP}'

Once you have the <CLUSTER_IP>, you can test connectivity from within your host machine:

curl <CLUSTER_IP>

If you are on macOS and using a VM (like Boot2Docker), remember to run the curl command from within the VM's shell.

Stopping the Cluster

The Kubernetes components launched via Kubelet are designed to be self-healing. This means Kubelet will attempt to restart any failed control plane containers. To properly shut down your local Kubernetes cluster, you must first stop the Kubelet container, which is managing the other master components. After that, you can stop Etcd and Kube-Proxy.

You can identify and stop specific containers by name:

docker kill kube-master-node
docker kill etcd-server
docker kill kube-proxy-service

Alternatively, to stop all running Docker containers (use with caution, as this affects all containers, not just Kubernetes-related ones):

docker kill $(docker ps -q)

Tags: kubernetes docker etcd kubelet kubectl

Posted on Thu, 08 Oct 2026 16:37:46 +0000 by markster