Kubernetes Cluster Setup in 7 Steps with Kubespray


There are many ways to set up a Kubernetes cluster. Some involve heavy manual configuration, others rely on cloud-specific tooling. The method that stands out for its simplicity and flexibility is Kubespray, an Ansible-based installer maintained by the Kubernetes SIGs community.

Kubespray supports a wide range of operating systems, from Ubuntu and CentOS to Debian and Red Hat. Configuration is done through YAML files, and enabling or disabling components often takes only a single line change. This reduces the workload significantly compared to setting up each component by hand.

Since Kubespray runs on Ansible, the control machine needs a few prerequisites: SSH access to the target nodes, Ansible, Git, and Python.

Step 1: Clone Kubespray

Start by cloning the Kubespray repository. Using --depth 1 limits the history to the latest commit, which speeds up the download.

git clone --depth 1 git@github.com:kubernetes-sigs/kubespray.git

This creates a kubespray directory with the full project structure.

Step 2: Install Dependencies

Move into the cloned directory and install the required Python packages.

cd kubespray
sudo pip3 install -r requirements.txt

If you are using Python 2 instead of Python 3, use pip instead of pip3.

Step 3: Create an Inventory

Kubespray ships with a sample inventory. Copy it to a new directory named after your environment.

cp -rfp inventory/sample inventory/test

The inventory/test/ directory now holds the configuration files for your cluster. You can use any name instead of test; this is only a directory name.

Step 4: Configure the Inventory File

The main inventory file is inventory/test/inventory.ini. It defines the nodes in your cluster and their roles.

Assume the following three servers:

NamePrivate IPPublic IPRole
node110.10.10.191.91.91.91Master
node210.10.10.292.92.92.92Worker
node310.10.10.393.93.93.93Worker

Edit inventory.ini and organize the nodes into the relevant sections:

[all]
node1 ansible_host=91.91.91.91 ip=10.10.10.1 etcd_member_name=etcd1
node2 ansible_host=92.92.92.92 ip=10.10.10.2 etcd_member_name=etcd2
node3 ansible_host=93.93.93.93 ip=10.10.10.3 etcd_member_name=etcd3

[kube-master]
node1

[kube-node]
node2
node3

[etcd]
node1

The ansible_host parameter is the IP address the control machine uses to reach the node. The ip parameter is the private IP used for node-to-node communication.

If you want the master node to also serve as a worker, add its name under [kube-node] as well.

Firewall Ports

If a firewall is in use, the following ports must be open on the respective nodes.

Master node:

PortPurpose
6443/tcpKubernetes API
2379-2380/tcpetcd
10250/tcpkubelet API
10251/tcpkube-scheduler
10252/tcpkube-controller-manager
10255/tcpRead-only kubelet

Worker node:

PortPurpose
10250/tcpkubelet API
10255/tcpRead-only kubelet
30000-32767/tcpNodePort services
6783/tcpWeave Net (if used)

Step 5: Adjust Group Variables

Kubespray uses group variables for cluster-wide settings. Two files are important here:

  • inventory/test/group_vars/all/all.yml
  • inventory/test/group_vars/k8s-cluster/k8s-cluster.yml

These files contain parameters for enabling or disabling components such as the Nginx Ingress Controller, Helm, the Kubernetes Dashboard, CoreDNS, the Metrics Server, and proxy settings. Each option is documented inline, and most can be toggled by changing false to true (or the reverse).

Step 6: Run the Playbook

Once the inventory and variables are configured, run the Ansible playbook.

ansible-playbook -i inventory/test/inventory.ini --become cluster.yml

This process takes about 20 to 30 minutes, depending on the number of nodes and network speed. The playbook installs all Kubernetes components, including etcd, kubelet, kube-apiserver, kube-controller-manager, kube-scheduler, kube-proxy, and the container runtime (Docker or containerd, depending on configuration).

Step 7: Configure kubectl on the Master

After the playbook completes successfully, SSH into the master node (node1 in this example) and verify that kubectl works.

kubectl get pods

You will likely see an error like:

The connection to the server localhost:8080 was refused - did you specify the right host or port?

This happens because kubectl does not have a valid kubeconfig yet. The cluster configuration is located at /etc/kubernetes/admin.conf. Copy it to the default location:

mkdir ~/.kube
sudo cp /etc/kubernetes/admin.conf ~/.kube/config
sudo chown $USER:$USER ~/.kube/config

Now kubectl is ready. Test it by creating a deployment:

kubectl create deployment hello --image=hello-world
kubectl get pods

The output should show a running pod:

NAME                     READY   STATUS    RESTARTS   AGE
hello-67d96bb797-lz8xf   1/1     Running   0          1d

Wrapping Up

Kubernetes continues to gain popularity as more teams adopt microservices and need to scale their applications. Kubespray makes the installation process repeatable and infrastructure-agnostic. Whether you are setting up a cluster for development or production, these seven steps provide a solid foundation.

The full Kubespray documentation covers many additional configuration options, including different network plugins, container runtimes, and add-on components. The official repository is a good next stop for deeper customization.

Hopefully this guide helps you get your cluster up and running without trouble. Wishing you a smooth Kubernetes journey.


Originally published in Turkish on Medium

You can read this post in Turkish.