Automating Kubernetes Cluster Setup with Ansible

Over the years, I’ve found myself repeatedly setting up Kubernetes clusters using kubeadm—and while it works well, the manual process can get repetitive and error-prone. That’s why I built kubeadm-ansible: an Ansible playbook that automates the entire process of standing up a Kubernetes cluster.

This project was born out of my desire for a simple, reusable way to deploy multi-node clusters quickly—especially in test environments, homelabs, and lightweight production setups.

Table of Contents

What It Does

kubeadm-ansible simplifies Kubernetes provisioning by:

  1. Installing all required packages (containerd, kubeadm, etc.)
  2. Networking and firewall setup.
  3. Initializing the control plane
  4. Joining master to existing cluster.
  5. Joining worker nodes.
  6. Installing CNI - (Calico/Flannel)
  7. Installing CSI - (Rook-Ceph/Longhron)
  8. Addon app - metallb, metrics-server, kube-state-metrics, headlamp
  9. Support deployment on both Debian base or Redhat base distros.

Setup

Clone the repo:

1git clone https://github.com/mcbtaguiad/kubeadm-ansible.git
2cd kubeadm-ansible

Build docker image or just pull from my repository.

1docker compose build
2docker compose up -d
3
4# exec to container
5docker exec -it ansible-kubeadm bash

Inventory

Update your inventory file at inventory/hosts.ini with the IPs or hostnames of your master and worker nodes.

Single Master Cluster

hosts.ini

 1[all]
 2master01 ansible_host=192.168.254.201 ansible_user=mcbtaguiad
 3worker01 ansible_host=192.168.254.204 ansible_user=mcbtaguiad
 4worker02 ansible_host=192.168.254.205 ansible_user=mcbtaguiad
 5
 6[master]
 7master01 ansible_host=192.168.254.201 ansible_user=mcbtaguiad
 8
 9[worker]
10worker01 ansible_host=192.168.254.204 ansible_user=mcbtaguiad
11worker02 ansible_host=192.168.254.205 ansible_user=mcbtaguiad

Multi Master Cluster

Note: Need at least 3 master nodes for high availability cluster

 1[all]
 2master01 ansible_host=192.168.254.201 ansible_user=mcbtaguiad
 3master02 ansible_host=192.168.254.202 ansible_user=mcbtaguiad
 4master03 ansible_host=192.168.254.203 ansible_user=mcbtaguiad
 5worker01 ansible_host=192.168.254.204 ansible_user=mcbtaguiad
 6worker02 ansible_host=192.168.254.205 ansible_user=mcbtaguiad
 7
 8[master]
 9master01 ansible_host=192.168.254.201 ansible_user=mcbtaguiad
10master02 ansible_host=192.168.254.202 ansible_user=mcbtaguiad
11master03 ansible_host=192.168.254.203 ansible_user=mcbtaguiad
12
13[worker]
14worker01 ansible_host=192.168.254.204 ansible_user=mcbtaguiad
15worker02 ansible_host=192.168.254.205 ansible_user=mcbtaguiad

Cluster Config

Enable what you need in you k8s cluster. By default, it is configured with Calico for CNI and Rook-Ceph for CSI. Also Metallb is enabled in the addon role, if you need Ingress Controller then you might need to install that separately. Check the repo for full variable and applications available to install.

*kubeadm_init.yaml

 1# ============================================================================ #
 2# Author: Mark Taguiad <marktaguiad@marktaguiad.dev>
 3# ============================================================================ #
 4- hosts: all
 5  become: true
 6  vars:
 7    HOST_COUNT: "{{ ansible_play_hosts | length }}"
 8    KUBECONFIG: /etc/kubernetes/admin.conf
 9
10  tasks:
11
12    - name: Run sys role
13      include_role:
14        name: sys
15
16    - name: Run k8s role
17      include_role:
18        name: k8s
19      vars:
20        K8S_VERSION: v1.35
21
22    - name: Wait 30 seconds
23      pause:
24        seconds: 30
25
26    - name: Run cni role
27      include_role:
28        name: cni
29      vars:
30        CNI_PLUGIN_VERSION: v1.9.0
31        CALICO_VERSION: v3.31.4
32        FLANNEL_VERSION: v0.28.1
33        apps_enabled:
34          - calico
35          # - flannel
36
37    - name: Wait 30 seconds
38      pause:
39        seconds: 30
40
41    - name: Run csi role
42      include_role:
43        name: csi
44      vars:
45        LONGHORN_VERSION: v1.11.0
46        ROOK_VERSION: v1.19.2
47        apps_enabled:
48          - rook-ceph
49          # - longhorn
50
51    - name: Wait 60 seconds
52      pause:
53        seconds: 60
54
55    - name: Run addons role
56      include_role:
57        name: addons
58      vars:
59        METALLB_VERSION: v0.15.3
60        METALLB_IP_RANGE: "192.168.254.220-192.168.254.250"
61        apps_enabled:
62          - metallb
63          - kube-state-metrics
64          - metrics-server
65          - headlamp

Init cluster

ansible-playbook playbook/kubeadm_init.yaml -i inventory/hosts.ini

That’s it. In just a few minutes, you’ll have a functional Kubernetes cluster ready to go. Kube Config file is generated as admin.yaml in the current directory.

Other Playbook

Check out the repo, I’ve also added playbook to add worker to existing cluster. Playbook to reset the nodes and installing k3s cluster (experimental).

k3s

For older or less powerful system, consider using k3s. The repo focus more on kubeadm, some error might be encountered if using this k3s playbook.

1$ ansible-playbook playbook/k3s_install.yaml -i inventory/hosts.ini