Compare commits

...

10 Commits

Author SHA1 Message Date
194fe4bf24 test 2025-07-05 13:22:00 +02:00
6e99cd64f9 forgot to delete some junk 2025-06-30 01:29:59 +02:00
e88a816753 consolidated more variables and deleted all hard-coded values 2025-06-30 01:28:25 +02:00
9c11c808ff forgot one line referencing old manifest 2025-06-30 00:11:31 +02:00
ab0dd018be simplified the variables and removed redundant information 2025-06-30 00:08:51 +02:00
d5032d4bb4 Create LICENSE 2025-06-29 21:27:14 +02:00
dc1e10328d added some warnings 2025-06-29 21:13:09 +02:00
2c2c10016d fixed readme 2025-06-29 21:12:00 +02:00
22369b4f02 added cert manager 2025-06-29 21:05:35 +02:00
268a82fea2 fixed some typos 2025-06-29 18:20:29 +02:00
20 changed files with 477 additions and 257 deletions

13
.env.example Normal file
View File

@ -0,0 +1,13 @@
export KUBE_USER="ubuntu"
export PRIVATE_KEY_PATH="$HOME/.ssh/id_ed25519"
export KUBE_CP="k8s-control-plane"
## Add workers to this list!
export KUBE_WORKERS=("k8s-worker1")
export ANSIBLE_DIR="ansible"
export POD_NET_CIDR="192.168.0.0/16"
export CNI_VER="v3.30.2"
export API_ADDR=$(getent hosts "$KUBE_CP" | awk '{ print $1 }')
export ACME_MAIL="name@mail.example"
export IP_POOL_RANGE="192.168.1.10-192.168.1.20"
export LOAD_BALANCER_IP="192.168.1.10"
export LONGHORN_DNS_NAME="longhorn.domain.tld"

1
.gitignore vendored Normal file
View File

@ -0,0 +1 @@
.env

201
LICENSE Normal file
View File

@ -0,0 +1,201 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

View File

@ -1,6 +1,8 @@
# Kubernetes Cluster Deployment Guide
This guide describes how to deploy a Kubernetes cluster tailored to your environment using the provided `redbutton.sh` script.
This guide describes how to deploy a Kubernetes cluster tailored to my environment using the provided `redbutton.sh` script.
Just be sure to edit the variables in the `redbutton.sh` script. I think you can scale this out by adding more hosts and adjusting the for loop but I haven't tried it yet. I needed four machines and that is what I worked with.
## ⚙️ Pre-requisites
@ -17,19 +19,25 @@ This setup will create a Kubernetes cluster with the following topology and comp
- **1 Control Plane Node**
- **2 Worker Nodes**
- **Calico** as the CNI (Container Network Interface)
- **MetalLB** as the cloud load balancer for bare metal services (change the configmap to adapt it to your network)
- **Traefik** as the ingress controller on IP 10.50.3.30 (change it in the values.yaml to adapt it to your network)
- **Longhorn** as the persistent storage provider (change the host to adapt it to your network)
- **MetalLB** as the cloud load balancer for bare metal services on your desired range
- **Traefik** as the ingress controller on your desired IP
- **Cert-Manager** to manage the internal certificates. Remember to set the API Key!
- **Longhorn** as the persistent storage provider to your desired hostname
## 🚀 How to Deploy
To initiate the deployment, run the provided script:
```bash
chmod +x init-deploy.sh
chmod +x helm-deploy.sh
cp .env.example .env
echo "export CF_API=YourSuperSecretAPIKey" >> .env
chmod +x redbutton.sh
./redbutton.sh
```
May the kubelets be ever in your favor, and your etcd never split!
![alt text](robotnik.png)

View File

@ -1,14 +0,0 @@
- name: Install Kubernetes CNI
hosts: k8s_control_plane
become: true
tasks:
- name: Download Calico manifest
get_url:
url: https://raw.githubusercontent.com/projectcalico/calico/v3.27.3/manifests/calico.yaml
dest: /tmp/calico.yaml
mode: '0644'
- name: Apply Calico CNI plugin
shell: kubectl apply -f /tmp/calico.yaml
environment:
KUBECONFIG: /etc/kubernetes/admin.conf

View File

@ -1,10 +0,0 @@
[k8s_control_plane]
k8s-control-plane
[k8s_nodes]
k8s-worker1
k8s-worker2
[all:vars]
ansible_user=kevin
ansible_ssh_private_key_file=~/.ssh/id_rsa

View File

@ -1,43 +0,0 @@
- name: Initialize Kubernetes Control Plane
hosts: k8s_control_plane
become: true
vars:
## This is the default networkd of Calico
pod_network_cidr: "192.168.0.0/16"
apiserver_advertise_address: "10.50.3.21"
cri_socket: "unix:///run/containerd/containerd.sock"
kubeconfig_src: "/etc/kubernetes/admin.conf"
kubeconfig_dest: "/home/{{ ansible_user }}/.kube/config"
## Crea la directory .kube nella home dell'utente
tasks:
- name: Ensure .kube directory exists
file:
path: "/home/{{ ansible_user }}/.kube"
state: directory
owner: "{{ ansible_user }}"
group: "{{ ansible_user }}"
mode: '0755'
## Crea il cluster con i parametri indicati sopra
- name: Run kubeadm init
command: >
kubeadm init
--pod-network-cidr={{ pod_network_cidr }}
--apiserver-advertise-address={{ apiserver_advertise_address }}
--cri-socket {{ cri_socket }}
args:
creates: /etc/kubernetes/pki/ca.crt
## Copia la configurazione del cluster così da poter eseguire comandi kubectl dall'utente
- name: Copy admin.conf to user's kube config
copy:
src: "{{ kubeconfig_src }}"
dest: "{{ kubeconfig_dest }}"
remote_src: true
owner: "{{ ansible_user }}"
group: "{{ ansible_user }}"
mode: '0644'

View File

@ -3,106 +3,96 @@
become: true
tasks:
- name: Ensure apt cache is updated
apt:
update_cache: yes
cache_valid_time: 3600
- name: Add Docker signing key
ansible.builtin.apt_key:
url: https://download.docker.com/linux/ubuntu/gpg
state: present
- name: Add Docker repository
ansible.builtin.apt_repository:
repo: deb [arch=amd64] https://download.docker.com/linux/ubuntu noble stable
state: present
- name: Install required packages
apt:
ansible.builtin.apt:
name:
- apt-transport-https
- ca-certificates
- curl
- gpg
- containerd
- containerd.io
state: present
update_cache: yes
## Questo non è nella documentazione! bisogna generare il file di configurazione di containerd
## ed scriverlo nella directory apposita, altrimenti usa un suo default che non va bene
## ed scriverlo nella directory apposita, altrimenti usa un suo default che non va bene.
- name: Ensure containerd config directory exists
file:
- name: Ensure containerd config directory exists.
ansible.builtin.file:
path: /etc/containerd
state: directory
mode: '0755'
- name: Generate default containerd config if missing
command: containerd config default
register: containerd_config
when: not lookup('file', '/etc/containerd/config.toml', errors='ignore')
changed_when: false
- name: Get defaults from containerd.
ansible.builtin.command: containerd config default
register: containerd_config_default
- name: Write default containerd config
copy:
content: "{{ containerd_config.stdout }}"
- name: Create config file
ansible.builtin.copy:
content: "{{ containerd_config_default.stdout }}"
dest: /etc/containerd/config.toml
when: containerd_config is defined
- name: Set SystemdCgroup = true in containerd config
replace:
- name: Set SystemdCgroup to true
ansible.builtin.replace:
path: /etc/containerd/config.toml
regexp: '^(\s*SystemdCgroup\s*=\s*)false'
replace: '\1true'
regexp: '^(\s*)SystemdCgroup\s*=\s*false'
replace: '\1SystemdCgroup = true'
- name: Restart containerd
systemd:
ansible.builtin.service:
name: containerd
state: restarted
enabled: yes
enabled: true
## Importantissimo per la gestione interna della network
- name: Enable IPv4 forwarding at runtime
sysctl:
ansible.posix.sysctl:
name: net.ipv4.ip_forward
value: '1'
state: present
reload: yes
reload: true
sysctl_set: yes
## Installa kubectl, kubeadm e kubelet dal repo ufficiale kubernetes
- name: Create /etc/apt/keyrings directory
file:
path: /etc/apt/keyrings
state: directory
mode: '0755'
- name: Add Kubernetes signing key
ansible.builtin.apt_key:
url: https://pkgs.k8s.io/core:/stable:/v1.33/deb/Release.key
state: present
- name: Download and save the Kubernetes APT key
ansible.builtin.shell: |
curl -fsSL https://pkgs.k8s.io/core:/stable:/v1.33/deb/Release.key | gpg --dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring.gpg
args:
creates: /etc/apt/keyrings/kubernetes-apt-keyring.gpg
- name: Add Kubernetes APT repository
copy:
dest: /etc/apt/sources.list.d/kubernetes.list
content: |
deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.gpg] https://pkgs.k8s.io/core:/stable:/v1.33/deb/ /
- name: Update apt cache after adding Kubernetes repo
apt:
update_cache: yes
- name: Add Kubernetes repository
ansible.builtin.apt_repository:
repo: deb [arch=amd64] https://pkgs.k8s.io/core:/stable:/v1.33/deb/ /
state: present
- name: Install Kubernetes components
apt:
ansible.builtin.apt:
name:
- kubelet
- kubeadm
- kubectl
state: present
update_cache: true
## Ferma i pacchetti ad una specifica versione
- name: Hold Kubernetes packages
ansible.builtin.shell: apt-mark hold kubelet kubeadm kubectl
- name: Enable and start containerd
systemd:
name: containerd
enabled: true
state: started
ansible.builtin.dpkg_selections:
name: "{{ item }}"
selection: hold
loop:
- kubelet
- kubeadm
- kubectl
## Abilita il servizio di kubelet

View File

@ -0,0 +1,46 @@
---
- name: Setup Longhorn Requirements
hosts: all
become: true
tasks:
- name: Install required packages
ansible.builtin.apt:
name:
- open-iscsi
- nfs-common
- cryptsetup
- dmsetup
state: present
update_cache: yes
- name: Ensure required kernel modules are loaded
community.general.modprobe:
name: "{{ item }}"
state: present
loop:
- iscsi_tcp
- dm_crypt
- name: Ensure required modules load on boot
ansible.builtin.copy:
content: "{{ item.name }}"
dest: "/etc/modules-load.d/{{ item.name }}.conf"
owner: root
group: root
mode: '0644'
loop:
- { name: iscsi_tcp }
- { name: dm_crypt }
- name: Disable and stop multipathd service
ansible.builtin.systemd_service:
name: multipathd
state: stopped
enabled: false
- name: Disable multipathd socket (if exists)
ansible.builtin.systemd_service:
name: multipathd.socket
enabled: false
state: stopped
ignore_errors: true

View File

@ -1,52 +0,0 @@
---
- name: Setup Longhorn Requirements
hosts: all
become: true
tasks:
- name: Install required packages
apt:
name:
- open-iscsi
- nfs-common
- cryptsetup
- dmsetup
state: present
update_cache: yes
- name: Ensure iscsi_tcp kernel module is loaded
modprobe:
name: iscsi_tcp
state: present
- name: Ensure dm_crypt kernel module is loaded
modprobe:
name: dm_crypt
state: present
- name: Ensure iscsi_tcp module loads on boot
copy:
dest: /etc/modules-load.d/iscsi.conf
content: |
iscsi_tcp
owner: root
group: root
mode: '0644'
- name: Ensure dm_crypt module loads on boot
copy:
dest: /etc/modules-load.d/dm_crypt.conf
content: |
dm_crypt
owner: root
group: root
mode: '0644'
- name: Disable and stop multipathd service
systemd:
name: multipathd
enabled: false
state: stopped
masked: true
daemon_reload: yes
ignore_errors: true # in case it's not installed

View File

@ -1,5 +0,0 @@
# master-k8s.yaml
- import_playbook: k8s-install-deps.yaml
- import_playbook: k8s-init.yaml
- import_playbook: install_cni.yaml
- import_playbook: longhorn-reqs.yaml

View File

@ -1,36 +0,0 @@
#!/bin/bash
## Setup MetalLb repo
helm repo add metallb https://metallb.github.io/metallb
helm repo update
helm install metallb metallb/metallb -n metallb-system --create-namespace
echo "Waiting for all the pods to start..."
kubectl wait --namespace metallb-system \
--for=condition=Ready pod \
--all \
--timeout=120s
## Apply the load-balancer IPs
kubectl apply -f manifests/metallb/metallb-config.yaml
## Setup traefik repo
helm repo add traefik https://traefik.github.io/charts
helm repo update
helm install traefik traefik/traefik -n traefik -f ./manifests/traefik/values.yaml --create-namespace
## Setup MetalLb repo
helm repo add longhorn https://charts.longhorn.io
helm repo update
helm install longhorn longhorn/longhorn -n longhorn-system --create-namespace
echo "Waiting for all the pods to start..."
kubectl wait --namespace longhorn-system \
--for=condition=Ready pod \
--all \
--timeout=120s
## Apply ingress rule
kubectl apply -f manifests/longhorn/longhorn-ingress.yaml

View File

@ -1,25 +0,0 @@
#!/bin/bash
KUBE_USER="kevin"
KUBE_CP="k8s-control-plane"
KUBE_W1="k8s-worker1"
KUBE_W2="k8s-worker2"
ANSIBLE_DIR="ansible"
## Prepare all of the nodes with k8s using the ansible playbooks I prepared
ansible-playbook -i ./"$ANSIBLE_DIR"/inventory.ini ./"$ANSIBLE_DIR"/master-k8s.yaml
## Fetch the configuration from the freshly installed cluster. BEWARE THAT ANY EXISTING CONFIG WILL BE OVERWRITTEN
scp "$KUBE_USER@$KUBE_CP":"$HOME"/.kube/config "$HOME"/.kube/config
## Now join the workers to the cluster
JOIN_TOKEN=$(ssh "$KUBE_USER@$KUBE_CP" "kubeadm token create --print-join-command")
for NODE in "$KUBE_W1" "$KUBE_W2"; do
echo "Joining $NODE"
ssh "$KUBE_USER@$NODE" "sudo $JOIN_TOKEN"
done

View File

@ -0,0 +1,16 @@
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: cloudflare-clusterissuer
spec:
acme:
email: ${ACME_MAIL}
server: https://acme-v02.api.letsencrypt.org/directory
privateKeySecretRef:
name: cloudflare-clusterissuer-key
solvers:
- dns01:
cloudflare:
apiTokenSecretRef:
name: cloudflare-api-token-secret
key: api-token

View File

@ -0,0 +1,5 @@
crds:
enabled: true
extraArgs:
- --dns01-recursive-nameservers-only
- --dns01-recursive-nameservers=1.1.1.1:53,1.0.0.1:53

View File

@ -0,0 +1,13 @@
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: longhorn-ssl-certificate
namespace: longhorn-system
spec:
# Secret names are always required.
secretName: longhorn-ssl-certificate
issuerRef:
name: cloudflare-clusterissuer
kind: ClusterIssuer
dnsNames:
- ${LONGHORN_DNS_NAME}

View File

@ -6,8 +6,12 @@ metadata:
annotations:
traefik.ingress.kubernetes.io/router.entrypoints: websecure
spec:
tls:
- hosts:
- ${LONGHORN_DNS_NAME}
secretName: longhorn-ssl-certificate
rules:
- host: longhorn.nixit.it
- host: ${LONGHORN_DNS_NAME}
http:
paths:
- path: /

View File

@ -5,7 +5,7 @@ metadata:
namespace: metallb-system
spec:
addresses:
- 10.50.3.30-10.50.3.40
- ${IP_POOL_RANGE}
---
apiVersion: metallb.io/v1beta1

View File

@ -1,8 +1,3 @@
service:
spec:
externalTrafficPolicy: Local
loadBalancerIP: 10.50.3.30
ports:
web:
redirections:

View File

@ -1,4 +1,117 @@
#!/bin/bash
./init-deploy.sh
./helm-deploy.sh
source .env
ALL_NODES=("$KUBE_CP" "${KUBE_WORKERS[@]}")
## Prepare all of the nodes with k8s using the ansible playbooks I prepared
ansible-playbook ./"$ANSIBLE_DIR"/k8s-install-deps.yaml \
-i "$(IFS=, ; echo "${ALL_NODES[*]}",)" \
-u "$KUBE_USER" \
--private-key "$PRIVATE_KEY_PATH"
ansible-playbook ./"$ANSIBLE_DIR"/longhorn-deps.yaml \
-i "$(IFS=, ; echo "${KUBE_WORKERS[*]}",)" \
-u "$KUBE_USER" \
--private-key "$PRIVATE_KEY_PATH"
## Bootstrap the cluster
ssh "$KUBE_USER@$KUBE_CP" \
"sudo kubeadm init \
--pod-network-cidr=$POD_NET_CIDR \
--apiserver-advertise-address=$API_ADDR \
--cri-socket unix:///run/containerd/containerd.sock"
ssh "$KUBE_USER@$KUBE_CP" \
"sudo cp /etc/kubernetes/admin.conf /tmp/config && sudo chown $KUBE_USER:$KUBE_USER /tmp/config"
## Fetch the configuration from the freshly installed cluster. BEWARE THAT ANY EXISTING CONFIG WILL BE OVERWRITTEN
scp "$KUBE_USER@$KUBE_CP":/tmp/config "$HOME"/.kube/config
## Install the CNI
kubectl apply -f \
"https://raw.githubusercontent.com/projectcalico/calico/$CNI_VER/manifests/calico.yaml"
## Now join the workers to the cluster
JOIN_TOKEN=$(ssh "$KUBE_USER@$KUBE_CP" \
"sudo kubeadm token create --print-join-command")
for NODE in "${KUBE_WORKERS[@]}"; do
echo "Joining $NODE"
ssh "$KUBE_USER@$NODE" "sudo $JOIN_TOKEN"
done
### NOW APPLYING HELMS ###
## Setup all the needed repos
helm repo add metallb https://metallb.github.io/metallb
helm repo add traefik https://traefik.github.io/charts
helm repo add jetstack https://charts.jetstack.io
helm repo add longhorn https://charts.longhorn.io
helm repo update
## Let's install metallb!
helm install \
metallb metallb/metallb \
-n metallb-system \
--create-namespace
echo "Waiting for all the pods to start..."
kubectl wait --namespace metallb-system \
--for=condition=Ready pod \
--all \
--timeout=200s
## Apply the load-balancer IPs range
envsubst < ./manifests/metallb/metallb-config.yaml | kubectl apply -f -
## Let's install traefik!
helm install \
traefik traefik/traefik \
-n traefik \
-f ./manifests/traefik/values.yaml \
--set service.spec.loadBalancerIP="$LOAD_BALANCER_IP" \
--create-namespace
## Let's install Cert-Manager!
helm install \
cert-manager jetstack/cert-manager \
-n cert-manager \
-f ./manifests/certmanager/values.yaml \
--create-namespace
## Set up the cloudflare API token secret
kubectl create secret generic cloudflare-api-token-secret \
--from-literal=api-token="$CF_API" \
-n=cert-manager
## Apply the cloudflare Issuer
envsubst < ./manifests/certmanager/issuer.yaml | kubectl apply -f -
## Let's install longhorn!
helm install longhorn longhorn/longhorn -n longhorn-system --create-namespace
echo "Waiting for all the pods to start..."
kubectl wait --namespace longhorn-system \
--for=condition=Ready pod \
--all \
--timeout=120s
## Apply ingress rule and certificate
envsubst < ./manifests/longhorn/certificate.yaml | kubectl apply -f -
envsubst < ./manifests/longhorn/ingress.yaml | kubectl apply -f -