Files
homelab-infrastructure-as-code/02-k8s-bootstrap/CLAUDE.md
T
kasun 3f98874008
Deploy k8s Bootstrap / Pulumi Preview (pull_request) Successful in 45s
Deploy k8s Bootstrap / Bootstrap k3s Cluster (pull_request) Skipped
Deploy k8s Infra / Pulumi Preview (pull_request) Successful in 47s
Deploy k8s Infra / Pulumi Deploy (pull_request) Skipped
feature: join k3s-worker-3 into the cluster
Wires the k8s-bootstrap join sequence (start, SSH wait, k3s agent join,
Longhorn disk mount) and the k8s-infra Longhorn disk patch for worker-3.
Its VM was already provisioned by proxmox-infra in an earlier branch.
2026-07-28 22:52:22 +02:00

2.5 KiB

k8s-bootstrap

This file provides guidance to Claude Code when working in 02-k8s-bootstrap. See the repo-root CLAUDE.md for shared conventions, deployment order, and CI/CD.

Bootstraps a k3s cluster on the Proxmox VMs created by proxmox-infra. Starts VMs via the Proxmox REST API, then provisions k3s over SSH using @pulumi/command remote.Command.

How it works

  1. Starts all VMs via POST /api2/json/nodes/{node}/qemu/{vmid}/status/start
  2. Waits for port 22 to open on each VM (bash /dev/tcp)
  3. Installs k3s on k3s-master-1 with --cluster-init --tls-san <master1Ip>
  4. Joins k3s-master-2 and k3s-master-3 as embedded etcd nodes
  5. Joins k3s-worker-1, k3s-worker-2, and k3s-worker-3 as agent nodes
  6. Formats the workers' dedicated scsi1 disk (ext4, if not already formatted) and mounts it at /mnt/longhorn-extra (via /etc/fstab) — this is the disk 03-k8s-infra later registers as an extra Longhorn disk, to keep Longhorn off the root filesystem and avoid DiskPressure
  7. Reads /etc/rancher/k3s/k3s.yaml from master-1 via SSH, patches the server URL, and exports it as the secret stack output kubeconfig

VM IDs and the CI runner SSH private key are read automatically from the proxmox-infra stack output via StackReference — no manual setup needed for those.

Required Pulumi config

# Pre-shared k3s token — any strong random string
pulumi config set --secret k3sToken "$(openssl rand -hex 32)"

# Node IPs — static DHCP leases from the router (not secrets)
pulumi config set master1Ip "192.168.1.x"
pulumi config set master2Ip "192.168.1.x"
pulumi config set master3Ip "192.168.1.x"
pulumi config set worker1Ip "192.168.1.x"
pulumi config set worker2Ip "192.168.1.x"
pulumi config set worker3Ip "192.168.1.x"

Proxmox credentials (pve1Endpoint, pve1ApiToken, pve2Endpoint, pve2ApiToken, pve3Endpoint, pve3ApiToken) are read automatically from proxmox-infra via StackReference — do not set them here.

Prerequisites

proxmox-infra must be deployed first. On its first pulumi up it generates an ed25519 SSH keypair via @pulumi/tls, writes the public key into every VM's cloud-init, and exports the private key as a secret stack output. VMs must be re-provisioned (or have the public key manually added to ~/.ssh/authorized_keys) before this stack can SSH in.

CI/CD

Workflow: ../.gitea/workflows/02-deploy-k8s-bootstrap.yaml. Secret: K8S_BOOTSTRAP_PULUMI_DEV_YAML. Deploy is manual (workflow_dispatch) — re-running this stack restarts the bootstrap sequence against live VMs.