Provisioning Kubernetes Cluster with SemaphoreUI & Kubespray

Provisioning Kubernetes Cluster with SemaphoreUI & Kubespray

Provisioning Kubernetes with SemaphoreUI and Kubespray: Automating Cluster Deployment

Kubernetes Oct 18, 2025

Semaphore UI is an open-source web-based interface for managing and automating Ansible tasks and CI/CD workflows. It allows DevOps engineers to visually organize playbooks, run commands, and monitor automation pipelines without complex terminal operations. This makes it a powerful tool for simplifying infrastructure deployment, especially when combined with Kubespray, an Ansible-based Kubernetes installer.

In this article, we’ll walk you through how to install and deploy Kubernetes using SemaphoreUI and Kubespray — from setting up your inventory and playbooks to running automated tasks via Semaphore pipelines. This approach not only reduces manual effort but also ensures repeatable, consistent, and production-ready Kubernetes deployments suitable for DevOps teams and cloud-native environments.

Topology

byamri.com - Topology flow Kubernetes with SemaphoreUI
byamri.com | Topology flow Kubernetes with SemaphoreUI

Lab Details

Kubernetes Version: v1.31.9

ETCD : Kubeadm

CNI: Calico

CRI: Containerd

OS: Ubuntu 22.04.5 LTS

IP Hostname
10.10.61.21 k8s-master-01
10.10.61.22 k8s-master-02
10.10.61.23 k8s-master-03
10.10.61.25 k8s-worker-01
10.10.61.26 k8s-worker-02

Prerequisites

  1. SemaphoreUI installed
  2. All Kubernetes nodes can connect to each other via passwordless SSH

Preparation

  1. Go to the terminal where SemaphoreUI is located, then clone kubespray. This lab uses Docker
docker exec -it  semaphore-semaphore-1 sh
git clone https://github.com/kubernetes-sigs/kubespray /tmp/kubespray
cd /tmp/kubespray
  1. Then switch to the release-2.27 branch and install requirements.txt
/tmp/kubespray $ git checkout release-2.27
/tmp/kubespray $ pip install -U -r requirements.txt

Deploy Steps

  1. The first step is to create a project in the Semaphore UI.
  2. Then, copy the PrivateKey from k8s-master-01 as a jumphost for SSH to all nodes.
cat ~/.ssh/id_rsa
...
-----BEGIN OPENSSH PRIVATE KEY-----
...
...
...
-----END OPENSSH PRIVATE KEY-----
byamri.com - Create PrivateKey
byamri.com | Create PrivateKey
  1. Then, create a repository.

Click RepositoryNEW REPOSITORY-> SAVE

byamri.com - Create Repository
byamri.com | Create Repository
  1. Create Inventory to include all hosts

Click InventoryAnsible InventoryNEW INVENTORYCreate

all:
  hosts:
    k8s-master-01:
      ansible_host: 10.10.61.21
      ip: 10.10.61.21
      access_ip: 10.10.61.21
      short_hostname: master-01
      node_taints:
        - "node-role.kubernetes.io/control-plane=:NoSchedule"
    k8s-master-02:
      ansible_host: 10.10.61.22
      ip: 10.10.61.22
      access_ip: 10.10.61.22
      short_hostname: master-02
      node_taints:
        - "node-role.kubernetes.io/control-plane=:NoSchedule"
    k8s-master-03:
      ansible_host: 10.10.61.23
      ip: 10.10.61.23
      access_ip: 10.10.61.23
      short_hostname: master-03
      node_taints:
        - "node-role.kubernetes.io/control-plane=:NoSchedule"
    k8s-worker-01:
      ansible_host: 10.10.61.25
      ip: 10.10.61.25
      access_ip: 10.10.61.25
      short_hostname: worker-01
      node_labels:
        node-role.kubernetes.io/worker: ""
        type: "app"
    k8s-worker-02:
      ansible_host: 10.10.61.26
      ip: 10.10.61.26
      access_ip: 10.10.61.26
      short_hostname: worker-02
      node_labels:
        node-role.kubernetes.io/worker: ""
        type: "app"
  children:
    kube_control_plane:
      hosts:
        k8s-master-01:
        k8s-master-02:
        k8s-master-03:
    kube_node:
      hosts:
        k8s-master-01:
        k8s-master-02:
        k8s-master-03:
        k8s-worker-01:
        k8s-worker-02:
    etcd:
      hosts:
        k8s-master-01:
        k8s-master-02:
        k8s-master-03:
    k8s_cluster:
      children:
        kube_control_plane:
        kube_node:
    calico_rr:
      hosts: {}
byamri.com - Create Inventory
byamri.com | Create Inventory
  1. Then create Environment to define the cluster version, name clusters, etc.

Click Variable GroupsNEW GROUPSAVE

byamri.com - Create Variable
byamri.com | Create Variable
💡
etcd_deployment_type uses kubeadm so that etcd is a static manifest, not systemd
Source: https://github.com/kubernetes-sigs/kubespray/blob/master/docs/operations/etcd.md#kubeadm
  1. Create a template: Task TemplatesNew TemplateAnsible Playbook → Input Value → Create
byamri.com - Create Template
byamri.com | Create Template

Deploy Cluster

  1. Select Task Templates and click Deploy KubernetesRUN
byamri.com - Deploy Kubernetes
byamri.com | Deploy Kubernetes
  1. Wait for the deployment process to complete
byamri.com - Task Success
byamri.com | Task Success

Verification

  1. Check the node status
byamri.com - Check Status Nodes
byamri.com | Check Status Nodes
  1. Check kube-system pods
byamri.com - Check Component Nodes
byamri.com - Check Component Nodes

By combining SemaphoreUI and Kubespray, deploying Kubernetes becomes more efficient, consistent, and less error-prone. This automation-driven approach not only simplifies infrastructure management but also accelerates your CI/CD workflows — helping teams focus more on innovation rather than manual configuration.

Tags

Roby Yasir Amri

I am interested in technological developments related to Cloud Computing, Linux, DevOps, Scripting, and Programming.