diff --git a/.gitignore b/.gitignore index f4156f9..6ec2175 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,3 @@ temp.yaml +**/.terraform +*.tar.gz \ No newline at end of file diff --git a/apply.sh b/apply.sh index 56a3fe3..f118322 100755 --- a/apply.sh +++ b/apply.sh @@ -311,3 +311,7 @@ helm upgrade --install redis -n db -f db/redis-values.yaml bitnami/redis # downgrade apt sudo apt install kubeadm=1.30.11-1.1 + +# passless sudo + + echo "junv ALL=(ALL) NOPASSWD: ALL" | sudo tee /etc/sudoers.d/junv \ No newline at end of file diff --git a/backup-k8s.sh b/backup-k8s.sh new file mode 100755 index 0000000..7177075 --- /dev/null +++ b/backup-k8s.sh @@ -0,0 +1,38 @@ +#!/bin/bash + +# Set backup directory +BACKUP_DIR="k8s-backup-$(date +%Y%m%d-%H%M%S)" +mkdir -p "$BACKUP_DIR" + +# Get all namespaces +kubectl get ns --no-headers | awk '{print $1}' | while read namespace; do + # Create namespace directory + NS_DIR="$BACKUP_DIR/$namespace" + mkdir -p "$NS_DIR" + + # Get all resource types in this namespace + kubectl api-resources --verbs=list --namespaced -o name | while read resource; do + # Skip some internal resources + if [[ $resource != "events"* ]] && [[ $resource != "events.events.k8s.io" ]]; then + echo "Backing up $resource in $namespace" + # Get all resources of this type and save to yaml + kubectl get "$resource" -n "$namespace" -o yaml > "$NS_DIR/$resource.yaml" 2>/dev/null + fi + done +done + +# Backup cluster-wide resources +CLUSTER_DIR="$BACKUP_DIR/cluster-resources" +mkdir -p "$CLUSTER_DIR" + +# Get all non-namespaced resources +kubectl api-resources --verbs=list --namespaced=false -o name | while read resource; do + echo "Backing up cluster resource $resource" + kubectl get "$resource" -o yaml > "$CLUSTER_DIR/$resource.yaml" 2>/dev/null +done + +# Create a tarball +tar -czf "$BACKUP_DIR.tar.gz" "$BACKUP_DIR" +rm -rf "$BACKUP_DIR" + +echo "Backup completed: $BACKUP_DIR.tar.gz" diff --git a/restore-k8s.sh b/restore-k8s.sh new file mode 100755 index 0000000..3bab8f6 --- /dev/null +++ b/restore-k8s.sh @@ -0,0 +1,72 @@ +#!/bin/bash + +if [ $# -ne 1 ]; then + echo "Usage: $0 " + exit 1 +fi + +BACKUP_FILE=$1 +TEMP_DIR="k8s-restore-$(date +%Y%m%d-%H%M%S)" + +# Extract backup +echo "Extracting backup..." +tar -xzf "$BACKUP_FILE" +BACKUP_DIR=$(tar -tzf "$BACKUP_FILE" | head -1 | cut -f1 -d"/") + +# Install k3s if not present +if ! command -v k3s >/dev/null 2>&1; then + echo "Installing k3s..." + curl -sfL https://get.k3s.io | sh - + mkdir -p ~/.kube + sudo cp /etc/rancher/k3s/k3s.yaml ~/.kube/config + sudo chown $(id -u):$(id -g) ~/.kube/config +fi + +# Wait for k3s to be ready +echo "Waiting for k3s to be ready..." +kubectl wait --for=condition=Ready nodes --all --timeout=300s + +# Create namespaces first +echo "Creating namespaces..." +find "$BACKUP_DIR" -mindepth 1 -maxdepth 1 -type d | while read ns_dir; do + ns=$(basename "$ns_dir") + if [ "$ns" != "cluster-resources" ]; then + kubectl create namespace "$ns" --dry-run=client -o yaml | kubectl apply -f - + fi +done + +# Apply CRDs first from cluster-resources +echo "Applying CRDs..." +if [ -f "$BACKUP_DIR/cluster-resources/customresourcedefinitions.apiextensions.k8s.io.yaml" ]; then + kubectl apply -f "$BACKUP_DIR/cluster-resources/customresourcedefinitions.apiextensions.k8s.io.yaml" + # Wait for CRDs to be established + sleep 10 +fi + +# Restore cluster-wide resources +echo "Restoring cluster-wide resources..." +find "$BACKUP_DIR/cluster-resources" -name "*.yaml" | while read resource; do + if [[ $(basename "$resource") != "nodes.yaml" ]] && \ + [[ $(basename "$resource") != "endpoints.yaml" ]] && \ + [[ $(basename "$resource") != "customresourcedefinitions.apiextensions.k8s.io.yaml" ]]; then + echo "Applying $(basename "$resource")..." + kubectl apply -f "$resource" + fi +done + +# Restore namespaced resources +echo "Restoring namespaced resources..." +find "$BACKUP_DIR" -mindepth 1 -maxdepth 1 -type d | while read ns_dir; do + ns=$(basename "$ns_dir") + if [ "$ns" != "cluster-resources" ]; then + echo "Restoring resources in namespace: $ns" + find "$ns_dir" -name "*.yaml" | while read resource; do + echo "Applying $(basename "$resource")..." + kubectl apply -f "$resource" || true + done + fi +done + +# Clean up +rm -rf "$BACKUP_DIR" +echo "Restore completed!" diff --git a/terraform/.terraform.lock.hcl b/terraform/.terraform.lock.hcl new file mode 100644 index 0000000..81bb679 --- /dev/null +++ b/terraform/.terraform.lock.hcl @@ -0,0 +1,21 @@ +# This file is maintained automatically by "terraform init". +# Manual edits may be lost in future updates. + +provider "registry.terraform.io/loafoe/ssh" { + version = "2.6.0" + constraints = "2.6.0" + hashes = [ + "h1:t88ktB3g9wVugCTkyg17AMJ38i+nz7FwotwiDbon/GU=", + "zh:1285448b69bd388a4a59ed170f9c07c641207a7291057860557937807d02da95", + "zh:2472c5dee4265cb555a627aa4ecc5702d32cd7aebe85722820df7499b7d4502a", + "zh:2a9b8f0ad446febb517a7fe38de9b02bc1bcceb90843a713c546770eff44aa84", + "zh:66e62d5bb280af7407315a62aee2ab35f8ce1b36f7400633f75f72111deede87", + "zh:832fc1213c3447fa831c1b2331cde71072c95a3f3eae04ff23dd09975d7c6577", + "zh:a4e19d6a6e776732cce70f350e8cf1954febf1e9281b4668f567636c7d0f75d8", + "zh:ac18abae233fe367f164c5a4492875a25e1c1de38a181876ffdc9f87c75abacf", + "zh:b44203b49cdef04f3e110923017a1e80c8b5588b91605e0c0985b3c2d839d6c0", + "zh:bf489e0f8ebc6f1d0d28cd6eadd871d6d63b952deaf10271765609fce417a5cf", + "zh:c41a209c6a4bf81309e573a53ad7b9e8d655bd7e81e40685214aeac92e682333", + "zh:ded134d1359bd39c2261ce1ed3bd468f8fac4fff09c07a213a3d281313d99d59", + ] +} diff --git a/terraform/README.md b/terraform/README.md new file mode 100644 index 0000000..a182c98 --- /dev/null +++ b/terraform/README.md @@ -0,0 +1,39 @@ +# K3s Cluster Setup with Terraform + +This Terraform configuration sets up a k3s cluster on an existing virtual machine. + +## Prerequisites + +- Terraform installed on your local machine +- SSH access to the target machine +- SSH private key configured + +## Usage + +1. Initialize Terraform: +```bash +terraform init +``` + +2. Apply the configuration: +```bash +terraform apply +``` + +3. To destroy the cluster: +```bash +terraform destroy +``` + +## Configuration + +The main configuration is in `main.tf`. It uses the SSH provider to: +1. Install k3s on the target machine +2. Retrieve the node token +3. Verify the node is running + +## Important Notes + +- Make sure your SSH private key has the correct permissions (600) +- The k3s token will be output after successful installation +- You can access the cluster using `kubectl` after copying the kubeconfig from the server diff --git a/terraform/main.tf b/terraform/main.tf new file mode 100644 index 0000000..f99b97b --- /dev/null +++ b/terraform/main.tf @@ -0,0 +1,65 @@ +terraform { + required_providers { + ssh = { + source = "loafoe/ssh" + version = "2.6.0" + } + } +} + +locals { + ssh_host = "192.168.1.2" + ssh_user = "junv" + ssh_port = 22422 + ssh_private_key = file("~/.ssh/id_ed25519") + kubeconfig_cmd = "scp -P ${local.ssh_port} ${local.ssh_user}@${local.ssh_host}:/etc/rancher/k3s/k3s.yaml ~/.kube/config && sed -i '' 's/127.0.0.1/${local.ssh_host}/g' ~/.kube/config" + token_cmd = "ssh -p ${local.ssh_port} ${local.ssh_user}@${local.ssh_host} 'sudo cat /var/lib/rancher/k3s/server/node-token'" +} + +resource "ssh_resource" "k3s_install" { + host = local.ssh_host + user = local.ssh_user + port = local.ssh_port + private_key = local.ssh_private_key + timeout = "15m" + + when = "create" + + commands = [ + "echo 'Installing k3s...'", + "curl -sfL https://get.k3s.io > install.sh", + "chmod +x install.sh", + "INSTALL_K3S_EXEC='--tls-san ${local.ssh_host}' sudo -E ./install.sh", + "echo 'Waiting for k3s to start (60s)...'", + "sleep 60", + "sudo chmod 644 /etc/rancher/k3s/k3s.yaml", + "echo 'Checking node status...'", + "sudo kubectl --kubeconfig=/etc/rancher/k3s/k3s.yaml get nodes -o wide", + "echo 'K3s installation completed!'" + ] +} + +output "k3s_token" { + value = local.token_cmd + sensitive = false +} + +output "kubeconfig_command" { + value = local.kubeconfig_cmd + sensitive = false +} + +output "next_steps" { + value = <