[{"data":1,"prerenderedAt":1622},["ShallowReactive",2],{"blog-en-k3s-on-proxmox-cluster":3,"blog-related-en-k3s-on-proxmox-cluster":1571,"blog-en-k3s-on-proxmox-cluster-alt":271},{"id":4,"title":5,"author":6,"body":7,"date":1555,"description":1556,"extension":1557,"image":236,"locale":1558,"meta":1559,"navigation":271,"path":1560,"seo":1561,"stem":1562,"tags":1563,"__hash__":1570},"blog\u002Fblog\u002Fen\u002Fk3s-on-proxmox-cluster.md","Building a K3s Cluster on Proxmox: A Step-by-Step Guide","Kubo Team",{"type":8,"value":9,"toc":1529},"minimark",[10,22,31,36,45,50,120,124,127,210,219,223,226,230,513,517,520,665,668,709,718,722,726,735,817,823,851,855,858,911,915,923,975,982,986,989,1064,1068,1072,1081,1207,1211,1218,1234,1238,1246,1300,1304,1308,1386,1390,1393,1449,1456,1460,1463,1470,1479,1484,1525],[11,12,13,14,21],"p",{},"Kubernetes has become the de facto standard for modern application deployment, but building and operating a full K8s cluster demands significant expertise. ",[15,16,20],"a",{"href":17,"rel":18},"https:\u002F\u002Fk3s.io\u002F",[19],"nofollow","K3s"," is a lightweight Kubernetes distribution developed by Rancher Labs that delivers full Kubernetes functionality with minimal resource overhead. Combined with Proxmox VE, it enables you to build a flexible, cost-effective Kubernetes foundation.",[11,23,24,25,30],{},"For organizations needing enterprise-grade managed Kubernetes, ",[15,26,29],{"href":27,"rel":28},"https:\u002F\u002Fwww.hexabase.com\u002Fproduct\u002Fkubo\u002Fon-premise",[19],"Kubo On-Premise"," delivers a fully managed K8s environment on Proxmox, minimizing infrastructure management overhead so your team can focus on development.",[32,33,35],"h2",{"id":34},"architecture-design-and-vm-planning","Architecture Design and VM Planning",[11,37,38,39,44],{},"K3s cluster design balances availability requirements against resource budgets. The ",[15,40,43],{"href":41,"rel":42},"https:\u002F\u002Fdocs.k3s.io\u002F",[19],"K3s official documentation"," recommends a minimum of 3 server nodes for production environments.",[46,47,49],"h3",{"id":48},"recommended-configuration","Recommended Configuration",[51,52,53,78],"table",{},[54,55,56],"thead",{},[57,58,59,63,66,69,72,75],"tr",{},[60,61,62],"th",{},"Role",[60,64,65],{},"Count",[60,67,68],{},"CPU",[60,70,71],{},"RAM",[60,73,74],{},"Storage",[60,76,77],{},"OS",[79,80,81,102],"tbody",{},[57,82,83,87,90,93,96,99],{},[84,85,86],"td",{},"Server (Control Plane)",[84,88,89],{},"3",[84,91,92],{},"4 vCPU",[84,94,95],{},"8 GB",[84,97,98],{},"50 GB SSD",[84,100,101],{},"Ubuntu 24.04 LTS",[57,103,104,107,110,112,115,118],{},[84,105,106],{},"Worker (Data Plane)",[84,108,109],{},"3+",[84,111,92],{},[84,113,114],{},"16 GB",[84,116,117],{},"100 GB SSD",[84,119,101],{},[46,121,123],{"id":122},"network-design","Network Design",[11,125,126],{},"Assign static IPs outside the DHCP range to cluster nodes:",[51,128,129,142],{},[54,130,131],{},[57,132,133,136,139],{},[60,134,135],{},"Node",[60,137,138],{},"Hostname",[60,140,141],{},"IP Address",[79,143,144,155,166,177,188,199],{},[57,145,146,149,152],{},[84,147,148],{},"Server 1",[84,150,151],{},"k3s-server-1",[84,153,154],{},"192.168.1.101",[57,156,157,160,163],{},[84,158,159],{},"Server 2",[84,161,162],{},"k3s-server-2",[84,164,165],{},"192.168.1.102",[57,167,168,171,174],{},[84,169,170],{},"Server 3",[84,172,173],{},"k3s-server-3",[84,175,176],{},"192.168.1.103",[57,178,179,182,185],{},[84,180,181],{},"Worker 1",[84,183,184],{},"k3s-worker-1",[84,186,187],{},"192.168.1.111",[57,189,190,193,196],{},[84,191,192],{},"Worker 2",[84,194,195],{},"k3s-worker-2",[84,197,198],{},"192.168.1.112",[57,200,201,204,207],{},[84,202,203],{},"Worker 3",[84,205,206],{},"k3s-worker-3",[84,208,209],{},"192.168.1.113",[11,211,212,213,218],{},"Leverage VLANs in ",[15,214,217],{"href":215,"rel":216},"https:\u002F\u002Fpve.proxmox.com\u002Fwiki\u002FNetwork_Configuration",[19],"Proxmox network configuration"," to isolate management and cluster traffic.",[32,220,222],{"id":221},"creating-vm-templates","Creating VM Templates",[11,224,225],{},"Build a Cloud-Init enabled VM template for efficient node provisioning. This allows you to spin up new nodes in minutes through simple clone operations.",[46,227,229],{"id":228},"downloading-ubuntu-cloud-image-and-creating-the-template","Downloading Ubuntu Cloud Image and Creating the Template",[231,232,237],"pre",{"className":233,"code":234,"language":235,"meta":236,"style":236},"language-bash shiki shiki-themes tokyo-night","# Run on Proxmox host\n# Download Ubuntu 24.04 Cloud Image\nwget https:\u002F\u002Fcloud-images.ubuntu.com\u002Fnoble\u002Fcurrent\u002Fnoble-server-cloudimg-amd64.img\n\n# Create VM (ID 9000 reserved for templates)\nqm create 9000 --name ubuntu-2404-template --memory 4096 --cores 2 \\\n  --net0 virtio,bridge=vmbr0 --scsihw virtio-scsi-single\n\n# Import disk image\nqm set 9000 --scsi0 local-lvm:0,import-from=\u002Froot\u002Fnoble-server-cloudimg-amd64.img\n\n# Add Cloud-Init drive\nqm set 9000 --ide2 local-lvm:cloudinit\nqm set 9000 --boot order=scsi0\nqm set 9000 --serial0 socket --vga serial0\n\n# Set Cloud-Init defaults\nqm set 9000 --ciuser ubuntu --cipassword \u003Cpassword>\nqm set 9000 --sshkeys ~\u002F.ssh\u002Fid_rsa.pub\nqm set 9000 --ipconfig0 ip=dhcp\n\n# Convert to template\nqm template 9000\n","bash","",[238,239,240,249,255,266,273,279,315,330,335,341,357,362,368,383,398,419,424,430,461,476,491,496,502],"code",{"__ignoreMap":236},[241,242,245],"span",{"class":243,"line":244},"line",1,[241,246,248],{"class":247},"sbD-w","# Run on Proxmox host\n",[241,250,252],{"class":243,"line":251},2,[241,253,254],{"class":247},"# Download Ubuntu 24.04 Cloud Image\n",[241,256,258,262],{"class":243,"line":257},3,[241,259,261],{"class":260},"sE3pS","wget",[241,263,265],{"class":264},"sPY7s"," https:\u002F\u002Fcloud-images.ubuntu.com\u002Fnoble\u002Fcurrent\u002Fnoble-server-cloudimg-amd64.img\n",[241,267,269],{"class":243,"line":268},4,[241,270,272],{"emptyLinePlaceholder":271},true,"\n",[241,274,276],{"class":243,"line":275},5,[241,277,278],{"class":247},"# Create VM (ID 9000 reserved for templates)\n",[241,280,282,285,288,292,296,299,302,305,308,311],{"class":243,"line":281},6,[241,283,284],{"class":260},"qm",[241,286,287],{"class":264}," create",[241,289,291],{"class":290},"sOJ5S"," 9000",[241,293,295],{"class":294},"sT800"," --name",[241,297,298],{"class":264}," ubuntu-2404-template",[241,300,301],{"class":294}," --memory",[241,303,304],{"class":290}," 4096",[241,306,307],{"class":294}," --cores",[241,309,310],{"class":290}," 2",[241,312,314],{"class":313},"sAklC"," \\\n",[241,316,318,321,324,327],{"class":243,"line":317},7,[241,319,320],{"class":294},"  --net0",[241,322,323],{"class":264}," virtio,bridge=vmbr0",[241,325,326],{"class":294}," --scsihw",[241,328,329],{"class":264}," virtio-scsi-single\n",[241,331,333],{"class":243,"line":332},8,[241,334,272],{"emptyLinePlaceholder":271},[241,336,338],{"class":243,"line":337},9,[241,339,340],{"class":247},"# Import disk image\n",[241,342,344,346,349,351,354],{"class":243,"line":343},10,[241,345,284],{"class":260},[241,347,348],{"class":264}," set",[241,350,291],{"class":290},[241,352,353],{"class":294}," --scsi0",[241,355,356],{"class":264}," local-lvm:0,import-from=\u002Froot\u002Fnoble-server-cloudimg-amd64.img\n",[241,358,360],{"class":243,"line":359},11,[241,361,272],{"emptyLinePlaceholder":271},[241,363,365],{"class":243,"line":364},12,[241,366,367],{"class":247},"# Add Cloud-Init drive\n",[241,369,371,373,375,377,380],{"class":243,"line":370},13,[241,372,284],{"class":260},[241,374,348],{"class":264},[241,376,291],{"class":290},[241,378,379],{"class":294}," --ide2",[241,381,382],{"class":264}," local-lvm:cloudinit\n",[241,384,386,388,390,392,395],{"class":243,"line":385},14,[241,387,284],{"class":260},[241,389,348],{"class":264},[241,391,291],{"class":290},[241,393,394],{"class":294}," --boot",[241,396,397],{"class":264}," order=scsi0\n",[241,399,401,403,405,407,410,413,416],{"class":243,"line":400},15,[241,402,284],{"class":260},[241,404,348],{"class":264},[241,406,291],{"class":290},[241,408,409],{"class":294}," --serial0",[241,411,412],{"class":264}," socket",[241,414,415],{"class":294}," --vga",[241,417,418],{"class":264}," serial0\n",[241,420,422],{"class":243,"line":421},16,[241,423,272],{"emptyLinePlaceholder":271},[241,425,427],{"class":243,"line":426},17,[241,428,429],{"class":247},"# Set Cloud-Init defaults\n",[241,431,433,435,437,439,442,445,448,451,454,458],{"class":243,"line":432},18,[241,434,284],{"class":260},[241,436,348],{"class":264},[241,438,291],{"class":290},[241,440,441],{"class":294}," --ciuser",[241,443,444],{"class":264}," ubuntu",[241,446,447],{"class":294}," --cipassword",[241,449,450],{"class":313}," \u003C",[241,452,453],{"class":264},"passwor",[241,455,457],{"class":456},"sGX4V","d",[241,459,460],{"class":313},">\n",[241,462,464,466,468,470,473],{"class":243,"line":463},19,[241,465,284],{"class":260},[241,467,348],{"class":264},[241,469,291],{"class":290},[241,471,472],{"class":294}," --sshkeys",[241,474,475],{"class":264}," ~\u002F.ssh\u002Fid_rsa.pub\n",[241,477,479,481,483,485,488],{"class":243,"line":478},20,[241,480,284],{"class":260},[241,482,348],{"class":264},[241,484,291],{"class":290},[241,486,487],{"class":294}," --ipconfig0",[241,489,490],{"class":264}," ip=dhcp\n",[241,492,494],{"class":243,"line":493},21,[241,495,272],{"emptyLinePlaceholder":271},[241,497,499],{"class":243,"line":498},22,[241,500,501],{"class":247},"# Convert to template\n",[241,503,505,507,510],{"class":243,"line":504},23,[241,506,284],{"class":260},[241,508,509],{"class":264}," template",[241,511,512],{"class":290}," 9000\n",[46,514,516],{"id":515},"cloning-nodes","Cloning Nodes",[11,518,519],{},"Create full clones from the template for each node:",[231,521,523],{"className":233,"code":522,"language":235,"meta":236,"style":236},"# Server nodes\nqm clone 9000 101 --name k3s-server-1 --full\nqm clone 9000 102 --name k3s-server-2 --full\nqm clone 9000 103 --name k3s-server-3 --full\n\n# Worker nodes (with increased resources)\nqm clone 9000 111 --name k3s-worker-1 --full\nqm set 111 --memory 16384 --cores 4\nqm clone 9000 112 --name k3s-worker-2 --full\nqm set 112 --memory 16384 --cores 4\n",[238,524,525,530,550,568,586,590,595,613,631,649],{"__ignoreMap":236},[241,526,527],{"class":243,"line":244},[241,528,529],{"class":247},"# Server nodes\n",[241,531,532,534,537,539,542,544,547],{"class":243,"line":251},[241,533,284],{"class":260},[241,535,536],{"class":264}," clone",[241,538,291],{"class":290},[241,540,541],{"class":290}," 101",[241,543,295],{"class":294},[241,545,546],{"class":264}," k3s-server-1",[241,548,549],{"class":294}," --full\n",[241,551,552,554,556,558,561,563,566],{"class":243,"line":257},[241,553,284],{"class":260},[241,555,536],{"class":264},[241,557,291],{"class":290},[241,559,560],{"class":290}," 102",[241,562,295],{"class":294},[241,564,565],{"class":264}," k3s-server-2",[241,567,549],{"class":294},[241,569,570,572,574,576,579,581,584],{"class":243,"line":268},[241,571,284],{"class":260},[241,573,536],{"class":264},[241,575,291],{"class":290},[241,577,578],{"class":290}," 103",[241,580,295],{"class":294},[241,582,583],{"class":264}," k3s-server-3",[241,585,549],{"class":294},[241,587,588],{"class":243,"line":275},[241,589,272],{"emptyLinePlaceholder":271},[241,591,592],{"class":243,"line":281},[241,593,594],{"class":247},"# Worker nodes (with increased resources)\n",[241,596,597,599,601,603,606,608,611],{"class":243,"line":317},[241,598,284],{"class":260},[241,600,536],{"class":264},[241,602,291],{"class":290},[241,604,605],{"class":290}," 111",[241,607,295],{"class":294},[241,609,610],{"class":264}," k3s-worker-1",[241,612,549],{"class":294},[241,614,615,617,619,621,623,626,628],{"class":243,"line":332},[241,616,284],{"class":260},[241,618,348],{"class":264},[241,620,605],{"class":290},[241,622,301],{"class":294},[241,624,625],{"class":290}," 16384",[241,627,307],{"class":294},[241,629,630],{"class":290}," 4\n",[241,632,633,635,637,639,642,644,647],{"class":243,"line":337},[241,634,284],{"class":260},[241,636,536],{"class":264},[241,638,291],{"class":290},[241,640,641],{"class":290}," 112",[241,643,295],{"class":294},[241,645,646],{"class":264}," k3s-worker-2",[241,648,549],{"class":294},[241,650,651,653,655,657,659,661,663],{"class":243,"line":343},[241,652,284],{"class":260},[241,654,348],{"class":264},[241,656,641],{"class":290},[241,658,301],{"class":294},[241,660,625],{"class":290},[241,662,307],{"class":294},[241,664,630],{"class":290},[11,666,667],{},"Set static IPs on each node:",[231,669,671],{"className":233,"code":670,"language":235,"meta":236,"style":236},"qm set 101 --ipconfig0 ip=192.168.1.101\u002F24,gw=192.168.1.1\nqm set 102 --ipconfig0 ip=192.168.1.102\u002F24,gw=192.168.1.1\n# Continue for remaining nodes\n",[238,672,673,689,704],{"__ignoreMap":236},[241,674,675,677,679,681,683,686],{"class":243,"line":244},[241,676,284],{"class":260},[241,678,348],{"class":264},[241,680,541],{"class":290},[241,682,487],{"class":294},[241,684,685],{"class":264}," ip=192.168.1.101\u002F24,gw=",[241,687,688],{"class":290},"192.168.1.1\n",[241,690,691,693,695,697,699,702],{"class":243,"line":251},[241,692,284],{"class":260},[241,694,348],{"class":264},[241,696,560],{"class":290},[241,698,487],{"class":294},[241,700,701],{"class":264}," ip=192.168.1.102\u002F24,gw=",[241,703,688],{"class":290},[241,705,706],{"class":243,"line":257},[241,707,708],{"class":247},"# Continue for remaining nodes\n",[11,710,711,712,717],{},"With ",[15,713,716],{"href":714,"rel":715},"https:\u002F\u002Fkubo.hexabase.io\u002F",[19],"Kubo",", you can bypass this complexity entirely and get a production-grade K8s environment through declarative configuration alone.",[32,719,721],{"id":720},"installing-and-configuring-k3s","Installing and Configuring K3s",[46,723,725],{"id":724},"initializing-the-first-server-node","Initializing the First Server Node",[11,727,728,729,734],{},"Initialize the K3s cluster on the first server node (k3s-server-1). Following the ",[15,730,733],{"href":731,"rel":732},"https:\u002F\u002Fdocs.k3s.io\u002Fquick-start",[19],"K3s Quick-Start Guide",":",[231,736,738],{"className":233,"code":737,"language":235,"meta":236,"style":236},"# Run on first server node\ncurl -sfL https:\u002F\u002Fget.k3s.io | K3S_TOKEN=\u003Csecure-token> sh -s - server \\\n  --cluster-init \\\n  --tls-san=192.168.1.100 \\\n  --disable traefik \\\n  --write-kubeconfig-mode 644\n",[238,739,740,745,785,792,799,809],{"__ignoreMap":236},[241,741,742],{"class":243,"line":244},[241,743,744],{"class":247},"# Run on first server node\n",[241,746,747,750,753,756,759,762,765,768,771,774,777,780,783],{"class":243,"line":251},[241,748,749],{"class":260},"curl",[241,751,752],{"class":294}," -sfL",[241,754,755],{"class":264}," https:\u002F\u002Fget.k3s.io",[241,757,758],{"class":313}," |",[241,760,761],{"class":260}," K3S_TOKEN",[241,763,764],{"class":313},"=\u003C",[241,766,767],{"class":264},"secure-token",[241,769,770],{"class":313},">",[241,772,773],{"class":260}," sh",[241,775,776],{"class":294}," -s",[241,778,779],{"class":264}," -",[241,781,782],{"class":264}," server",[241,784,314],{"class":313},[241,786,787,790],{"class":243,"line":257},[241,788,789],{"class":294},"  --cluster-init",[241,791,314],{"class":313},[241,793,794,797],{"class":243,"line":268},[241,795,796],{"class":294},"  --tls-san=192.168.1.100",[241,798,314],{"class":313},[241,800,801,804,807],{"class":243,"line":275},[241,802,803],{"class":294},"  --disable",[241,805,806],{"class":264}," traefik",[241,808,314],{"class":313},[241,810,811,814],{"class":243,"line":281},[241,812,813],{"class":294},"  --write-kubeconfig-mode",[241,815,816],{"class":290}," 644\n",[11,818,819],{},[820,821,822],"strong",{},"Option explanations:",[824,825,826,833,839,845],"ul",{},[827,828,829,832],"li",{},[238,830,831],{},"--cluster-init",": Initialize in HA mode using embedded etcd",[827,834,835,838],{},[238,836,837],{},"--tls-san",": Add load balancer VIP to the certificate's Subject Alternative Names",[827,840,841,844],{},[238,842,843],{},"--disable traefik",": Disable built-in Traefik to install a custom Ingress Controller later",[827,846,847,850],{},[238,848,849],{},"--write-kubeconfig-mode 644",": Set readable permissions on kubeconfig",[46,852,854],{"id":853},"joining-additional-server-nodes","Joining Additional Server Nodes",[11,856,857],{},"Add remaining server nodes to the cluster:",[231,859,861],{"className":233,"code":860,"language":235,"meta":236,"style":236},"# Run on k3s-server-2 and k3s-server-3\ncurl -sfL https:\u002F\u002Fget.k3s.io | K3S_TOKEN=\u003Csecure-token> sh -s - server \\\n  --server https:\u002F\u002F192.168.1.101:6443 \\\n  --tls-san=192.168.1.100\n",[238,862,863,868,896,906],{"__ignoreMap":236},[241,864,865],{"class":243,"line":244},[241,866,867],{"class":247},"# Run on k3s-server-2 and k3s-server-3\n",[241,869,870,872,874,876,878,880,882,884,886,888,890,892,894],{"class":243,"line":251},[241,871,749],{"class":260},[241,873,752],{"class":294},[241,875,755],{"class":264},[241,877,758],{"class":313},[241,879,761],{"class":260},[241,881,764],{"class":313},[241,883,767],{"class":264},[241,885,770],{"class":313},[241,887,773],{"class":260},[241,889,776],{"class":294},[241,891,779],{"class":264},[241,893,782],{"class":264},[241,895,314],{"class":313},[241,897,898,901,904],{"class":243,"line":257},[241,899,900],{"class":294},"  --server",[241,902,903],{"class":264}," https:\u002F\u002F192.168.1.101:6443",[241,905,314],{"class":313},[241,907,908],{"class":243,"line":268},[241,909,910],{"class":294},"  --tls-san=192.168.1.100\n",[46,912,914],{"id":913},"adding-worker-nodes","Adding Worker Nodes",[11,916,917,918,734],{},"Worker nodes join by specifying the ",[15,919,922],{"href":920,"rel":921},"https:\u002F\u002Fdocs.k3s.io\u002Fcli\u002Fagent",[19],"K3S_URL environment variable",[231,924,926],{"className":233,"code":925,"language":235,"meta":236,"style":236},"# Run on each worker node\ncurl -sfL https:\u002F\u002Fget.k3s.io | K3S_URL=https:\u002F\u002F192.168.1.101:6443 \\\n  K3S_TOKEN=\u003Csecure-token> sh -\n",[238,927,928,933,954],{"__ignoreMap":236},[241,929,930],{"class":243,"line":244},[241,931,932],{"class":247},"# Run on each worker node\n",[241,934,935,937,939,941,943,946,949,952],{"class":243,"line":251},[241,936,749],{"class":260},[241,938,752],{"class":294},[241,940,755],{"class":264},[241,942,758],{"class":313},[241,944,945],{"class":260}," K3S_URL",[241,947,948],{"class":313},"=",[241,950,951],{"class":264},"https:\u002F\u002F192.168.1.101:6443",[241,953,314],{"class":260},[241,955,956,959,962,965,968,970,972],{"class":243,"line":257},[241,957,958],{"class":264},"  K3S_TOKEN=",[241,960,961],{"class":313},"\u003C",[241,963,964],{"class":264},"secure-toke",[241,966,967],{"class":456},"n",[241,969,770],{"class":313},[241,971,773],{"class":264},[241,973,974],{"class":264}," -\n",[11,976,977,978,981],{},"The server token can be retrieved from ",[238,979,980],{},"\u002Fvar\u002Flib\u002Francher\u002Fk3s\u002Fserver\u002Fnode-token"," on any server node.",[46,983,985],{"id":984},"configuring-kubeconfig","Configuring kubeconfig",[11,987,988],{},"Copy the kubeconfig to your local machine for kubectl access:",[231,990,992],{"className":233,"code":991,"language":235,"meta":236,"style":236},"# Retrieve kubeconfig from server node\nscp ubuntu@192.168.1.101:\u002Fetc\u002Francher\u002Fk3s\u002Fk3s.yaml ~\u002F.kube\u002Fconfig\n\n# Update server address to external IP\nsed -i 's\u002F127.0.0.1\u002F192.168.1.101\u002F' ~\u002F.kube\u002Fconfig\n\n# Verify node list\nkubectl get nodes -o wide\n",[238,993,994,999,1010,1014,1019,1038,1042,1047],{"__ignoreMap":236},[241,995,996],{"class":243,"line":244},[241,997,998],{"class":247},"# Retrieve kubeconfig from server node\n",[241,1000,1001,1004,1007],{"class":243,"line":251},[241,1002,1003],{"class":260},"scp",[241,1005,1006],{"class":264}," ubuntu@192.168.1.101:\u002Fetc\u002Francher\u002Fk3s\u002Fk3s.yaml",[241,1008,1009],{"class":264}," ~\u002F.kube\u002Fconfig\n",[241,1011,1012],{"class":243,"line":257},[241,1013,272],{"emptyLinePlaceholder":271},[241,1015,1016],{"class":243,"line":268},[241,1017,1018],{"class":247},"# Update server address to external IP\n",[241,1020,1021,1024,1027,1030,1033,1036],{"class":243,"line":275},[241,1022,1023],{"class":260},"sed",[241,1025,1026],{"class":294}," -i",[241,1028,1029],{"class":313}," '",[241,1031,1032],{"class":264},"s\u002F127.0.0.1\u002F192.168.1.101\u002F",[241,1034,1035],{"class":313},"'",[241,1037,1009],{"class":264},[241,1039,1040],{"class":243,"line":281},[241,1041,272],{"emptyLinePlaceholder":271},[241,1043,1044],{"class":243,"line":317},[241,1045,1046],{"class":247},"# Verify node list\n",[241,1048,1049,1052,1055,1058,1061],{"class":243,"line":332},[241,1050,1051],{"class":260},"kubectl",[241,1053,1054],{"class":264}," get",[241,1056,1057],{"class":264}," nodes",[241,1059,1060],{"class":294}," -o",[241,1062,1063],{"class":264}," wide\n",[32,1065,1067],{"id":1066},"network-and-storage-configuration","Network and Storage Configuration",[46,1069,1071],{"id":1070},"metallb-load-balancer","MetalLB Load Balancer",[11,1073,1074,1075,1080],{},"In bare-metal environments, ",[15,1076,1079],{"href":1077,"rel":1078},"https:\u002F\u002Fmetallb.universe.tf\u002F",[19],"MetalLB"," assigns external IPs to LoadBalancer-type Services:",[231,1082,1084],{"className":233,"code":1083,"language":235,"meta":236,"style":236},"# Install MetalLB\nkubectl apply -f https:\u002F\u002Fraw.githubusercontent.com\u002Fmetallb\u002Fmetallb\u002Fv0.14.9\u002Fconfig\u002Fmanifests\u002Fmetallb-native.yaml\n\n# Configure IP address pool\ncat \u003C\u003CEOF | kubectl apply -f -\napiVersion: metallb.io\u002Fv1beta1\nkind: IPAddressPool\nmetadata:\n  name: default-pool\n  namespace: metallb-system\nspec:\n  addresses:\n  - 192.168.1.200-192.168.1.250\n---\napiVersion: metallb.io\u002Fv1beta1\nkind: L2Advertisement\nmetadata:\n  name: default\n  namespace: metallb-system\nEOF\n",[238,1085,1086,1091,1104,1108,1113,1135,1140,1145,1150,1155,1160,1165,1170,1175,1180,1184,1189,1193,1198,1202],{"__ignoreMap":236},[241,1087,1088],{"class":243,"line":244},[241,1089,1090],{"class":247},"# Install MetalLB\n",[241,1092,1093,1095,1098,1101],{"class":243,"line":251},[241,1094,1051],{"class":260},[241,1096,1097],{"class":264}," apply",[241,1099,1100],{"class":294}," -f",[241,1102,1103],{"class":264}," https:\u002F\u002Fraw.githubusercontent.com\u002Fmetallb\u002Fmetallb\u002Fv0.14.9\u002Fconfig\u002Fmanifests\u002Fmetallb-native.yaml\n",[241,1105,1106],{"class":243,"line":257},[241,1107,272],{"emptyLinePlaceholder":271},[241,1109,1110],{"class":243,"line":268},[241,1111,1112],{"class":247},"# Configure IP address pool\n",[241,1114,1115,1118,1121,1124,1126,1129,1131,1133],{"class":243,"line":275},[241,1116,1117],{"class":260},"cat",[241,1119,1120],{"class":313}," \u003C\u003C",[241,1122,1123],{"class":313},"EOF",[241,1125,758],{"class":313},[241,1127,1128],{"class":260}," kubectl",[241,1130,1097],{"class":264},[241,1132,1100],{"class":294},[241,1134,974],{"class":264},[241,1136,1137],{"class":243,"line":281},[241,1138,1139],{"class":264},"apiVersion: metallb.io\u002Fv1beta1\n",[241,1141,1142],{"class":243,"line":317},[241,1143,1144],{"class":264},"kind: IPAddressPool\n",[241,1146,1147],{"class":243,"line":332},[241,1148,1149],{"class":264},"metadata:\n",[241,1151,1152],{"class":243,"line":337},[241,1153,1154],{"class":264},"  name: default-pool\n",[241,1156,1157],{"class":243,"line":343},[241,1158,1159],{"class":264},"  namespace: metallb-system\n",[241,1161,1162],{"class":243,"line":359},[241,1163,1164],{"class":264},"spec:\n",[241,1166,1167],{"class":243,"line":364},[241,1168,1169],{"class":264},"  addresses:\n",[241,1171,1172],{"class":243,"line":370},[241,1173,1174],{"class":264},"  - 192.168.1.200-192.168.1.250\n",[241,1176,1177],{"class":243,"line":385},[241,1178,1179],{"class":264},"---\n",[241,1181,1182],{"class":243,"line":400},[241,1183,1139],{"class":264},[241,1185,1186],{"class":243,"line":421},[241,1187,1188],{"class":264},"kind: L2Advertisement\n",[241,1190,1191],{"class":243,"line":426},[241,1192,1149],{"class":264},[241,1194,1195],{"class":243,"line":432},[241,1196,1197],{"class":264},"  name: default\n",[241,1199,1200],{"class":243,"line":463},[241,1201,1159],{"class":264},[241,1203,1204],{"class":243,"line":478},[241,1205,1206],{"class":313},"EOF\n",[46,1208,1210],{"id":1209},"nginx-ingress-controller","NGINX Ingress Controller",[11,1212,1213,1214,734],{},"Route HTTP\u002FHTTPS traffic with the ",[15,1215,1210],{"href":1216,"rel":1217},"https:\u002F\u002Fkubernetes.github.io\u002Fingress-nginx\u002F",[19],[231,1219,1221],{"className":233,"code":1220,"language":235,"meta":236,"style":236},"kubectl apply -f https:\u002F\u002Fraw.githubusercontent.com\u002Fkubernetes\u002Fingress-nginx\u002Fcontroller-v1.12.0\u002Fdeploy\u002Fstatic\u002Fprovider\u002Fbaremetal\u002Fdeploy.yaml\n",[238,1222,1223],{"__ignoreMap":236},[241,1224,1225,1227,1229,1231],{"class":243,"line":244},[241,1226,1051],{"class":260},[241,1228,1097],{"class":264},[241,1230,1100],{"class":294},[241,1232,1233],{"class":264}," https:\u002F\u002Fraw.githubusercontent.com\u002Fkubernetes\u002Fingress-nginx\u002Fcontroller-v1.12.0\u002Fdeploy\u002Fstatic\u002Fprovider\u002Fbaremetal\u002Fdeploy.yaml\n",[46,1235,1237],{"id":1236},"longhorn-distributed-storage","Longhorn Distributed Storage",[11,1239,1240,1245],{},[15,1241,1244],{"href":1242,"rel":1243},"https:\u002F\u002Flonghorn.io\u002F",[19],"Longhorn"," is a Kubernetes-native distributed block storage system with excellent K3s integration:",[231,1247,1249],{"className":233,"code":1248,"language":235,"meta":236,"style":236},"# Install Longhorn\nkubectl apply -f https:\u002F\u002Fraw.githubusercontent.com\u002Flonghorn\u002Flonghorn\u002Fv1.7.2\u002Fdeploy\u002Flonghorn.yaml\n\n# Set as default StorageClass\nkubectl patch storageclass longhorn -p '{\"metadata\":{\"annotations\":{\"storageclass.kubernetes.io\u002Fis-default-class\":\"true\"}}}'\n",[238,1250,1251,1256,1267,1271,1276],{"__ignoreMap":236},[241,1252,1253],{"class":243,"line":244},[241,1254,1255],{"class":247},"# Install Longhorn\n",[241,1257,1258,1260,1262,1264],{"class":243,"line":251},[241,1259,1051],{"class":260},[241,1261,1097],{"class":264},[241,1263,1100],{"class":294},[241,1265,1266],{"class":264}," https:\u002F\u002Fraw.githubusercontent.com\u002Flonghorn\u002Flonghorn\u002Fv1.7.2\u002Fdeploy\u002Flonghorn.yaml\n",[241,1268,1269],{"class":243,"line":257},[241,1270,272],{"emptyLinePlaceholder":271},[241,1272,1273],{"class":243,"line":268},[241,1274,1275],{"class":247},"# Set as default StorageClass\n",[241,1277,1278,1280,1283,1286,1289,1292,1294,1297],{"class":243,"line":275},[241,1279,1051],{"class":260},[241,1281,1282],{"class":264}," patch",[241,1284,1285],{"class":264}," storageclass",[241,1287,1288],{"class":264}," longhorn",[241,1290,1291],{"class":294}," -p",[241,1293,1029],{"class":313},[241,1295,1296],{"class":264},"{\"metadata\":{\"annotations\":{\"storageclass.kubernetes.io\u002Fis-default-class\":\"true\"}}}",[241,1298,1299],{"class":313},"'\n",[32,1301,1303],{"id":1302},"operations-and-monitoring","Operations and Monitoring",[46,1305,1307],{"id":1306},"cluster-health-checks","Cluster Health Checks",[231,1309,1311],{"className":233,"code":1310,"language":235,"meta":236,"style":236},"# Node status\nkubectl get nodes -o wide\n\n# System pod verification\nkubectl get pods -A\n\n# K3s service status\nsystemctl status k3s       # Server nodes\nsystemctl status k3s-agent # Worker nodes\n",[238,1312,1313,1318,1330,1334,1339,1351,1355,1360,1374],{"__ignoreMap":236},[241,1314,1315],{"class":243,"line":244},[241,1316,1317],{"class":247},"# Node status\n",[241,1319,1320,1322,1324,1326,1328],{"class":243,"line":251},[241,1321,1051],{"class":260},[241,1323,1054],{"class":264},[241,1325,1057],{"class":264},[241,1327,1060],{"class":294},[241,1329,1063],{"class":264},[241,1331,1332],{"class":243,"line":257},[241,1333,272],{"emptyLinePlaceholder":271},[241,1335,1336],{"class":243,"line":268},[241,1337,1338],{"class":247},"# System pod verification\n",[241,1340,1341,1343,1345,1348],{"class":243,"line":275},[241,1342,1051],{"class":260},[241,1344,1054],{"class":264},[241,1346,1347],{"class":264}," pods",[241,1349,1350],{"class":294}," -A\n",[241,1352,1353],{"class":243,"line":281},[241,1354,272],{"emptyLinePlaceholder":271},[241,1356,1357],{"class":243,"line":317},[241,1358,1359],{"class":247},"# K3s service status\n",[241,1361,1362,1365,1368,1371],{"class":243,"line":332},[241,1363,1364],{"class":260},"systemctl",[241,1366,1367],{"class":264}," status",[241,1369,1370],{"class":264}," k3s",[241,1372,1373],{"class":247},"       # Server nodes\n",[241,1375,1376,1378,1380,1383],{"class":243,"line":337},[241,1377,1364],{"class":260},[241,1379,1367],{"class":264},[241,1381,1382],{"class":264}," k3s-agent",[241,1384,1385],{"class":247}," # Worker nodes\n",[46,1387,1389],{"id":1388},"backup-and-recovery","Backup and Recovery",[11,1391,1392],{},"K3s automatically takes etcd snapshots, but manual backups are also important:",[231,1394,1396],{"className":233,"code":1395,"language":235,"meta":236,"style":236},"# Manual etcd snapshot\nk3s etcd-snapshot save --name manual-backup-$(date +%Y%m%d)\n\n# List snapshots\nk3s etcd-snapshot ls\n",[238,1397,1398,1403,1431,1435,1440],{"__ignoreMap":236},[241,1399,1400],{"class":243,"line":244},[241,1401,1402],{"class":247},"# Manual etcd snapshot\n",[241,1404,1405,1408,1411,1414,1416,1419,1422,1425,1428],{"class":243,"line":251},[241,1406,1407],{"class":260},"k3s",[241,1409,1410],{"class":264}," etcd-snapshot",[241,1412,1413],{"class":264}," save",[241,1415,295],{"class":294},[241,1417,1418],{"class":264}," manual-backup-",[241,1420,1421],{"class":313},"$(",[241,1423,1424],{"class":260},"date",[241,1426,1427],{"class":264}," +%Y%m%d",[241,1429,1430],{"class":313},")\n",[241,1432,1433],{"class":243,"line":257},[241,1434,272],{"emptyLinePlaceholder":271},[241,1436,1437],{"class":243,"line":268},[241,1438,1439],{"class":247},"# List snapshots\n",[241,1441,1442,1444,1446],{"class":243,"line":275},[241,1443,1407],{"class":260},[241,1445,1410],{"class":264},[241,1447,1448],{"class":264}," ls\n",[11,1450,1451,1452,1455],{},"To automate K3s cluster operations and achieve enterprise-grade reliability, ",[15,1453,29],{"href":27,"rel":1454},[19]," is the ideal solution.",[32,1457,1459],{"id":1458},"conclusion","Conclusion",[11,1461,1462],{},"Building a K3s cluster on Proxmox VE delivers a flexible, cost-effective Kubernetes environment. This guide covered efficient provisioning with VM templates, high availability configuration, distributed storage with Longhorn, and everything needed for production operations.",[11,1464,1465,1466,1469],{},"For advanced management capabilities and enterprise support, consider adopting ",[15,1467,716],{"href":714,"rel":1468},[19],". Even on Proxmox, Kubo On-Premise operates as fully managed K8s, handling cluster lifecycle management, auto-scaling, and security patching in a single integrated solution.",[11,1471,1472,1473,1478],{},"For more details, ",[15,1474,1477],{"href":1475,"rel":1476},"https:\u002F\u002Fwww.hexabase.com\u002Fcontact-us\u002F",[19],"contact us"," to discuss your requirements.",[11,1480,1481],{},[820,1482,1483],{},"Related Links:",[824,1485,1486,1492,1499,1506,1512,1518],{},[827,1487,1488],{},[15,1489,1491],{"href":41,"rel":1490},[19],"K3s Official Documentation",[827,1493,1494],{},[15,1495,1498],{"href":1496,"rel":1497},"https:\u002F\u002Fgithub.com\u002Fk3s-io\u002Fk3s",[19],"K3s GitHub Repository",[827,1500,1501],{},[15,1502,1505],{"href":1503,"rel":1504},"https:\u002F\u002Fpve.proxmox.com\u002Fpve-docs\u002F",[19],"Proxmox VE Documentation",[827,1507,1508],{},[15,1509,1511],{"href":1077,"rel":1510},[19],"MetalLB Official Site",[827,1513,1514],{},[15,1515,1517],{"href":1242,"rel":1516},[19],"Longhorn Storage",[827,1519,1520],{},[15,1521,1524],{"href":1522,"rel":1523},"https:\u002F\u002Fkubernetes.io\u002Fdocs\u002F",[19],"Kubernetes Official Documentation",[1526,1527,1528],"style",{},"html pre.shiki code .sbD-w, html code.shiki .sbD-w{--shiki-default:#51597D;--shiki-default-font-style:italic}html pre.shiki code .sE3pS, html code.shiki .sE3pS{--shiki-default:#C0CAF5}html pre.shiki code .sPY7s, html code.shiki .sPY7s{--shiki-default:#9ECE6A}html pre.shiki code .sOJ5S, html code.shiki .sOJ5S{--shiki-default:#FF9E64}html pre.shiki code .sT800, html code.shiki .sT800{--shiki-default:#E0AF68}html pre.shiki code .sAklC, html code.shiki .sAklC{--shiki-default:#89DDFF}html pre.shiki code .sGX4V, html code.shiki .sGX4V{--shiki-default:#A9B1D6}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}",{"title":236,"searchDepth":251,"depth":251,"links":1530},[1531,1535,1539,1545,1550,1554],{"id":34,"depth":251,"text":35,"children":1532},[1533,1534],{"id":48,"depth":257,"text":49},{"id":122,"depth":257,"text":123},{"id":221,"depth":251,"text":222,"children":1536},[1537,1538],{"id":228,"depth":257,"text":229},{"id":515,"depth":257,"text":516},{"id":720,"depth":251,"text":721,"children":1540},[1541,1542,1543,1544],{"id":724,"depth":257,"text":725},{"id":853,"depth":257,"text":854},{"id":913,"depth":257,"text":914},{"id":984,"depth":257,"text":985},{"id":1066,"depth":251,"text":1067,"children":1546},[1547,1548,1549],{"id":1070,"depth":257,"text":1071},{"id":1209,"depth":257,"text":1210},{"id":1236,"depth":257,"text":1237},{"id":1302,"depth":251,"text":1303,"children":1551},[1552,1553],{"id":1306,"depth":257,"text":1307},{"id":1388,"depth":257,"text":1389},{"id":1458,"depth":251,"text":1459},"2026-05-27","Complete guide to deploying a lightweight K3s Kubernetes cluster on Proxmox VE, covering VM templates, HA configuration, storage, and Ingress setup.","md","en",{},"\u002Fblog\u002Fen\u002Fk3s-on-proxmox-cluster",{"title":5,"description":1556},"blog\u002Fen\u002Fk3s-on-proxmox-cluster",[1407,1564,1565,1566,1567,1568,1569],"kubernetes","proxmox","self-hosting","containers","cluster","devops","sWCnpyTrVfGlFlLJGH4uSdU4e6dj9epuQXeVFEoho5c",[1572,1581,1589,1597,1605,1614],{"path":1573,"title":1574,"description":1575,"date":1576,"tags":1577},"\u002Fblog\u002Fen\u002Fk3s-proxmox-live-migration-etcd-quorum-affinity-design","Proxmox Live Migration Quietly Breaks K3s etcd Quorum: When Virtualization Collides with Raft","A deep dive into how live-migrating a K3s control plane VM on Proxmox can break etcd quorum, explained through heartbeat\u002Felection-timeout mechanics and Proxmox affinity design, with concrete operational countermeasures.","2026-09-09",[1407,1564,1565,1578,1579,1580],"etcd","live-migration","high-availability",{"path":1582,"title":1583,"description":1584,"date":1585,"tags":1586},"\u002Fblog\u002Fen\u002Fk3s-homelab-raspberry-pi-kubestronaut","Kubestronauts Broke Three Raspberry Pis Before They Ever Opened a Study Guide","The people who go from zero Kubernetes experience to Kubestronaut (holder of every CNCF certification) share one trait: they built a breakable K3s homelab before touching an exam prep book. Here's why.","2026-08-25",[1407,1564,1587,1588,1569],"kubestronaut","homelab",{"path":1590,"title":1591,"description":1592,"date":1593,"tags":1594},"\u002Fblog\u002Fen\u002Fkubernetes-operations-specialization-managed-k3s-hiring","eBPF, cert-manager, Service Mesh: Why Kubernetes Operations Outgrew What One Engineer Can Handle","Why do Kubernetes operations roles stay unfilled for months? It isn't a lack of tool knowledge — it's that the discipline has splintered into too many specialties. Instead of hiring more heads, absorb the specialization into the platform with managed K3s.","2026-08-21",[1407,1564,1595,1569,1596],"managed-kubernetes","platform-engineering",{"path":1598,"title":1599,"description":1600,"date":1601,"tags":1602},"\u002Fblog\u002Fen\u002Fkubernetes-gitops-branch-antipattern-fleet-scaling","Your dev\u002Fstaging\u002Fprod Branches Are a Time Bomb: Why Kubernetes GitOps Really Breaks","Splitting dev\u002Fstaging\u002Fproduction by Git branch is a GitOps anti-pattern that undermines Kubernetes' declarative foundations. Learn why drift happens, how to migrate to a directory-based, trunk-based setup, and how to design for fleet-scale growth.","2026-08-10",[1407,1564,1603,1604,1569],"gitops","argocd",{"path":1606,"title":1607,"description":1608,"date":1609,"tags":1610},"\u002Fblog\u002Fen\u002Fkubernetes-mlops-gpu-scheduling-talent-shortage","In the Age of AI-Written Code, Why Are Infrastructure Engineers Getting Raises? Inside the 'MLOps Talent Shortage' Fueled by the Corporate AI Adoption Rush","Generative AI has made it possible for almost anyone to write code, yet as more companies adopt AI, demand for MLOps talent who can reliably run GPUs and model serving on Kubernetes keeps rising. Here's why, and how a managed Kubernetes platform can help.","2026-07-30",[1564,1407,1611,1612,1613,1569],"mlops","ai-infrastructure","gpu-scheduling",{"path":1615,"title":1616,"description":1617,"date":1618,"tags":1619},"\u002Fblog\u002Fen\u002Fkubernetes-feature-flags-progressive-delivery-rollback","The More You Test, The More Production Breaks: Why Feature Flags Beat Monitoring in Kubernetes Operations","Stacking more QA tests doesn't reduce production incidents, because it's fundamentally impossible to enumerate every edge case in advance. This article explains the 'design for failure' mindset behind feature flags, monitoring, and automated rollback in Kubernetes, plus a practical adoption roadmap for K3s environments.","2026-07-24",[1407,1564,1620,1621,1569,1595],"feature-flags","progressive-delivery",1792488904409]