<?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>Helm-Diff on inetshell</title><link>https://inet.sh/es/tags/helm-diff/</link><description>Recent content in Helm-Diff 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/helm-diff/index.xml" rel="self" type="application/rss+xml"/><item><title>helmfile en producción: diff a tres bandas, 'already set in map', OCI 403, dependencias duplicadas y adoptar recursos que ya estaban desplegados</title><link>https://inet.sh/es/posts/kubernetes/helmfile-en-produccion-trucos/</link><pubDate>Sat, 26 Sep 2026 00:00:00 +0000</pubDate><guid>https://inet.sh/es/posts/kubernetes/helmfile-en-produccion-trucos/</guid><description>Lo que se aprende de helmfile después de meses de usarlo en CI: HELM_DIFF_THREE_WAY_MERGE para ver la deriva real del clúster, HELMFILE_GOCCY_GOYAML para el error &amp;#39;key already set in map&amp;#39;, --skip-diff-on-install para instalaciones enormes, el 403 de registros OCI que arregla un helm más nuevo, &amp;#39;more than one dependency with name or alias&amp;#39; por desajuste de versiones, filtrar por -l name=, y cómo hacer que Helm adopte recursos que se aplicaron con kubectl. Con los cambios de helmfile 1.x y Helm 4.</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></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="nb">export</span> <span class="nv">HELM_DIFF_THREE_WAY_MERGE</span><span class="o">=</span><span class="nb">true</span>        <span class="c1"># diff contra lo que hay en el clúster, no contra el último release</span>
</span></span><span class="line"><span class="cl"><span class="nb">export</span> <span class="nv">HELM_DIFF_NORMALIZE_MANIFESTS</span><span class="o">=</span><span class="nb">true</span>    <span class="c1"># quita ruido de formato del diff</span>
</span></span><span class="line"><span class="cl"><span class="nb">export</span> <span class="nv">HELMFILE_GOCCY_GOYAML</span><span class="o">=</span><span class="nb">true</span>            <span class="c1"># helmfile 0.x: evita &#34;key already set in map&#34;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">helmfile -e prod -l <span class="nv">name</span><span class="o">=</span>rabbitmq diff        <span class="c1"># una sola release</span>
</span></span><span class="line"><span class="cl">helmfile -e prod apply --skip-diff-on-install <span class="c1"># primera instalación gigante sin diff</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p>Y en CI, versiones fijas de las tres piezas (<code>helm</code>, <code>helmfile</code>, <code>helm-diff</code>): la mitad de los errores raros de helmfile son combinaciones que no se han probado juntas.</p>
<h2 id="los-errores-y-qué-los-arregla">Los errores y qué los arregla</h2>
<table>
  <thead>
      <tr>
          <th>Mensaje</th>
          <th>Causa</th>
          <th>Arreglo</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><code>helmfile diff</code> dice que no hay cambios, pero el clúster no coincide con el chart</td>
          <td>helm-diff compara el manifiesto del último release con el nuevo, no con el estado vivo; un <code>kubectl edit</code> a mano no aparece</td>
          <td><code>HELM_DIFF_THREE_WAY_MERGE=true</code> (o <code>--three-way-merge</code> en helm-diff)</td>
      </tr>
      <tr>
          <td>El diff está lleno de cambios de comillas, orden de claves e indentación</td>
          <td>Distintas versiones de Helm o del chart serializan distinto</td>
          <td><code>HELM_DIFF_NORMALIZE_MANIFESTS=true</code></td>
      </tr>
      <tr>
          <td><code>key &quot;image&quot; already set in map</code> al renderizar valores</td>
          <td>La librería YAML antigua no admite claves duplicadas ni ciertos anclajes en <code>values</code></td>
          <td><code>HELMFILE_GOCCY_GOYAML=true</code> en helmfile 0.x; helmfile 1.x ya usa esa librería</td>
      </tr>
      <tr>
          <td><code>Body is too long (maximum is 65536 characters)</code> o el job se eterniza en la primera instalación</td>
          <td>El diff de una instalación nueva es el chart entero, y el comentario en la PR o el log no lo aguantan</td>
          <td><code>--skip-diff-on-install</code></td>
      </tr>
      <tr>
          <td><code>Error: failed to authorize: … 403 Forbidden</code> al bajar un chart de <code>oci://ghcr.io/…</code></td>
          <td>Helm anterior a 3.8 con soporte OCI experimental, o sin <code>helm registry login</code></td>
          <td>Actualizar helm; <code>helm registry login ghcr.io</code> si el registro es privado</td>
      </tr>
      <tr>
          <td><code>Error: validation: more than one dependency with name or alias</code></td>
          <td>Desajuste entre helm y helmfile (helm 3.15 necesitó helmfile ≥ 0.164; helm 3.13 iba con 0.158)</td>
          <td>Actualizar helmfile a la par que helm; en 1.x ya no ocurre</td>
      </tr>
      <tr>
          <td>El diff sale sin color en CI</td>
          <td>helm-diff detecta que no hay TTY</td>
          <td><code>HELM_DIFF_COLOR=true</code></td>
      </tr>
  </tbody>
</table>
<h2 id="adoptar-recursos-que-ya-existen">Adoptar recursos que ya existen</h2>
<p>El caso típico: alguien instaló ArgoCD (o lo que sea) con <code>kubectl apply -f</code>, y ahora quieres que lo gestione una release de helmfile. Helm se niega a instalar sobre recursos que no son suyos (<code>rendered manifests contain a resource that already exists … invalid ownership metadata</code>). Desde Helm 3.2 basta con <strong>marcarlos como suyos</strong> antes de instalar:</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><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</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">NS</span><span class="o">=</span>argocd<span class="p">;</span> <span class="nv">REL</span><span class="o">=</span>argocd
</span></span><span class="line"><span class="cl"><span class="k">for</span> kind in deploy sts svc cm secret sa ingress role rolebinding networkpolicy<span class="p">;</span> <span class="k">do</span>
</span></span><span class="line"><span class="cl">  kubectl -n <span class="nv">$NS</span> get <span class="nv">$kind</span> -o name 2&gt;/dev/null <span class="p">|</span> <span class="k">while</span> <span class="nb">read</span> -r r<span class="p">;</span> <span class="k">do</span>
</span></span><span class="line"><span class="cl">    kubectl -n <span class="nv">$NS</span> label <span class="s2">&#34;</span><span class="nv">$r</span><span class="s2">&#34;</span> app.kubernetes.io/managed-by<span class="o">=</span>Helm --overwrite
</span></span><span class="line"><span class="cl">    kubectl -n <span class="nv">$NS</span> annotate <span class="s2">&#34;</span><span class="nv">$r</span><span class="s2">&#34;</span> meta.helm.sh/release-name<span class="o">=</span><span class="nv">$REL</span> meta.helm.sh/release-namespace<span class="o">=</span><span class="nv">$NS</span> --overwrite
</span></span><span class="line"><span class="cl">  <span class="k">done</span>
</span></span><span class="line"><span class="cl"><span class="k">done</span>
</span></span><span class="line"><span class="cl"><span class="c1"># recursos de clúster: mismas etiquetas, sin -n</span>
</span></span><span class="line"><span class="cl"><span class="k">for</span> r in <span class="k">$(</span>kubectl get crd,clusterrole,clusterrolebinding -o name <span class="p">|</span> grep -i argo<span class="k">)</span><span class="p">;</span> <span class="k">do</span>
</span></span><span class="line"><span class="cl">  kubectl label <span class="s2">&#34;</span><span class="nv">$r</span><span class="s2">&#34;</span> app.kubernetes.io/managed-by<span class="o">=</span>Helm --overwrite
</span></span><span class="line"><span class="cl">  kubectl annotate <span class="s2">&#34;</span><span class="nv">$r</span><span class="s2">&#34;</span> meta.helm.sh/release-name<span class="o">=</span><span class="nv">$REL</span> meta.helm.sh/release-namespace<span class="o">=</span><span class="nv">$NS</span> --overwrite
</span></span><span class="line"><span class="cl"><span class="k">done</span>
</span></span><span class="line"><span class="cl">helmfile -e prod -l <span class="nv">name</span><span class="o">=</span><span class="nv">$REL</span> diff     <span class="c1"># debería ser casi vacío</span>
</span></span><span class="line"><span class="cl">helmfile -e prod -l <span class="nv">name</span><span class="o">=</span><span class="nv">$REL</span> apply
</span></span></code></pre></td></tr></table>
</div>
</div><p>Solo marca lo que el chart va a renderizar: un recurso etiquetado que el chart no incluye no pasa nada, pero uno que el chart renderiza con otro nombre acaba duplicado.</p>
<h2 id="helmfile-1x-y-helm-4">helmfile 1.x y Helm 4</h2>
<p>Si vienes de 0.x, esto es lo que cambia al actualizar:</p>
<ul>
<li>Un <code>helmfile.yaml</code> con plantillas Go tiene que llamarse <strong><code>helmfile.yaml.gotmpl</code></strong>; el <code>.yaml</code> a secas ya no se renderiza.</li>
<li><code>environments:</code> y <code>releases:</code> van en <strong>partes separadas por <code>---</code></strong> dentro del mismo archivo.</li>
<li><code>helmfile delete</code> desaparece (es <code>destroy</code>), <code>helmfile charts</code> también, y <code>--args</code> se elimina.</li>
<li><code>HELMFILE_SKIP_INSECURE_TEMPLATE_FUNCTIONS</code> pasa a ser <code>HELMFILE_DISABLE_INSECURE_FEATURES</code>.</li>
<li>helmfile 1.x funciona con <strong>Helm 3 y Helm 4</strong>. Con Helm 4, instala helm-diff con <code>helm plugin install https://github.com/databus23/helm-diff --verify=false</code> (Helm 4 verifica la procedencia de los plugins y helm-diff no la publica).</li>
</ul>
<h2 id="trampas">Trampas</h2>
<ul>
<li><strong><code>apply</code> sin diff previo en CI</strong>: <code>helmfile apply</code> ya hace el diff y solo aplica si hay cambios; <code>sync</code> aplica siempre. En pipelines, <code>diff</code> en la PR y <code>apply</code> en main.</li>
<li><strong><code>installed: false</code></strong> desinstala la release en el siguiente <code>apply</code>; útil para retirar cosas por Git, peligroso si lo copias de otro entorno.</li>
<li><strong>Secretos en <code>values</code></strong>: helmfile los deja en el manifiesto del release (Secret de Helm en el namespace); usa <code>helm-secrets</code> con SOPS o referencias externas.</li>
<li><strong><code>--skip-diff-on-install</code> no es <code>--skip-diff</code></strong>: solo se salta el diff en releases que aún no existen. Las actualizaciones siguen mostrando su diff.</li>
<li><strong>Tres binarios, tres versiones</strong>: <code>helm version</code>, <code>helmfile version</code> y <code>helm plugin list</code> en el primer paso del pipeline, y en la imagen de CI fijadas por tag.</li>
</ul>
<p>Referencias: <a href="https://github.com/databus23/helm-diff">helm-diff</a>, <a href="https://helmfile.readthedocs.io/">helmfile</a> y <a href="https://github.com/helmfile/helmfile/blob/main/docs/proposals/towards-1.0.md">la propuesta de cambios para 1.0</a>.</p>
<h2 id="ver-también">Ver también</h2>
<ul>
<li><a href="/es/posts/k3s/importar-imagenes-sin-registry/">k3s: importar imágenes sin registro</a> — cuando la release depende de una imagen que no está en ningún registro.</li>
</ul>
]]></content:encoded></item></channel></rss>