<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>Ha on inetshell</title><link>https://inet.sh/es/tags/ha/</link><description>Recent content in Ha on inetshell</description><generator>Hugo</generator><language>es</language><lastBuildDate>Fri, 25 Sep 2026 00:00:00 +0000</lastBuildDate><atom:link href="https://inet.sh/es/tags/ha/index.xml" rel="self" type="application/rss+xml"/><item><title>k3s: recuperar un clúster HA con etcd embebido que perdió el quórum (--cluster-reset)</title><link>https://inet.sh/es/posts/k3s/cluster-reset-perdida-de-quorum/</link><pubDate>Fri, 25 Sep 2026 00:00:00 +0000</pubDate><guid>https://inet.sh/es/posts/k3s/cluster-reset-perdida-de-quorum/</guid><description>Cuando dos de tres servidores k3s con etcd embebido mueren, la API deja de responder. k3s server --cluster-reset convierte al superviviente en el único miembro de etcd conservando sus datos; los demás servidores borran su db y se vuelven a unir. También cómo restaurar desde un snapshot con --cluster-reset-restore-path, qué pasa con el token, y cómo evitar montar dos clústeres sin querer.</description><content:encoded><![CDATA[<h2 id="en-corto">En corto</h2>
<p>En <strong>un solo</strong> servidor, el que tenga los datos más recientes:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl">systemctl stop k3s
</span></span><span class="line"><span class="cl">k3s server --cluster-reset
</span></span><span class="line"><span class="cl"><span class="c1"># ... termina con:</span>
</span></span><span class="line"><span class="cl"><span class="c1"># Managed etcd cluster membership has been reset, restart without --cluster-reset flag now</span>
</span></span><span class="line"><span class="cl">systemctl start k3s
</span></span></code></pre></td></tr></table>
</div>
</div><p>En <strong>cada uno de los otros servidores</strong>, con su <code>/etc/rancher/k3s/config.yaml</code> apuntando al que reseteaste (<code>server: https://node1:6443</code>):</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl">systemctl stop k3s
</span></span><span class="line"><span class="cl">rm -rf /var/lib/rancher/k3s/server/db
</span></span><span class="line"><span class="cl">systemctl start k3s
</span></span></code></pre></td></tr></table>
</div>
</div><p>Los agentes no necesitan nada; se reconectan solos.</p>
<h2 id="cuándo-hace-falta">Cuándo hace falta</h2>
<p>etcd necesita mayoría: con tres servidores, dos vivos; con cinco, tres. Si pierdes la mayoría (dos nodos muertos, una partición de red, un cambio de IPs a la vez, un intento de quitar nodos a mano), el que queda no puede escribir y la API se congela:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">kubectl get nodes
</span></span><span class="line"><span class="cl">Error from server: etcdserver: request timed out
</span></span></code></pre></td></tr></table>
</div>
</div><p>En <code>journalctl -u k3s</code> verás <code>etcd cluster join failed</code>, <code>failed to get raft status</code> o <code>waiting for etcd quorum</code>. <code>--cluster-reset</code> es la salida que documenta k3s para exactamente esto.</p>
<h2 id="qué-hace---cluster-reset">Qué hace <code>--cluster-reset</code></h2>
<p>Reescribe la lista de miembros de etcd para que el nodo actual sea <strong>el único</strong>, conservando todos sus datos (los objetos de Kubernetes, secretos, todo). No toca los pods ni los agentes. Lo único que se pierde son escrituras que no alcanzaron a replicarse a este nodo antes de la caída, que en la práctica son pocas o ninguna si eliges el que estaba más al día.</p>
<p>Con <code>--cluster-reset-restore-path</code> hace lo mismo pero <strong>sustituye</strong> los datos por los de un snapshot; todo lo posterior al snapshot desaparece.</p>
<h2 id="paso-a-paso">Paso a paso</h2>
<ol>
<li>
<p><strong>Elige el nodo.</strong> Si varios servidores siguen vivos pero sin quórum, quédate con el que tenga el snapshot o el <code>db</code> más reciente: <code>ls -la /var/lib/rancher/k3s/server/db/</code> y <code>k3s etcd-snapshot ls</code>.</p>
</li>
<li>
<p><strong>Guarda una copia por si acaso</strong>, incluido el token:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl">cp -a /var/lib/rancher/k3s/server/db /root/k3s-db-<span class="k">$(</span>date +%F<span class="k">)</span>
</span></span><span class="line"><span class="cl">cp /var/lib/rancher/k3s/server/token /root/k3s-token
</span></span></code></pre></td></tr></table>
</div>
</div></li>
<li>
<p><strong>Resetea y arranca</strong> (el bloque del En corto). El comando tarda unos segundos; no lo interrumpas.</p>
</li>
<li>
<p><strong>Comprueba</strong> que la API responde y que el nodo es el único miembro de etcd:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl">kubectl get nodes -o wide
</span></span><span class="line"><span class="cl">kubectl get nodes -l node-role.kubernetes.io/etcd<span class="o">=</span><span class="nb">true</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p>Los otros servidores saldrán <code>NotReady</code> hasta que se unan; los agentes vuelven a <code>Ready</code> solos.</p>
</li>
<li>
<p><strong>Revisa la configuración de los demás servidores antes de arrancarlos.</strong> El primer nodo del clúster suele tener <code>cluster-init: true</code> y <strong>ningún</strong> <code>server:</code>; si reseteaste otro nodo, ese primero arrancaría un clúster nuevo por su cuenta. Asegúrate de que todos los que se van a unir tienen:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="c"># /etc/rancher/k3s/config.yaml</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="nt">server</span><span class="p">:</span><span class="w"> </span><span class="l">https://node1:6443    </span><span class="w"> </span><span class="c"># el nodo reseteado (o el VIP, si apunta a él)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="nt">token</span><span class="p">:</span><span class="w"> </span><span class="l">&lt;el mismo token&gt;</span><span class="w">
</span></span></span></code></pre></td></tr></table>
</div>
</div></li>
<li>
<p><strong>Únelos uno a uno</strong>: stop, borrar <code>server/db</code>, start. Cada uno entra como <em>learner</em> y tarda uno o dos minutos en ser miembro pleno; espera a que aparezca <code>Ready</code> antes del siguiente.</p>
</li>
<li>
<p><strong>Snapshot nuevo</strong> cuando todo esté verde: <code>k3s etcd-snapshot save --name post-reset</code>.</p>
</li>
</ol>
<h2 id="restaurar-desde-un-snapshot">Restaurar desde un snapshot</h2>
<p>Si el <code>db</code> del superviviente está corrupto o quieres volver a un punto anterior:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl">k3s etcd-snapshot ls
</span></span><span class="line"><span class="cl">systemctl stop k3s
</span></span><span class="line"><span class="cl">k3s server --cluster-reset --cluster-reset-restore-path<span class="o">=</span>/var/lib/rancher/k3s/server/db/snapshots/etcd-snapshot-node1-1758760000
</span></span><span class="line"><span class="cl">systemctl start k3s
</span></span></code></pre></td></tr></table>
</div>
</div><p>Y después, el mismo rejoin de los demás servidores. Por defecto k3s guarda un snapshot cada 12 horas (<code>0 */12 * * *</code>) y conserva 5, en <code>/var/lib/rancher/k3s/server/db/snapshots</code>; <code>--etcd-s3</code> los manda a S3.</p>
<h2 id="trampas">Trampas</h2>
<ul>
<li><strong>Nunca en dos nodos.</strong> <code>--cluster-reset</code> en dos servidores da dos clústeres con el mismo nombre y agentes confundidos entre ambos. Uno resetea, el resto se une.</li>
<li><strong>El token manda.</strong> El snapshot lleva los certificados y las llaves de cifrado protegidos con el token del clúster. Restaurar en un nodo nuevo sin el mismo token (<code>--token</code>) no arranca. Guarda <code>/var/lib/rancher/k3s/server/token</code> fuera del clúster.</li>
<li><strong>SQLite no tiene esto.</strong> Un servidor único sin etcd no necesita ni acepta <code>--cluster-reset</code>; su backup es copiar <code>/var/lib/rancher/k3s/server/db/</code>.</li>
<li><strong><code>cluster-init</code> huérfano</strong> en un nodo que se va a reunir es la forma más fácil de acabar con dos clústeres. Revisa el punto 5.</li>
<li><strong>Balanceador o VIP delante de los servidores</strong>: si apunta a un nodo muerto, los agentes tampoco vuelven; revísalo antes de culpar a etcd.</li>
</ul>
<p>Referencia: <a href="https://docs.k3s.io/cli/etcd-snapshot">etcd-snapshot</a> y <a href="https://docs.k3s.io/datastore/backup-restore">Backup and Restore</a> en la documentación de k3s.</p>
]]></content:encoded></item></channel></rss>