<?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>Webhook on inetshell</title><link>https://inet.sh/es/tags/webhook/</link><description>Recent content in Webhook on inetshell</description><generator>Hugo</generator><language>es</language><lastBuildDate>Sat, 26 Sep 2026 00:00:00 +0000</lastBuildDate><atom:link href="https://inet.sh/es/tags/webhook/index.xml" rel="self" type="application/rss+xml"/><item><title>Quitar Rancher de un clúster: cattle-system en Terminating, clústeres que no se dejan borrar, el webhook que bloquea todo y recuperar el admin</title><link>https://inet.sh/es/posts/kubernetes/rancher-limpiar-cattle-system-namespaces-terminating/</link><pubDate>Sat, 26 Sep 2026 00:00:00 +0000</pubDate><guid>https://inet.sh/es/posts/kubernetes/rancher-limpiar-cattle-system-namespaces-terminating/</guid><description>Después de desinstalar Rancher (o de que se rompa), cattle-system y cattle-fleet-system se quedan en Terminating por el finalizer controller.cattle.io/namespace-auth, los objetos Cluster no se dejan borrar, y los webhooks rancher.cattle.io rechazan cualquier cambio porque el pod que los atendía ya no existe. El job oficial rancher-cleanup para limpiar todo de una vez, la cirugía manual cuando solo quieres arreglar una cosa, y reset-password / ensure-default-admin cuando el problema es que no puedes entrar.</description><content:encoded><![CDATA[<h2 id="en-corto">En corto</h2>
<p>Para <strong>quitar Rancher del todo</strong> de un clúster donde estuvo instalado (irreversible, con backup hecho):</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">kubectl create -f https://raw.githubusercontent.com/rancher/rancher-cleanup/main/deploy/rancher-cleanup.yaml
</span></span><span class="line"><span class="cl">kubectl -n kube-system logs -l job-name<span class="o">=</span>cleanup-job -f
</span></span><span class="line"><span class="cl">kubectl create -f https://raw.githubusercontent.com/rancher/rancher-cleanup/main/deploy/verify.yaml
</span></span><span class="line"><span class="cl">kubectl -n kube-system logs -l job-name<span class="o">=</span>verify-job -f      <span class="c1"># debe salir vacío</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p>Para <strong>arreglar una sola cosa</strong> sin arrasar, lo que sigue.</p>
<h2 id="namespace-en-terminating">Namespace en Terminating</h2>
<p><code>cattle-system</code>, <code>cattle-fleet-system</code>, <code>cattle-impersonation-system</code>, <code>local</code>, los <code>cluster-fleet-*</code>, o cualquier namespace que Rancher creó, se quedan en <code>Terminating</code> para siempre:</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></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 ns cattle-system -o <span class="nv">jsonpath</span><span class="o">=</span><span class="s1">&#39;{.metadata.finalizers}{&#34;\n&#34;}{.spec.finalizers}{&#34;\n&#34;}{.status.conditions}{&#34;\n&#34;}&#39;</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p>Dos casos distintos:</p>
<ol>
<li>
<p><strong><code>metadata.finalizers</code> trae <code>controller.cattle.io/namespace-auth</code></strong> (o cualquier <code>*.cattle.io</code>). Lo puso Rancher y solo Rancher lo quita; si Rancher ya no está, nadie lo hará. Quítalo tú:</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></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 patch ns cattle-system --type<span class="o">=</span>merge -p <span class="s1">&#39;{&#34;metadata&#34;:{&#34;finalizers&#34;:[]}}&#39;</span>
</span></span></code></pre></td></tr></table>
</div>
</div></li>
<li>
<p><strong><code>spec.finalizers</code> trae <code>kubernetes</code> y <code>status.conditions</code> dice <code>SomeResourcesRemain</code> o <code>DiscoveryFailed</code></strong>. El API server no borra el namespace porque dentro quedan recursos, casi siempre CRs de un API group cuyo servicio desapareció (un <code>apiservice</code> de Rancher). Antes de forzar, mira qué es:</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">kubectl api-resources --verbs<span class="o">=</span>list --namespaced -o name <span class="se">\
</span></span></span><span class="line"><span class="cl"><span class="se"></span>  <span class="p">|</span> xargs -n1 kubectl -n cattle-system get --ignore-not-found --show-kind 2&gt;/dev/null
</span></span><span class="line"><span class="cl">kubectl get apiservice <span class="p">|</span> grep -v True        <span class="c1"># APIs muertas que rompen el discovery</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p>Borra el <code>apiservice</code> muerto o los CRs con finalizers, y el namespace cae solo. Forzar <code>spec.finalizers</code> a vacío es el último recurso y deja huérfanos:</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 ns cattle-system -o json <span class="p">|</span> jq <span class="s1">&#39;.spec.finalizers=[]&#39;</span> <span class="se">\
</span></span></span><span class="line"><span class="cl"><span class="se"></span>  <span class="p">|</span> kubectl replace --raw /api/v1/namespaces/cattle-system/finalize -f -
</span></span></code></pre></td></tr></table>
</div>
</div></li>
</ol>
<h2 id="clúster-que-no-se-puede-borrar">Clúster que no se puede borrar</h2>
<p>Un clúster importado que ya no existe se queda en <em>Removing</em> en la UI, o <code>kubectl delete</code> no termina. Son dos objetos con finalizers, uno por API:</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">kubectl -n fleet-default get clusters.provisioning.cattle.io
</span></span><span class="line"><span class="cl">kubectl -n fleet-default patch clusters.provisioning.cattle.io my-cluster --type<span class="o">=</span>merge -p <span class="s1">&#39;{&#34;metadata&#34;:{&#34;finalizers&#34;:[]}}&#39;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">kubectl get clusters.management.cattle.io          <span class="c1"># c-m-xxxxxxxx (v2.6+) o c-xxxxx</span>
</span></span><span class="line"><span class="cl">kubectl patch clusters.management.cattle.io c-m-xxxxxxxx --type<span class="o">=</span>merge -p <span class="s1">&#39;{&#34;metadata&#34;:{&#34;finalizers&#34;:[]}}&#39;</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p>Después limpia el namespace <code>cluster-fleet-default-&lt;nombre&gt;-&lt;hash&gt;</code> y los <code>clusters.fleet.cattle.io</code> que queden en <code>fleet-default</code>.</p>
<h2 id="el-webhook-que-rechaza-todo">El webhook que rechaza todo</h2>
<p><code>rancher-webhook</code> valida y muta recursos de <code>*.cattle.io</code> (y algunos de core, como namespaces y ServiceAccounts en clústeres gestionados). Si el pod no existe o está roto, cada cambio falla con:</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></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">Error from server (InternalError): Internal error occurred: failed calling webhook &#34;rancher.cattle.io&#34;: … connect: connection refused
</span></span></code></pre></td></tr></table>
</div>
</div><p>Exporta las configuraciones, bórralas, deja que el pod vuelva sano, y restáuralas:</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><span class="lnt">6
</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 validatingwebhookconfiguration rancher.cattle.io -o yaml &gt; vwc-rancher.yaml
</span></span><span class="line"><span class="cl">kubectl get mutatingwebhookconfiguration rancher.cattle.io -o yaml &gt; mwc-rancher.yaml
</span></span><span class="line"><span class="cl">kubectl delete validatingwebhookconfiguration rancher.cattle.io
</span></span><span class="line"><span class="cl">kubectl delete mutatingwebhookconfiguration rancher.cattle.io
</span></span><span class="line"><span class="cl"><span class="c1"># … arreglar rancher-webhook (kubectl -n cattle-system rollout restart deploy/rancher-webhook) …</span>
</span></span><span class="line"><span class="cl">kubectl apply -f vwc-rancher.yaml -f mwc-rancher.yaml
</span></span></code></pre></td></tr></table>
</div>
</div><p>Si estás desinstalando, no las restaures: son lo primero que hay que quitar para que el resto del borrado avance.</p>
<h2 id="recuperar-el-acceso">Recuperar el acceso</h2>
<p>Contraseña del admin perdida, o el usuario admin desactivado por error:</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">kubectl -n cattle-system <span class="nb">exec</span> -it deploy/rancher -- reset-password
</span></span><span class="line"><span class="cl"><span class="c1"># New password for default administrator (user-xxxxx): …</span>
</span></span><span class="line"><span class="cl">kubectl -n cattle-system <span class="nb">exec</span> -it deploy/rancher -- ensure-default-admin
</span></span></code></pre></td></tr></table>
</div>
</div><p><code>ensure-default-admin</code> reactiva el usuario y le devuelve el rol de administrador; <code>reset-password</code> solo cambia la contraseña.</p>
<h2 id="trampas">Trampas</h2>
<ul>
<li><strong><code>rancher-cleanup</code> borra los objetos de los clústeres aguas abajo</strong> (los clústeres siguen funcionando, pero dejan de estar registrados) y todo lo que Rancher instaló: monitoring, logging, Gatekeeper. Longhorn se queda. No lo lances en el clúster de Rancher que quieres conservar.</li>
<li><strong>Backup antes</strong>: <code>kubectl get -A -o yaml</code> de los <code>*.cattle.io</code> que te importen, o el backup-operator de Rancher. Los finalizers se quitan en un segundo; lo que había detrás no vuelve.</li>
<li><strong><code>kubectl delete ns --force --grace-period=0</code> no hace nada</strong> con un namespace en Terminating: el bloqueo está en los finalizers, no en el grace period.</li>
<li><strong>Rancher vuelve a poner los finalizers</strong> mientras esté vivo: si estás limpiando un clúster que todavía está conectado a un Rancher, desconéctalo primero (borra el <code>cattle-cluster-agent</code>) o los patches se deshacen solos.</li>
<li><strong>Los CRDs <code>*.cattle.io</code> sobreviven</strong> a una desinstalación por Helm; <code>rancher-cleanup</code> los quita, la desinstalación manual no.</li>
</ul>
<h2 id="ver-también">Ver también</h2>
<ul>
<li><a href="/es/posts/k3s/cluster-reset-perdida-de-quorum/">k3s: reset del clúster tras perder el quórum</a> — la otra cirugía de clúster que conviene tener a mano.</li>
<li><a href="https://github.com/rancher/rancher-cleanup">rancher-cleanup</a> y <a href="https://ranchermanager.docs.rancher.com/faq/technical-items">Technical FAQ de Rancher</a>.</li>
</ul>
]]></content:encoded></item><item><title>Vault Agent Injector en GKE privado: el sidecar no aparece y el pod tarda 30 s (el control plane no llega al webhook en el 8080)</title><link>https://inet.sh/es/posts/kubernetes/vault-agent-injector-gke-private-cluster-sin-sidecar/</link><pubDate>Sat, 26 Sep 2026 00:00:00 +0000</pubDate><guid>https://inet.sh/es/posts/kubernetes/vault-agent-injector-gke-private-cluster-sin-sidecar/</guid><description>En un clúster GKE privado, los pods con vault.hashicorp.com/agent-inject arrancan sin los contenedores vault-agent-init y vault-agent, tardan medio minuto más en crearse y el injector no registra ninguna petición. El control plane solo puede abrir conexiones a los nodos en los puertos 443 y 10250; el injector escucha en el 8080 y el webhook falla en silencio porque failurePolicy es Ignore. Regla de firewall desde el rango del control plane, cómo validar en los logs del injector, y el mismo problema en cualquier otro webhook de admisión.</description><content:encoded><![CDATA[<h2 id="en-corto">En corto</h2>
<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><span class="lnt">6
</span><span class="lnt">7
</span><span class="lnt">8
</span><span class="lnt">9
</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"><span class="nv">CLUSTER</span><span class="o">=</span>my-cluster<span class="p">;</span> <span class="nv">REGION</span><span class="o">=</span>us-central1<span class="p">;</span> <span class="nv">NETWORK</span><span class="o">=</span>my-vpc
</span></span><span class="line"><span class="cl"><span class="nv">MASTER_CIDR</span><span class="o">=</span><span class="k">$(</span>gcloud container clusters describe <span class="nv">$CLUSTER</span> --region <span class="nv">$REGION</span> <span class="se">\
</span></span></span><span class="line"><span class="cl"><span class="se"></span>  --format<span class="o">=</span><span class="s1">&#39;value(privateClusterConfig.masterIpv4CidrBlock)&#39;</span><span class="k">)</span>
</span></span><span class="line"><span class="cl"><span class="nv">NODE_TAG</span><span class="o">=</span><span class="k">$(</span>gcloud compute firewall-rules list --filter<span class="o">=</span><span class="s2">&#34;name~^gke-</span><span class="nv">$CLUSTER</span><span class="s2">&#34;</span> <span class="se">\
</span></span></span><span class="line"><span class="cl"><span class="se"></span>  --format<span class="o">=</span><span class="s1">&#39;value(targetTags.list())&#39;</span> <span class="p">|</span> head -1<span class="k">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">gcloud compute firewall-rules create gke-<span class="nv">$CLUSTER</span>-master-to-vault-injector <span class="se">\
</span></span></span><span class="line"><span class="cl"><span class="se"></span>  --network<span class="o">=</span><span class="nv">$NETWORK</span> --direction<span class="o">=</span>INGRESS --action<span class="o">=</span>ALLOW <span class="se">\
</span></span></span><span class="line"><span class="cl"><span class="se"></span>  --source-ranges<span class="o">=</span><span class="nv">$MASTER_CIDR</span> --target-tags<span class="o">=</span><span class="nv">$NODE_TAG</span> --rules<span class="o">=</span>tcp:8080
</span></span></code></pre></td></tr></table>
</div>
</div><p>Borra un pod anotado y comprueba que el injector recibe la llamada:</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">kubectl -n app delete pod -l <span class="nv">app</span><span class="o">=</span>api
</span></span><span class="line"><span class="cl">kubectl -n vault logs deploy/vault-agent-injector <span class="p">|</span> grep mutate
</span></span><span class="line"><span class="cl"><span class="c1"># [INFO]  handler: Request received: Method=POST URL=/mutate?timeout=30s</span>
</span></span><span class="line"><span class="cl">kubectl -n app get pod -l <span class="nv">app</span><span class="o">=</span>api -o <span class="nv">jsonpath</span><span class="o">=</span><span class="s1">&#39;{.items[0].spec.initContainers[*].name} {.items[0].spec.containers[*].name}{&#34;\n&#34;}&#39;</span>
</span></span><span class="line"><span class="cl"><span class="c1"># vault-agent-init api vault-agent</span>
</span></span></code></pre></td></tr></table>
</div>
</div><h2 id="el-síntoma">El síntoma</h2>
<ul>
<li>El pod lleva <code>vault.hashicorp.com/agent-inject: &quot;true&quot;</code> y el resto de anotaciones, pero arranca <strong>solo con el contenedor de la aplicación</strong>: ni <code>vault-agent-init</code> ni <code>vault-agent</code>.</li>
<li>Crear el pod <strong>tarda unos 30 segundos más</strong> de lo normal.</li>
<li><code>kubectl get events</code> no dice nada del webhook. En los logs del injector no hay ni una línea de <code>Request received</code>.</li>
<li>En otros clústeres (zonales públicos, kind, k3s) el mismo chart y las mismas anotaciones funcionan.</li>
</ul>
<h2 id="por-qué">Por qué</h2>
<p>En un clúster <strong>privado</strong> de GKE el control plane vive en una VPC de Google y llega a tus nodos a través de la regla de firewall que GKE crea sola (<code>gke-&lt;cluster&gt;-&lt;hash&gt;-master</code>). Esa regla solo permite <strong>TCP 443 y 10250</strong> desde el rango del control plane hacia los nodos. Todo lo demás está cerrado.</p>
<p>Un webhook de admisión no pasa por el Service como lo haría un cliente normal: el API server resuelve el Service a sus endpoints y <strong>conecta directamente con la IP del pod en el <code>targetPort</code></strong>. El Service del injector (<code>vault-agent-injector-svc</code>) publica el 443, pero el pod escucha en el <strong>8080</strong> (<code>injector.port</code> del chart), así que la conexión real es al 8080 y el firewall la descarta.</p>
<p>Lo que pasa después lo explican dos valores por defecto del chart de Vault:</p>
<table>
  <thead>
      <tr>
          <th>Valor</th>
          <th>Por defecto</th>
          <th>Efecto</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><code>injector.webhook.timeoutSeconds</code></td>
          <td><code>30</code></td>
          <td>El API server espera 30 s la respuesta del webhook</td>
      </tr>
      <tr>
          <td><code>injector.webhook.failurePolicy</code></td>
          <td><code>Ignore</code></td>
          <td>Si el webhook no contesta, el pod se crea <strong>sin mutar</strong>, sin error</td>
      </tr>
  </tbody>
</table>
<p>De ahí los 30 segundos de retraso y el pod sin sidecar y sin ningún mensaje. Con <code>failurePolicy: Fail</code> habrías visto <code>failed calling webhook &quot;vault.hashicorp.com&quot;: … context deadline exceeded</code> en los eventos del ReplicaSet, que al menos apunta al sitio correcto.</p>
<h2 id="no-es-solo-vault">No es solo Vault</h2>
<p>Cualquier webhook de admisión, conversión de CRDs o API agregada que escuche en un puerto que no sea 443 o 10250 falla igual en GKE privado: el operador de OpenTelemetry (9443), Kyverno (9443), Gatekeeper (8443)… cert-manager escucha en el <strong>10250</strong> precisamente para no necesitar esta regla. La documentación de GKE lo lista como requisito de &ldquo;admission webhooks, aggregated API servers, webhook conversion&rdquo;: una regla por puerto, desde <code>masterIpv4CidrBlock</code> hacia los tags de los nodos.</p>
<p>Si el clúster está en Terraform, deja la regla junto al clúster para que no se pierda al recrearlo:</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><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-hcl" data-lang="hcl"><span class="line"><span class="cl"><span class="k">resource</span> <span class="s2">&#34;google_compute_firewall&#34; &#34;master_to_vault_injector&#34;</span> {
</span></span><span class="line"><span class="cl"><span class="n">  name</span>          <span class="o">=</span> <span class="s2">&#34;gke-${google_container_cluster.main.name}-master-to-vault-injector&#34;</span>
</span></span><span class="line"><span class="cl"><span class="n">  network</span>       <span class="o">=</span> <span class="k">google_compute_network</span><span class="p">.</span><span class="k">main</span><span class="p">.</span><span class="k">name</span>
</span></span><span class="line"><span class="cl"><span class="n">  direction</span>     <span class="o">=</span> <span class="s2">&#34;INGRESS&#34;</span>
</span></span><span class="line"><span class="cl"><span class="n">  source_ranges</span> <span class="o">=</span> <span class="p">[</span><span class="k">google_container_cluster</span><span class="p">.</span><span class="k">main</span><span class="p">.</span><span class="k">private_cluster_config</span><span class="p">[</span><span class="m">0</span><span class="p">].</span><span class="k">master_ipv4_cidr_block</span><span class="p">]</span>
</span></span><span class="line"><span class="cl"><span class="n">  target_tags</span>   <span class="o">=</span> <span class="p">[</span><span class="s2">&#34;gke-${google_container_cluster.main.name}&#34;</span><span class="p">]</span><span class="c1">   # el tag que usan tus node pools
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>  <span class="k">allow</span> {
</span></span><span class="line"><span class="cl"><span class="n">    protocol</span> <span class="o">=</span> <span class="s2">&#34;tcp&#34;</span>
</span></span><span class="line"><span class="cl"><span class="n">    ports</span>    <span class="o">=</span> <span class="p">[</span><span class="s2">&#34;8080&#34;</span><span class="p">]</span>
</span></span><span class="line"><span class="cl">  }
</span></span><span class="line"><span class="cl">}
</span></span></code></pre></td></tr></table>
</div>
</div><h2 id="trampas">Trampas</h2>
<ul>
<li><strong>El tag equivocado</strong>: los nodos llevan <code>gke-&lt;cluster&gt;-&lt;hash&gt;-node</code>; cópialo de las reglas <code>gke-&lt;cluster&gt;-*</code> existentes en vez de escribirlo a mano. Con varios node pools, comprueba que todos tengan el tag.</li>
<li><strong>El rango del control plane cambia si recreas el clúster</strong>; una regla escrita a mano con el CIDR viejo deja de servir sin avisar.</li>
<li><strong><code>failurePolicy: Fail</code></strong> hace visible el fallo, pero mientras el webhook esté caído <strong>no se crea ningún pod</strong> en los namespaces que casen con el <code>namespaceSelector</code>; el chart excluye al propio injector, pero no a Vault si comparten namespace y etiquetas. Úsalo con <code>replicas: 2</code>.</li>
<li><strong>El injector sí recibe la petición y sigue sin sidecar</strong>: entonces ya no es red. Mira los logs de <code>vault-agent-init</code>: <code>permission denied</code> es el rol de Kubernetes auth (<code>bound_service_account_names</code>, <code>bound_service_account_namespaces</code>) o la política; <code>connection refused</code> es <code>vault.hashicorp.com/service</code> o la dirección de Vault.</li>
<li><strong>Un solo puerto por regla no escala</strong>: si acumulas webhooks, una regla con <code>--rules=tcp:8080,8443,9443</code> desde el control plane es más fácil de mantener que cinco.</li>
</ul>
<p>Referencias: <a href="https://github.com/hashicorp/vault-k8s/issues/46">vault-k8s #46</a>, <a href="https://github.com/hashicorp/vault-k8s/issues/32">vault-k8s #32</a> y <a href="https://docs.cloud.google.com/kubernetes-engine/docs/how-to/private-clusters">reglas de firewall en clústeres privados</a> en la documentación de GKE.</p>
<h2 id="ver-también">Ver también</h2>
<ul>
<li><a href="/es/posts/kubernetes/cert-manager-http01-308-ingressclassname/">cert-manager: el reto HTTP-01 devuelve 308</a> — otro componente que &ldquo;no hace nada&rdquo; hasta que miras el sitio correcto.</li>
<li><a href="/es/posts/gcp/github-actions-workload-identity-federation/">GitHub Actions → Google Cloud sin llaves</a> — para desplegar en ese GKE sin llaves JSON.</li>
</ul>
]]></content:encoded></item></channel></rss>