From cba783b7ba9c445fb08a0aa08b7df04e833c11bf Mon Sep 17 00:00:00 2001 From: Taqi Tahmid Date: Sat, 28 Jun 2025 13:37:19 +0300 Subject: [PATCH] homeserver/ansible: add playbook to spin up k8s cluster - add new playbook to spin-up kubernetes cluster using k0sctl and k0sctl config file --- ansible/inventory/group_vars/vms.yaml | 20 +++- ansible/inventory/host_vars/proxmox1.yaml | 2 +- .../playbooks/create-kubernetes-cluster.yaml | 6 ++ .../create-kubernetes-cluster/tasks/main.yaml | 97 +++++++++++++++++++ .../templates/ipAddressPool.yaml.j2 | 8 ++ .../templates/k0sctl.yaml.j2 | 70 +++++++++++++ kubernetes/kube-vip/values.yaml | 12 +++ 7 files changed, 213 insertions(+), 2 deletions(-) create mode 100644 ansible/playbooks/create-kubernetes-cluster.yaml create mode 100644 ansible/roles/create-kubernetes-cluster/tasks/main.yaml create mode 100644 ansible/roles/create-kubernetes-cluster/templates/ipAddressPool.yaml.j2 create mode 100644 ansible/roles/create-kubernetes-cluster/templates/k0sctl.yaml.j2 create mode 100644 kubernetes/kube-vip/values.yaml diff --git a/ansible/inventory/group_vars/vms.yaml b/ansible/inventory/group_vars/vms.yaml index 891dadf..0305a57 100644 --- a/ansible/inventory/group_vars/vms.yaml +++ b/ansible/inventory/group_vars/vms.yaml @@ -1,4 +1,22 @@ apt_packages: - curl - vim - - htop \ No newline at end of file + - htop + +# Kubernetes k0sctl configuration vars +master1_ip: "192.168.1.151" +master1_hostname: "vm6" +master2_ip: "192.168.1.161" +master2_hostname: "vm8" +worker1_ip: "192.168.1.152" +worker1_hostname: "vm7" +worker2_ip: "192.168.1.162" +worker2_hostname: "vm9" + +pod_CIDR: "10.244.0.0/16" +service_CIDR: "10.96.0.0/12" +metallb_ip_range: "192.168.1.201-192.168.1.220" + +k0s_version: "v1.33.2+k0s.0" +metallb_version: "0.15.2" +traefik_version: "36.2.0" \ No newline at end of file diff --git a/ansible/inventory/host_vars/proxmox1.yaml b/ansible/inventory/host_vars/proxmox1.yaml index cd1c9d6..b65a766 100644 --- a/ansible/inventory/host_vars/proxmox1.yaml +++ b/ansible/inventory/host_vars/proxmox1.yaml @@ -17,7 +17,7 @@ vm_list: ip: "192.168.1.152/24" gateway: "192.168.1.1" nameserver1: "192.168.1.145" - nameserver2: "8.8.8.8" + nameserver2: "1.1.1.1" # cloud-init variables node: "homeserver1" diff --git a/ansible/playbooks/create-kubernetes-cluster.yaml b/ansible/playbooks/create-kubernetes-cluster.yaml new file mode 100644 index 0000000..0dc1d29 --- /dev/null +++ b/ansible/playbooks/create-kubernetes-cluster.yaml @@ -0,0 +1,6 @@ +- name: Create Kubernetes Cluster + hosts: vms + vars_files: + - ../secrets/vault.yaml + roles: + - create-kubernetes-cluster diff --git a/ansible/roles/create-kubernetes-cluster/tasks/main.yaml b/ansible/roles/create-kubernetes-cluster/tasks/main.yaml new file mode 100644 index 0000000..30ab720 --- /dev/null +++ b/ansible/roles/create-kubernetes-cluster/tasks/main.yaml @@ -0,0 +1,97 @@ +- name: Remove known_hosts file if it exists + delegate_to: localhost + run_once: true + ansible.builtin.file: + path: /home/taqi/.ssh/known_hosts + state: absent + +- name: Remove k0ctl lock file if it exists + ansible.builtin.file: + path: /run/lock/k0sctl + state: absent + become: true + +- name: Install k0sctl on host + delegate_to: localhost + ansible.builtin.command: + cmd: "go install github.com/k0sproject/k0sctl@latest" + +- name: Ensure k0sctl is installed on host + delegate_to: localhost + run_once: true + ansible.builtin.command: + cmd: "k0sctl version" + register: k0sctl_version + changed_when: false + +- name: Generate k0sctl configuration file + delegate_to: localhost + run_once: true + ansible.builtin.template: + src: k0sctl.yaml.j2 + dest: /tmp/k0sctl.yaml + when: k0sctl_version is defined + tags: + - generate-k0sctl-config + +- name: Generate MetalLB IP Address Pool configuration file + delegate_to: localhost + run_once: true + ansible.builtin.template: + src: ipAddressPool.yaml.j2 + dest: /tmp/ipAddressPool.yaml + when: k0sctl_version is defined + tags: + - generatemetallb-ippool + - metallb-ippool + +- name: Create Cluster using k0sctl from host + delegate_to: localhost + run_once: true + ansible.builtin.command: + cmd: "k0sctl apply --config /tmp/k0sctl.yaml" + when: k0sctl_version is defined + +- name: Save kubeconfig file on host + delegate_to: localhost + run_once: true + ansible.builtin.shell: + cmd: "cd /tmp && k0sctl kubeconfig > /home/taqi/.kube/k0s_config.yaml" + register: kubeconfig_result + retries: 3 + delay: 5 + until: kubeconfig_result.rc == 0 + when: k0sctl_version is defined + tags: + - generate-kubeconfig + +- name: Apply IP Pool for MetalLB from host + delegate_to: localhost + run_once: true + ansible.builtin.shell: + cmd: "kubectl apply -f /tmp/ipAddressPool.yaml --kubeconfig /home/taqi/.kube/k0s_config.yaml" + register: metallb_ippool_result + retries: 3 + delay: 5 + until: metallb_ippool_result.rc == 0 + when: k0sctl_version is defined + tags: + - metallb-ippool + +- name: Cleanup temporary files + delegate_to: localhost + run_once: true + block: + - name: Remove k0sctl.yaml temporary file + ansible.builtin.file: + path: /tmp/k0sctl.yaml + state: absent + + - name: Remove ipAddressPool.yaml temporary file + ansible.builtin.shell: + cmd: "rm -f /tmp/ipAddressPool.yaml" + delegate_to: localhost + run_once: true + tags: + - cleanup + when: k0sctl_version is defined \ No newline at end of file diff --git a/ansible/roles/create-kubernetes-cluster/templates/ipAddressPool.yaml.j2 b/ansible/roles/create-kubernetes-cluster/templates/ipAddressPool.yaml.j2 new file mode 100644 index 0000000..c0d1ae7 --- /dev/null +++ b/ansible/roles/create-kubernetes-cluster/templates/ipAddressPool.yaml.j2 @@ -0,0 +1,8 @@ +apiVersion: metallb.io/v1beta1 +kind: IPAddressPool +metadata: + name: first-pool + namespace: metallb-system +spec: + addresses: + - "{{ metallb_ip_range }}" \ No newline at end of file diff --git a/ansible/roles/create-kubernetes-cluster/templates/k0sctl.yaml.j2 b/ansible/roles/create-kubernetes-cluster/templates/k0sctl.yaml.j2 new file mode 100644 index 0000000..60449e9 --- /dev/null +++ b/ansible/roles/create-kubernetes-cluster/templates/k0sctl.yaml.j2 @@ -0,0 +1,70 @@ +apiVersion: k0sctl.k0sproject.io/v1beta1 +kind: Cluster +metadata: + name: k0s-cluster +spec: + hosts: + - ssh: + address: "{{ master1_ip }}" + user: "{{ ansible_vm_user }}" + keyPath: "{{ ansible_ssh_private_key_file }}" + role: controller+worker + hostname: "{{ master1_hostname }}" + noTaints: true + - ssh: + address: "{{ master2_ip }}" + user: "{{ ansible_vm_user }}" + keyPath: "{{ ansible_ssh_private_key_file }}" + role: controller+worker + hostname: "{{ master2_hostname }}" + noTaints: true + - ssh: + address: "{{ worker1_ip }}" + user: "{{ ansible_vm_user }}" + keyPath: "{{ ansible_ssh_private_key_file }}" + role: worker + hostname: "{{ worker1_hostname }}" + - ssh: + address: "{{ worker2_ip }}" + user: "{{ ansible_vm_user }}" + keyPath: "{{ ansible_ssh_private_key_file }}" + role: worker + hostname: "{{ worker2_hostname }}" + k0s: + version: "{{ k0s_version }}" + config: + spec: + api: + address: "{{ master1_ip }}" + port: 6443 + k0sApiPort: 9443 + sans: + - "{{ master1_ip }}" + - "{{ master2_ip }}" + - k8s.local + - api.k8s.local + network: + kubeProxy: + mode: iptables + kuberouter: + disabled: false + podCIDR: "{{ pod_CIDR }}" + serviceCIDR: "{{ service_CIDR }}" + provider: kuberouter + extensions: + helm: + concurrencyLevel: 5 + repositories: + - name: metallb + url: https://metallb.github.io/metallb + - name: traefik + url: https://traefik.github.io/charts + charts: + - name: metallb + chartname: metallb/metallb + version: "{{ metallb_version }}" + namespace: metallb-system + - name: traefik + chartname: traefik/traefik + version: "{{ traefik_version }}" + namespace: traefik-system diff --git a/kubernetes/kube-vip/values.yaml b/kubernetes/kube-vip/values.yaml new file mode 100644 index 0000000..d5d6b16 --- /dev/null +++ b/kubernetes/kube-vip/values.yaml @@ -0,0 +1,12 @@ +# custom-values.yaml +config: + address: $VIP_ADDRESS +env: + # Ensure the interface name is correct for the Nodes + # Can be found using `ip a` command + # For proxmox nodes, the interface name is usually `ens18` + vip_interface: ens18 + cp_enable: true + svc_enable: false +nodeSelector: + node-role.kubernetes.io/control-plane: "true"