-
Notifications
You must be signed in to change notification settings - Fork 15
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
scripts: easy tool to quick setup the cluster from zero
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.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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() |