Skip to content

Commit

Permalink
scripts: easy tool to quick setup the cluster from zero
Browse files Browse the repository at this point in the history
Signed-off-by: Le Yao <[email protected]>
  • Loading branch information
Le Yao committed Oct 24, 2023
1 parent a0e719a commit 306b1d0
Showing 1 changed file with 227 additions and 0 deletions.
227 changes: 227 additions & 0 deletions k8s-manifests/k8s-setup.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,227 @@
import subprocess
import sys
import os
import platform
import re

def execute_command(command, return_output=False):
process = subprocess.Popen(
command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True
)

output = []
while True:
line = process.stdout.readline()
if not line:
break
print(line, end='') # Print line in real-time
if return_output:
output.append(line)

process.stdout.close()
process.wait()

if process.returncode != 0:
error_output = process.stderr.read()
print(f"Command failed with error: {process.returncode}\n{error_output}")
process.stderr.close()
sys.exit(1)

if return_output:
return ''.join(output)

def check_host_readiness():
# Check if script is run as root
if os.geteuid() != 0:
print("Please run as root")
sys.exit(1)

# Check kernel version (assuming a minimum kernel version of 3.10)
kernel_version = platform.uname().release
major_version = int(kernel_version.split('.')[0])
minor_version = int(kernel_version.split('.')[1])
if major_version < 3 or (major_version == 3 and minor_version < 10):
print(f"Kernel version {kernel_version} is not supported. Minimum required is 3.10")
sys.exit(1)

def disable_swap():
commands = [
"swapoff -a",
"sed -i '/ swap / s/^\(.*\)$/#\1/g' /etc/fstab"
]
for command in commands:
execute_command(command)

def configure_kernel():
commands = [
"tee /etc/modules-load.d/containerd.conf <<EOF\noverlay\nbr_netfilter\nEOF",
"modprobe overlay",
"modprobe br_netfilter",
"tee /etc/sysctl.d/kubernetes.conf <<EOF\nnet.bridge.bridge-nf-call-ip6tables=1\nnet.bridge.bridge-nf-call-iptables=1\nnet.ipv4.ip_forward=1\nEOF",
"sysctl --system"
]
for command in commands:
execute_command(command)

def install_pre_requisites():
commands = [
"apt update",
"apt install -y apt-transport-https ca-certificates curl gnupg software-properties-common debian-keyring debian-archive-keyring",
"mkdir -p -m 755 /etc/apt/keyrings",
# Import the Docker GPG key using keyrings
"curl -fsSL https://download.docker.com/linux/ubuntu/gpg | gpg --no-default-keyring --keyring gnupg-ring:/etc/apt/trusted.gpg.d/docker-archive-keyring.gpg --import --batch --yes",
"chmod 644 /etc/apt/trusted.gpg.d/docker-archive-keyring.gpg", # Set the appropriate permissions
"add-apt-repository -y \"deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable\"",
# Import the Kubernetes GPG key using keyrings
"curl -s https://packages.cloud.google.com/apt/doc/apt-key.gpg | gpg --no-default-keyring --keyring gnupg-ring:/etc/apt/trusted.gpg.d/kubernetes-archive-keyring.gpg --import --batch --yes",
"chmod 644 /etc/apt/trusted.gpg.d/kubernetes-archive-keyring.gpg", # Set the appropriate permissions
"apt-add-repository -y \"deb http://apt.kubernetes.io/ kubernetes-xenial main\"",
"apt update"
]
for command in commands:
execute_command(command)

def install_container():
commands = [
"apt install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin"
]
for command in commands:
execute_command(command)

def configure_container():
commands = [
"mkdir -p /etc/containerd",
"containerd config default | tee /etc/containerd/config.toml >/dev/null 2>&1",
"sed -i 's/SystemdCgroup \= false/SystemdCgroup \= true/g' /etc/containerd/config.toml",
"systemctl daemon-reload",
"systemctl restart containerd",
"systemctl enable containerd"
]
for command in commands:
execute_command(command)

def install_kubernetes():
k8s_version = input("Enter Kubernetes version (default: 1.28.2-00): ") or "1.28.2-00"

commands = [
f"apt install -y kubelet={k8s_version} kubeadm={k8s_version} kubectl={k8s_version} --allow-change-held-packages",
"apt-mark hold kubelet kubeadm kubectl"
]
for command in commands:
execute_command(command)

def initialize_cluster():
pod_network_cidr = input("Enter Pod Network CIDR (default: 10.244.0.0/16): ") or "10.244.0.0/16"
command = f"kubeadm init --pod-network-cidr={pod_network_cidr}"
output = execute_command(command, return_output=True)

# Setup kubectl for the user
commands = [
"mkdir -p $HOME/.kube",
"cp /etc/kubernetes/admin.conf $HOME/.kube/config",
"chown $(id -u):$(id -g) $HOME/.kube/config"
]
for command in commands:
execute_command(command)

join_command_match = re.search(r"kubeadm join ([\d.]+:\d+) --token (\S+) \\\n\s+ --discovery-token-ca-cert-hash sha256:(\S+)", output)

if join_command_match:
master_ip = join_command_match.group(1)
token = join_command_match.group(2)
cert_hash = join_command_match.group(3)
print(f"Master IP: {master_ip}")
print(f"Token: {token}")
print(f"Certificate Hash: {cert_hash}")
else:
print("Failed to extract kubeadm join command details.")

print(f"Cluster initialized with Pod Network CIDR {pod_network_cidr}")

def join_cluster():
token = input("Enter token to join the cluster: ")
cert_hash = input("Enter certificate hash: ")
master_ip = input("Enter master node IP address: ")
command = f"kubeadm join {master_ip}:6443 --token {token} --discovery-token-ca-cert-hash sha256:{cert_hash}"
execute_command(command)

def setup_cluster():
print("1: Initialize as Master Node")
print("2: Join as Worker Node")
choice = input("Enter choice (1/2): ")
if choice == '1':
initialize_cluster()
elif choice == '2':
join_cluster()
else:
print("Invalid choice. Exiting.")
sys.exit(1)

def install_cni():
print("Do you want to setup a Container Network Interface (CNI)?")
cni_choice = input("Enter 'yes' to setup or 'no' to skip: ").lower()
if cni_choice == 'no':
print("Skipping CNI setup.")
return

print("Choose a CNI plugin:")
print("1: Calico")
print("2: Flannel")
cni_plugin_choice = input("Enter choice (1/2): ")

if cni_plugin_choice == '1':
calico_url = "https://projectcalico.docs.tigera.io/manifests/calico.yaml"
command = f"kubectl apply -f {calico_url}"
execute_command(command)
print("Calico CNI plugin has been installed.")
elif cni_plugin_choice == '2':
flannel_url = "https://raw.githubusercontent.com/flannel-io/flannel/master/Documentation/kube-flannel.yml"
command = f"kubectl apply -f {flannel_url}"
execute_command(command)
print("Flannel CNI plugin has been installed.")
else:
print("Invalid choice. Exiting.")
sys.exit(1)


def main():

check_host_readiness()

steps = {
1: disable_swap,
2: configure_kernel,
3: install_pre_requisites,
4: install_container,
5: configure_container,
6: install_kubernetes,
7: setup_cluster,
8: install_cni
}

while True: # This will keep the loop running until the user decides to exit
print("Choose a step to execute:")
print("0: Execute all steps")
for step_num, step_func in steps.items():
print(f"{step_num}: {step_func.__name__}")
print("9: Exit") # Provide an option to exit

try:
choice = int(input("Enter step number: "))
except ValueError:
print("Invalid input. Please enter a number.")
continue # This will skip the rest of the loop and go back to the beginning

if choice == 0:
for step_func in steps.values():
step_func()
break # This will exit the loop once all steps have been executed
elif choice in steps:
steps[choice]() # Execute the chosen step
elif choice == 9:
break # This will exit the loop, ending the program
else:
print("Invalid step number. Please try again.")

if __name__ == "__main__":
main()

0 comments on commit 306b1d0

Please sign in to comment.