# Building a Kubernetes Cluster on a laptop  using kubeadm, VirtualBox, and Vagrant

Running Kubernetes locally is one of the best ways to understand how clusters work internally. In this article, I’ll walk through how I built a **multi-node Kubernetes cluster on my Mac using Vagrant and VirtualBox**, bootstrapped it with **kubeadm**, installed networking with **Calico**, and finally deployed an **Nginx application** to verify everything works.

This setup is perfect for **DevOps engineers, SREs, and Kubernetes learners** who want a production-like environment on their laptop.

> Tips -
> 
> Follow/Read this article first to get base idea and then deploy as per your requirement by using [cka-practice-code](https://github.com/abhinandan-chougule/cka-practice-code.git) repo for specfic commands

### Lab Architecture

```plaintext
Mac (Host Machine)
        │
        ▼
VirtualBox Hypervisor
        │
        ▼
Vagrant Managed VMs
        │
        ├── controlplane
        ├── node01
        └── node02
```

### Environment Setup

Tools used in the lab:

*   **Oracle VM VirtualBox** – VM hypervisor
    
*   **Vagrant** – Infrastructure automation
    
*   **Kubernetes** – Cluster platform
    
*   **Project Calico** – CNI networking plugin
    

### VM Resources

| Node | CPU | RAM |
| --- | --- | --- |
| controlplane | 2 | 2GB |
| node01 | 2 | 2GB |
| node02 | 2 | 2GB |

### Configure laptop and build VMs  
Install the following tools on Windows or macOS x86.

Download and install **Oracle VM VirtualBox**

[https://www.virtualbox.org/wiki/Downloads](https://www.virtualbox.org/wiki/Downloads)

![](https://cdn.hashnode.com/uploads/covers/6997142f587b14d25b5231b7/a47c745e-1ca3-4a99-b36b-7f388d9b249f.png align="center")

![](https://cdn.hashnode.com/uploads/covers/6997142f587b14d25b5231b7/95c54b51-7ac3-4820-aea6-cc56d07a6364.png align="center")

![](https://cdn.hashnode.com/uploads/covers/6997142f587b14d25b5231b7/a0d24b71-ca1d-422a-860e-fd66ff54425a.png align="center")

*   ### Go to the `App` `click` `VirtualBox` to complete the installation
    

![](https://cdn.hashnode.com/uploads/covers/6997142f587b14d25b5231b7/731a8296-ecf3-4d41-a8c2-c9e98808303d.png align="center")

### Go to Terminal and Install Vagrant

```plaintext
brew tap hashicorp/tap
brew install hashicorp/tap/hashicorp-vagrant
```

*   **Verify Installation with** `vagrant --version`
    

![](https://cdn.hashnode.com/uploads/covers/6997142f587b14d25b5231b7/9299c1b3-2b98-469d-a1e2-e8b7396c81bd.png align="center")

### Clone the [cka-practice-code](https://github.com/abhinandan-chougule/cka-practice-code.git) locally

*   ### Navigate to the cloned directory
    

`cka-practice-code/kubeadm-clusters/virtualbox` **and type** `vagrant up` **to start creating virtual machines** `(Controlplane, node01 & node02)` **through a script**

![](https://cdn.hashnode.com/uploads/covers/6997142f587b14d25b5231b7/8df524f8-6226-4a75-948c-4c4520be07ea.png align="center")

> Note the IPs after completion, required for SSH

![](https://cdn.hashnode.com/uploads/covers/6997142f587b14d25b5231b7/b205896e-34a6-419d-9df2-59e30b8f35ab.png align="center")

We can check the status in **Oracle Virtual Manager** as well

![](https://cdn.hashnode.com/uploads/covers/6997142f587b14d25b5231b7/0dd70f6a-fb68-42c8-870e-74b928514b78.png align="center")

*   **Access VMs by SSH to install required tools/components**
    

Use the commands below to play with the environment

Check Status

```plaintext
vagrant status
```

Stop all VMs:

```plaintext
vagrant halt
```

Destroy environment:

```plaintext
vagrant destroy
```

Show VM's Names

```plaintext
VBoxManage list vms | awk -F\" '{print $2}'
```

* * *

### Install Multipass on Mac M series (Apple Silicon)

[https://canonical.com/multipass/install](https://canonical.com/multipass/install)

![](https://cdn.hashnode.com/uploads/covers/6997142f587b14d25b5231b7/50253748-beb6-44f6-b829-2c72d6b2a2aa.png align="center")

*   **Navigate to the Apple-Silicon directory and run the script** `./deploy-virtual-machines.sh`
    

![](https://cdn.hashnode.com/uploads/covers/6997142f587b14d25b5231b7/dca23c17-2777-4f2a-84ae-90151389e886.png align="center")

*   **Destroyed by the script** `./destroy-virtual-machines.sh`
    

* * *

### Primary setup: Run these commands on all three nodes `Controlplane, node01 & node3`

> Tips - [Kubernetes document](https://kubernetes.io/docs/setup/production-environment/tools/kubeadm/install-kubeadm/) for reference

Go to the repo [04-node-setup.md](https://github.com/abhinandan-chougule/cka-practice-code/tree/main/kubeadm-clusters/generic) and start running commands one by one

Connect all three by SSH with the below credentials.

> username: vagrant  
> password: vagrant

![](https://cdn.hashnode.com/uploads/covers/6997142f587b14d25b5231b7/c77554d5-687d-4d40-ac95-a43dfd210b1d.png align="center")

> Note- Run all these commands on all three (Controlplane, node01, node2)

* * *

### **Boot the controlplane**

Configure Controlplane by following [05-Controlplane.md](https://github.com/abhinandan-chougule/cka-practice-code/blob/main/kubeadm-clusters/generic/05-controlplane.md) commands

> Note- Run this only on Controlplane
> 
> Refer [CNI documents](https://docs.tigera.io/calico/latest/getting-started/kubernetes/self-managed-onprem/onpremises) but required commands provided in repo itself

Remember to copy the kubeadm join command and follow the remaining steps until

*   **Verify Controlplane is Ready**
    

```plaintext
kubectl get pods -n kube-system
```

![](https://cdn.hashnode.com/uploads/covers/6997142f587b14d25b5231b7/164e5dc6-7a04-4ee6-95e0-d4a22fc6ab44.png align="center")

* * *

### Join the workers nodes to Controlplane by using step [06-workers.md](https://github.com/abhinandan-chougule/certified-kubernetes-administrator-course/blob/master/kubeadm-clusters/generic/06-workers.md)

Hope you have the below ready-to-use command copied from Controlplane; otherwise, it can be retrieved by using `kubeadm token create --print-join-command`

```plaintext
kubeadm join 192.168.0.185:6443 --token 2lccuf.ha2rxb9dclxzkvrp \
        --discovery-token-ca-cert-hash sha256:26d681f9cd77e66a71bbe5e4cd903fae34458660ce2304ff7b73f168fcf9c4c2
```

*   ### Verify on Controlplane if nodes are joined as Workers
    

![](https://cdn.hashnode.com/uploads/covers/6997142f587b14d25b5231b7/94698065-9865-4398-a76f-509ea0bf7c90.png align="center")

* * *

### **Test the cluster, follow** [**07-test.md**](https://github.com/abhinandan-chougule/cka-practice-code/blob/main/kubeadm-clusters/generic/07-test.md)

*   Test worker node01
    

![](https://cdn.hashnode.com/uploads/covers/6997142f587b14d25b5231b7/24e1beac-39c4-4ccf-a631-13c3014537ad.png align="center")

*   Test worker node02
    

![](https://cdn.hashnode.com/uploads/covers/6997142f587b14d25b5231b7/e84588f8-3e53-40e6-8194-6ab7a0d4a0b5.png align="center")

*   ### Since we have installed the cluster with bridge networking (the default), we can view NodePort services with your browser.
    

Run the following command on `controlplane` to get the browser address, then copy the output to your browser:

```plaintext
echo "http://$(dig +short node01):$PORT_NUMBER"
```

### Verify from the browser

![](https://cdn.hashnode.com/uploads/covers/6997142f587b14d25b5231b7/759da800-8b89-44af-a5f8-346d93eb5da7.png align="center")

* * *

### Key Learnings

Building Kubernetes manually with kubeadm provides a deeper understanding of:

*   Control plane components
    
*   Node registration
    
*   Cluster networking
    
*   Kubernetes troubleshooting
    
*   Real production cluster architecture
    

### Final Result

✔ Multi-node Kubernetes cluster running locally  
✔ Networking configured with Calico  
✔ Worker nodes successfully joined  
✔ Nginx application deployed and accessible from the browser

This environment closely simulates a **real production Kubernetes setup** and is extremely useful for learning Kubernetes architecture and troubleshooting.

> `Thanks for your time and effort to get your hands dirty.`

### Happy Learning!

> Abhinandan Chougule
