<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>Resizes Blog</title><link>https://resiz.es/blog</link><description>Notes from the Resizes team</description><language>en</language><item><title>Ingress NGINX is retiring — how we cut over to Envoy Gateway in 3 days (without downtime)</title><link>https://resiz.es/blog/ingress-to-gateway-migration</link><guid isPermaLink="false">https://blog.resiz.es/ingress-to-gateway-migration</guid><pubDate>Tue, 01 Sep 2026 00:00:00 GMT</pubDate><description>SIG Network retires Ingress NGINX in March 2026. Scope, the oauth2-proxy bugs we caught before DNS moved, what ingress2gateway does not cover, and how Resizes runs the same cutover for you.</description><content:encoded>&lt;p&gt;Most organizations do not have an &lt;strong&gt;ingress strategy&lt;/strong&gt;. They have NGINX controllers that grew with the cluster — snippet annotations, oauth2-proxy in front of internal tools, cert-manager secrets in app namespaces — and a &lt;a href=&quot;https://kubernetes.io/blog/2025/11/11/ingress-nginx-retirement/&quot;&gt;March 2026 deadline&lt;/a&gt; that is not on anyone&#39;s roadmap yet.&lt;/p&gt;
&lt;p&gt;At &lt;strong&gt;&lt;a href=&quot;https://resiz.es/&quot;&gt;Resizes&lt;/a&gt;&lt;/strong&gt;, we migrated production traffic on EKS from Ingress NGINX to &lt;strong&gt;&lt;a href=&quot;https://gateway.envoyproxy.io/&quot;&gt;Envoy Gateway&lt;/a&gt;&lt;/strong&gt;: &lt;strong&gt;dual-run&lt;/strong&gt;, canary DNS per hostname, NGINX left up until each host was proven on Envoy.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Three days&lt;/strong&gt; is the &lt;strong&gt;DNS cutover window&lt;/strong&gt;, not the full program. Platform design, Envoy Gateway rollout, and our migration toolkit came first. Those three days were lane conversion, GitOps merges, and moving ~50 hostnames — &lt;strong&gt;no user-visible outage&lt;/strong&gt;, &lt;strong&gt;no DNS rollback&lt;/strong&gt;, &lt;strong&gt;no incidents filed in our change log&lt;/strong&gt;. We scaled NGINX down about a week later, after soak.&lt;/p&gt;
&lt;!--truncate--&gt;
&lt;hr&gt;
&lt;h2 id=&quot;scope&quot; tabindex=&quot;-1&quot;&gt;Scope&lt;/h2&gt;
&lt;div class=&quot;blog-table&quot; role=&quot;region&quot; aria-label=&quot;Article table&quot; tabindex=&quot;0&quot;&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Cluster&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;One production EKS estate&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Traffic lanes&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;3 (&lt;code&gt;IngressClass&lt;/code&gt;: internal, external, custom)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Ingress objects&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;~40 across all lanes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Hostnames on Envoy&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;~50 (multi-host Ingresses, per-customer TLS on custom)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;GitOps&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Argo CD; HTTPRoutes in each app&#39;s &lt;code&gt;templates/&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Team&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;2–3 platform engineers; app teams unchanged&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;Zero downtime&lt;/strong&gt; meant users always hit a working endpoint. We did not remove NGINX for a hostname until Envoy passed auth, TLS, and path checks — tested with &lt;code&gt;curl --resolve&lt;/code&gt; while DNS still pointed at NGINX.&lt;/p&gt;
&lt;p&gt;Gateways and NLBs were live in dual-run &lt;strong&gt;before&lt;/strong&gt; the first DNS change. The three-day window was only the DNS moves.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;kubectl get pods --all-namespaces \
  --selector app.kubernetes.io/name=ingress-nginx
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If that returns controllers, you have a deadline. After March 2026 there are no security patches — see &lt;a href=&quot;https://kubernetes.io/blog/2025/11/11/ingress-nginx-retirement/&quot;&gt;SIG Network&#39;s announcement&lt;/a&gt; for context.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&quot;the-migration-that-almost-shipped-broken-oauth2-proxy&quot; tabindex=&quot;-1&quot;&gt;The migration that almost shipped broken (oauth2-proxy)&lt;/h2&gt;
&lt;p&gt;ingress2gateway alone was not enough. The wake-up call was an &lt;strong&gt;internal app behind oauth2-proxy&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;NGINX used &lt;code&gt;auth-url&lt;/code&gt; and &lt;code&gt;auth-response-headers&lt;/code&gt;. The HTTPRoute looked fine in Git. Against the new Gateway with &lt;code&gt;curl --resolve&lt;/code&gt; — &lt;strong&gt;before&lt;/strong&gt; DNS — we hit:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;401 on APIs&lt;/strong&gt; — backend expected &lt;code&gt;X-Auth-Request-Email&lt;/code&gt;; Envoy was not forwarding extAuth headers like NGINX.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;202 from extAuth&lt;/strong&gt; — oauth2-proxy&#39;s &lt;code&gt;/oauth2/auth&lt;/code&gt; returns 202; Envoy Gateway only accepts &lt;strong&gt;200&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;405 on POST&lt;/strong&gt; — traffic went through oauth2-proxy instead of the frontend Service.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;None of that shows up in &lt;code&gt;kubectl get httproute&lt;/code&gt;. All of it would have been a production incident after a DNS flip.&lt;/p&gt;
&lt;p&gt;The pattern we reuse:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;HTTPRoute → &lt;strong&gt;application&lt;/strong&gt; Service, not oauth2-proxy&lt;/li&gt;
&lt;li&gt;&lt;code&gt;SecurityPolicy&lt;/code&gt; extAuth → oauth2-proxy with &lt;strong&gt;&lt;code&gt;upstreams: [&quot;static://200&quot;]&lt;/code&gt;&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Test session cookies and API calls &lt;strong&gt;before&lt;/strong&gt; ExternalDNS hands off the name&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In every estate we have assessed, at least one of &lt;strong&gt;auth-url&lt;/strong&gt;, &lt;strong&gt;snippets&lt;/strong&gt;, or &lt;strong&gt;per-host TLS&lt;/strong&gt; needed work beyond ingress2gateway.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&quot;ingress2gateway-is-the-converter--not-the-migration&quot; tabindex=&quot;-1&quot;&gt;ingress2gateway is the converter — not the migration&lt;/h2&gt;
&lt;p&gt;We still start with &lt;strong&gt;&lt;a href=&quot;https://github.com/kubernetes-sigs/ingress2gateway&quot;&gt;ingress2gateway&lt;/a&gt;&lt;/strong&gt;. Plain apps get a useful HTTPRoute draft.&lt;/p&gt;
&lt;p&gt;Production also needs platform manifests (Gateway + NLB per &lt;code&gt;IngressClass&lt;/code&gt;), conversion from &lt;strong&gt;live&lt;/strong&gt; Ingress (not Helm templates in Git), post-processing (&lt;code&gt;parentRefs&lt;/code&gt;, ExternalDNS, cert-manager, extAuth, &lt;code&gt;X-Forwarded-Proto&lt;/code&gt;), GitOps promotion into app charts, and a &lt;strong&gt;triage report&lt;/strong&gt; per lane.&lt;/p&gt;
&lt;p&gt;That is what our &lt;strong&gt;closed-source toolkit&lt;/strong&gt; delivers on a Resizes engagement: discovery + lane design, platform manifests, per-lane convert and report, promotion PRs into your GitOps repo, and a cutover runbook.&lt;/p&gt;
&lt;h3 id=&quot;conversion-report-excerpt&quot; tabindex=&quot;-1&quot;&gt;Conversion report (excerpt)&lt;/h3&gt;
&lt;p&gt;Full estate: &lt;strong&gt;~40 Ingress&lt;/strong&gt;. One lane (custom): 18 snapshots → 61 resources. ingress2gateway warnings + toolkit follow-ups, anonymized:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;Lane: custom
Input Ingress snapshots: 18
Output resources kept: 61
Dropped (platform-owned Gateway): 18

WARN  Unsupported annotation nginx.ingress.kubernetes.io/configuration-snippet
      object: Ingress: acme-cms/acme-wordpress
WARN  Unsupported annotation nginx.ingress.kubernetes.io/server-snippet
      object: Ingress: acme-cms/acme-wordpress
WARN  Unsupported annotation nginx.ingress.kubernetes.io/force-ssl-redirect
      object: Ingress: saas-app/saas-app-main

INFO  nginx auth-url → SecurityPolicy extAuth oauth2-proxy:4180
INFO  RequestHeaderModifier X-Forwarded-Proto=https (TLS terminated before Envoy)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;One CMS needed snippet logic translated manually — deny a path, proxy assets externally, serve the rest in-cluster — into HTTPRoute rules, a direct-response filter, and Envoy &lt;code&gt;Backend&lt;/code&gt; resources. Custom-lane TLS needed per-host SNI, &lt;code&gt;ReferenceGrant&lt;/code&gt; per namespace, and the right NLB &lt;code&gt;targetPort&lt;/code&gt;. Test with real hostnames and SNI, not the raw NLB URL.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&quot;cutover-without-downtime&quot; tabindex=&quot;-1&quot;&gt;Cutover without downtime&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;NGINX and Envoy ran together&lt;/strong&gt; until each hostname moved.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Envoy Gateway + Gateways up; &lt;strong&gt;new NLB per lane&lt;/strong&gt;; DNS still on NGINX.&lt;/li&gt;
&lt;li&gt;HTTPRoutes synced via GitOps.&lt;/li&gt;
&lt;li&gt;Validate each host from VPC/VPN — DNS unchanged. Lower TTL to ~60s in the week before if you can:&lt;/li&gt;
&lt;/ol&gt;
&lt;pre tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;NEW_LB=&amp;lt;gateway-internal-….elb.region.amazonaws.com&amp;gt;

curl -vk --resolve app.internal.example.com:443:&lt;span class=&quot;hljs-variable&quot;&gt;${NEW_LB}&lt;/span&gt; \
  https://app.internal.example.com/
&lt;/code&gt;&lt;/pre&gt;
&lt;ol start=&quot;4&quot;&gt;
&lt;li&gt;Move &lt;strong&gt;one hostname&lt;/strong&gt; — ExternalDNS handoff (one owner per name) or manual alias.&lt;/li&gt;
&lt;li&gt;Soak; repeat. Internal first; auth-heavy and customer-facing after.&lt;/li&gt;
&lt;li&gt;Wildcard records last.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;With ExternalDNS &lt;code&gt;policy: sync&lt;/code&gt;, add &lt;code&gt;gateway-httproute&lt;/code&gt; as a source and copy &lt;code&gt;managed-by&lt;/code&gt; / hostname annotations to HTTPRoutes. Rollback: point the alias back at the NGINX NLB.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&quot;why-envoy-gateway&quot; tabindex=&quot;-1&quot;&gt;Why Envoy Gateway&lt;/h2&gt;
&lt;p&gt;SIG Network points to &lt;strong&gt;Gateway API&lt;/strong&gt;. We picked &lt;strong&gt;Envoy Gateway&lt;/strong&gt; because ingress2gateway emits it, we needed north-south routing without a mesh, and policy CRDs cover extAuth and backends without snippets. Cilium Gateway, AWS Gateway API Controller, or Kong may fit you better; for our three-lane EKS estate with heavy annotation debt, Envoy Gateway was what we could ship.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&quot;the-3-day-dns-window&quot; tabindex=&quot;-1&quot;&gt;The 3-day DNS window&lt;/h2&gt;
&lt;div class=&quot;blog-table&quot; role=&quot;region&quot; aria-label=&quot;Article table&quot; tabindex=&quot;0&quot;&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Day&lt;/th&gt;
&lt;th&gt;Work&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;1&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Lane converts; report triaged; oauth2-proxy + TLS on internal canaries via &lt;code&gt;--resolve&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;2&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;GitOps PRs merged; DNS handoffs on internal + external; ExternalDNS checked&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;3&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Custom lane DNS; all ~50 hostnames on Envoy&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;
&lt;div class=&quot;blog-table&quot; role=&quot;region&quot; aria-label=&quot;Article table&quot; tabindex=&quot;0&quot;&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;DNS cutover&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;3 days&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;User-visible outages / rollbacks&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;0&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;NGINX removed&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;~1 week later&lt;/strong&gt; (24–48h soak per lane)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;Next time:&lt;/strong&gt; drop TTL on all canary zones a week ahead; finish snippet translations before DNS week; consider weighted Route53 on the first external host.&lt;/p&gt;
&lt;p&gt;This timeline assumes Envoy Gateway, Gateways, and NLBs were already running in dual-run — platform and toolkit in place, as in our case.&lt;/p&gt;
&lt;p&gt;Repeatable sequence: &lt;strong&gt;convert → report → fix → PR → &lt;code&gt;--resolve&lt;/code&gt; → DNS → soak → decommission&lt;/strong&gt;.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&quot;after-cutover&quot; tabindex=&quot;-1&quot;&gt;After cutover&lt;/h2&gt;
&lt;p&gt;Patchable control plane past March 2026. Routing in reviewable CRDs instead of snippets. New hosts follow HTTPRoute templates instead of copied nginx annotations. Dual-run costs a few hundred dollars per month on AWS until NGINX is gone per lane; steady state is similar. What you skip is the emergency migration when patches stop.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&quot;how-we-run-this-for-you&quot; tabindex=&quot;-1&quot;&gt;How we run this for you&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Discovery&lt;/strong&gt; — inventory, annotation scan, lane design → migration map and cutover estimate.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Platform&lt;/strong&gt; — Envoy alongside NGINX.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Convert + GitOps&lt;/strong&gt; — cluster-first convert, report triage, PRs into your Argo &lt;code&gt;templates/&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Cutover + handover&lt;/strong&gt; — canary DNS, soak, NGINX decommission.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;We will say wait if you are ALB-only, Ingress count is tiny with accepted risk, or nginx behavior has no Gateway API equivalent.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://resiz.es/&quot;&gt;Contact us&lt;/a&gt; for a short discovery — retirement check, annotation scan, and a cutover timeline for your environment.&lt;/p&gt;
</content:encoded></item><item><title>One message, dozens of calls: how we measured and cut agent-chat spend</title><link>https://resiz.es/blog/one-message-dozens-of-calls</link><guid isPermaLink="false">https://blog.resiz.es/one-message-dozens-of-calls</guid><pubDate>Thu, 20 Aug 2026 00:00:00 GMT</pubDate><description>A chat message is not one request — it is a loop of model calls. How we attributed LiteLLM spend, saw the whole proxy in Grafana, and cut tokens without breaking the agent.</description><content:encoded>&lt;p&gt;LiteLLM isn&#39;t an infrastructure detail. It&#39;s the money bottleneck for almost everything we do with models: the Resizes AI chat, customer agents, internal pipelines. When the bill went up, the instinct was &quot;the chat is expensive.&quot; The truth was broader: a shared proxy, no map, and an agent that turns one message into a loop of calls.&lt;/p&gt;
&lt;p&gt;This post covers how we saw it, how we almost broke it by blindly cutting turns, and what ended up in code: per-agent and per-conversation attribution, less context, fewer tools, a real cap in the runtime, and a Grafana dashboard covering everything that goes through LiteLLM.&lt;/p&gt;
&lt;!--truncate--&gt;
&lt;h2 id=&quot;the-symptom&quot; tabindex=&quot;-1&quot;&gt;The symptom&lt;/h2&gt;
&lt;p&gt;In private beta the chat felt like it was &quot;thinking too much&quot;: endless statuses, extra tool calls, sometimes a 502 mid-task. In parallel, LiteLLM spend didn&#39;t line up with user traffic.&lt;/p&gt;
&lt;p&gt;The trap: a user message is not a request. It&#39;s this:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;User
  → web chat (Nuxt / Nitro API)
    → Agent Sandbox (EKS, one sandbox per deployment)
      → Hermes (agent runtime inside the sandbox)
        → N calls to LiteLLM  (think, tool, think, tool…)
          → model (Bedrock / Claude, Ollama Cloud, …)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Postgres — CloudNativePG (CNPG) in our cluster — stores what the person sees. LiteLLM stores what gets paid. If those two views don&#39;t cross, you&#39;re operating blind.&lt;/p&gt;
&lt;p&gt;And Resizes AI wasn&#39;t the only client of the proxy. The same LiteLLM serves Resizes Agentic (our platform product), customer agents, and other internal services. Without platform-level metrics, a spend spike could be the chat… or any other consumer.&lt;/p&gt;
&lt;h2 id=&quot;two-problems-two-instruments&quot; tabindex=&quot;-1&quot;&gt;Two problems, two instruments&lt;/h2&gt;
&lt;div class=&quot;blog-table&quot; role=&quot;region&quot; aria-label=&quot;Article table&quot; tabindex=&quot;0&quot;&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Question&lt;/th&gt;
&lt;th&gt;Where it&#39;s answered&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Which agent / org / conversation is spending?&lt;/td&gt;
&lt;td&gt;LiteLLM spend logs + attribution headers + &lt;code&gt;X-Resizes-LiteLLM-Session&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Is the proxy healthy? Which model is failing? What&#39;s total traffic?&lt;/td&gt;
&lt;td&gt;Prometheus + Grafana + Discord alerts&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;
&lt;p&gt;We measured first. We cut second. In that order, on purpose.&lt;/p&gt;
&lt;h2 id=&quot;layer-1--attributing-resizes-ai-spend&quot; tabindex=&quot;-1&quot;&gt;Layer 1 — Attributing Resizes AI spend&lt;/h2&gt;
&lt;p&gt;Before, every LiteLLM call was an anonymous data point. Now Nitro (the Nuxt server) builds identity at the first hop — &lt;code&gt;web chat&lt;/code&gt; in the diagram above — and Hermes forwards those headers on every one of the N calls in the loop.&lt;/p&gt;
&lt;p&gt;What travels:&lt;/p&gt;
&lt;div class=&quot;blog-table&quot; role=&quot;region&quot; aria-label=&quot;Article table&quot; tabindex=&quot;0&quot;&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Header&lt;/th&gt;
&lt;th&gt;Value&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;X-Resizes-LiteLLM-User&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Deployment UUID&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;X-Resizes-LiteLLM-Tags&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;org:Name,agent:AgentName,env:prod&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;X-Resizes-LiteLLM-Session&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Conversation UUID&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;
&lt;pre tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-ts&quot;&gt;&lt;span class=&quot;hljs-comment&quot;&gt;// server/services/litellm-attribution.ts&lt;/span&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;hljs-title function_&quot;&gt;buildLitellmAttribution&lt;/span&gt;(&lt;span class=&quot;hljs-params&quot;&gt;
  &lt;span class=&quot;hljs-attr&quot;&gt;input&lt;/span&gt;: &lt;span class=&quot;hljs-title class_&quot;&gt;LitellmAttributionInput&lt;/span&gt;,
&lt;/span&gt;): &lt;span class=&quot;hljs-title class_&quot;&gt;LitellmAttribution&lt;/span&gt; {
  &lt;span class=&quot;hljs-keyword&quot;&gt;const&lt;/span&gt; orgRaw = input.&lt;span class=&quot;hljs-property&quot;&gt;organizationName&lt;/span&gt;?.&lt;span class=&quot;hljs-title function_&quot;&gt;trim&lt;/span&gt;() || input.&lt;span class=&quot;hljs-property&quot;&gt;organizationId&lt;/span&gt;
  &lt;span class=&quot;hljs-keyword&quot;&gt;const&lt;/span&gt; orgTag = &lt;span class=&quot;hljs-title function_&quot;&gt;sanitizeLitellmTagValue&lt;/span&gt;(orgRaw) || &lt;span class=&quot;hljs-string&quot;&gt;&#39;unknown&#39;&lt;/span&gt;
  &lt;span class=&quot;hljs-keyword&quot;&gt;const&lt;/span&gt; displayRaw = input.&lt;span class=&quot;hljs-property&quot;&gt;agentDisplayName&lt;/span&gt;?.&lt;span class=&quot;hljs-title function_&quot;&gt;trim&lt;/span&gt;() || &lt;span class=&quot;hljs-string&quot;&gt;&#39;unknown&#39;&lt;/span&gt;
  &lt;span class=&quot;hljs-keyword&quot;&gt;const&lt;/span&gt; agentTag = &lt;span class=&quot;hljs-title function_&quot;&gt;sanitizeLitellmTagValue&lt;/span&gt;(displayRaw) || &lt;span class=&quot;hljs-string&quot;&gt;&#39;unknown&#39;&lt;/span&gt;
  &lt;span class=&quot;hljs-keyword&quot;&gt;const&lt;/span&gt; env = input.&lt;span class=&quot;hljs-property&quot;&gt;spendEnvironment&lt;/span&gt; ?? &lt;span class=&quot;hljs-title function_&quot;&gt;resolveLitellmSpendEnvironment&lt;/span&gt;()

  &lt;span class=&quot;hljs-keyword&quot;&gt;const&lt;/span&gt; tags = [
    &lt;span class=&quot;hljs-string&quot;&gt;`org:&lt;span class=&quot;hljs-subst&quot;&gt;${orgTag}&lt;/span&gt;`&lt;/span&gt;,
    &lt;span class=&quot;hljs-string&quot;&gt;`agent:&lt;span class=&quot;hljs-subst&quot;&gt;${agentTag}&lt;/span&gt;`&lt;/span&gt;,
    &lt;span class=&quot;hljs-string&quot;&gt;`env:&lt;span class=&quot;hljs-subst&quot;&gt;${env}&lt;/span&gt;`&lt;/span&gt;,
  ]

  &lt;span class=&quot;hljs-keyword&quot;&gt;return&lt;/span&gt; {
    &lt;span class=&quot;hljs-attr&quot;&gt;user&lt;/span&gt;: input.&lt;span class=&quot;hljs-property&quot;&gt;deploymentId&lt;/span&gt;,
    tags,
    &lt;span class=&quot;hljs-attr&quot;&gt;tagsHeader&lt;/span&gt;: tags.&lt;span class=&quot;hljs-title function_&quot;&gt;join&lt;/span&gt;(&lt;span class=&quot;hljs-string&quot;&gt;&#39;,&#39;&lt;/span&gt;),
    &lt;span class=&quot;hljs-attr&quot;&gt;sessionId&lt;/span&gt;: &lt;span class=&quot;hljs-title function_&quot;&gt;sanitizeLitellmSessionId&lt;/span&gt;(input.&lt;span class=&quot;hljs-property&quot;&gt;conversationId&lt;/span&gt;),
  }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;env&lt;/code&gt; resolves with priority: first the &lt;code&gt;RESIZES_SPEND_ENV&lt;/code&gt; env var (if set), then it&#39;s inferred from &lt;code&gt;NUXT_PUBLIC_APP_URL&lt;/code&gt; (&lt;code&gt;local&lt;/code&gt; / &lt;code&gt;test&lt;/code&gt; / &lt;code&gt;prod&lt;/code&gt;), to avoid mixing dogfooding with production.&lt;/p&gt;
&lt;p&gt;In Hermes, those headers get injected into every LiteLLM call. The detail that matters: every iteration in a thread shares the same session id (the &lt;code&gt;conversationId&lt;/code&gt;), so we can count &quot;how many calls one response generates.&quot;&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;hljs-comment&quot;&gt;# integrations/hermes/resizes_litellm_attribution.py&lt;/span&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; session:
    &lt;span class=&quot;hljs-comment&quot;&gt;# Don&#39;t pass session_id as a kwarg: the OpenAI SDK rejects it.&lt;/span&gt;
    headers[&lt;span class=&quot;hljs-string&quot;&gt;&quot;x-litellm-session-id&quot;&lt;/span&gt;] = session
    extra_body = &lt;span class=&quot;hljs-built_in&quot;&gt;dict&lt;/span&gt;(api_kwargs.get(&lt;span class=&quot;hljs-string&quot;&gt;&quot;extra_body&quot;&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;or&lt;/span&gt; {})
    extra_body[&lt;span class=&quot;hljs-string&quot;&gt;&quot;litellm_session_id&quot;&lt;/span&gt;] = session
    api_kwargs[&lt;span class=&quot;hljs-string&quot;&gt;&quot;extra_body&quot;&lt;/span&gt;] = extra_body
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;That last part isn&#39;t theoretical. The first attempt passed &lt;code&gt;session_id=&lt;/code&gt; as a top-level argument. The chat died mid-stream:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;Completions.create() got an unexpected keyword argument &#39;session_id&#39;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Observability is product code. One misplaced header takes down the chat.&lt;/p&gt;
&lt;h2 id=&quot;layer-2--grafana-for-everything-that-talks-to-litellm&quot; tabindex=&quot;-1&quot;&gt;Layer 2 — Grafana for everything that talks to LiteLLM&lt;/h2&gt;
&lt;p&gt;Attributing Resizes AI isn&#39;t enough if the proxy is shared. We turned on Prometheus metrics in LiteLLM, in-cluster scrape, Grafana dashboard.&lt;/p&gt;
&lt;p&gt;The public endpoint is &lt;code&gt;/v1/&lt;/code&gt; (API). Metrics live inside the cluster, at &lt;code&gt;/metrics&lt;/code&gt;, scraped every 30s. Auth is off on that endpoint because it is not exposed outside the cluster — only Prometheus scrapes it.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;&lt;span class=&quot;hljs-comment&quot;&gt;# core/litellm/values.yaml&lt;/span&gt;
&lt;span class=&quot;hljs-attr&quot;&gt;litellm_settings:&lt;/span&gt;
  &lt;span class=&quot;hljs-attr&quot;&gt;callbacks:&lt;/span&gt;
    &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;prometheus&lt;/span&gt;
  &lt;span class=&quot;hljs-attr&quot;&gt;require_auth_for_metrics_endpoint:&lt;/span&gt; &lt;span class=&quot;hljs-literal&quot;&gt;false&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;pre tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;&lt;span class=&quot;hljs-comment&quot;&gt;# ServiceMonitor&lt;/span&gt;
&lt;span class=&quot;hljs-attr&quot;&gt;apiVersion:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;monitoring.coreos.com/v1&lt;/span&gt;
&lt;span class=&quot;hljs-attr&quot;&gt;kind:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;ServiceMonitor&lt;/span&gt;
&lt;span class=&quot;hljs-attr&quot;&gt;metadata:&lt;/span&gt;
  &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;litellm&lt;/span&gt;
  &lt;span class=&quot;hljs-attr&quot;&gt;labels:&lt;/span&gt;
    &lt;span class=&quot;hljs-attr&quot;&gt;release:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;kube-prometheus-stack&lt;/span&gt;
&lt;span class=&quot;hljs-attr&quot;&gt;spec:&lt;/span&gt;
  &lt;span class=&quot;hljs-attr&quot;&gt;endpoints:&lt;/span&gt;
    &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;port:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;http&lt;/span&gt;
      &lt;span class=&quot;hljs-attr&quot;&gt;path:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;/metrics&lt;/span&gt;
      &lt;span class=&quot;hljs-attr&quot;&gt;interval:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;30s&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;LiteLLM dashboard (uid &lt;code&gt;litellm-proxy&lt;/code&gt;):&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Deployment status (healthy / partial / outage)&lt;/li&gt;
&lt;li&gt;Error rate by provider and model&lt;/li&gt;
&lt;li&gt;Request rate by provider and model&lt;/li&gt;
&lt;li&gt;Fallbacks ok / failed&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;That bounds the pie: it&#39;s no longer &quot;LiteLLM is expensive.&quot; It&#39;s &quot;Claude on Bedrock has X req/s and Y% error rate; this Ollama Cloud model is the other spike; Resizes AI is this slice of spend, the rest is Resizes Agentic / customer agents / CI.&quot;&lt;/p&gt;
&lt;p&gt;Grafana answers proxy-wide health and volume. Spend logs + attribution headers answer who within Resizes AI. Together, the two are the map.&lt;/p&gt;
&lt;h2 id=&quot;the-false-shortcut-lets-set-10-turns&quot; tabindex=&quot;-1&quot;&gt;The false shortcut: &quot;let&#39;s set 10 turns&quot;&lt;/h2&gt;
&lt;p&gt;With half the numbers in hand, the first cut was dropping the agent loop to 10 iterations and sending it in the &lt;code&gt;/v1/runs&lt;/code&gt; body.&lt;/p&gt;
&lt;p&gt;In Resizes Agentic we already knew 10 breaks agents that need long tool chains. There we landed on a 50-turn cap, with forced synthesis when the agent hits the limit.&lt;/p&gt;
&lt;p&gt;Here the finding was worse: Hermes ignored &lt;code&gt;max_turns&lt;/code&gt; from the body. The &lt;code&gt;/v1/runs&lt;/code&gt; handler doesn&#39;t read it. The real cap is Hermes runtime config:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;&lt;span class=&quot;hljs-comment&quot;&gt;# ~/.hermes/config.yaml (local) — on EKS, Helm: agent.maxTurns: 50&lt;/span&gt;
&lt;span class=&quot;hljs-attr&quot;&gt;agent:&lt;/span&gt;
  &lt;span class=&quot;hljs-attr&quot;&gt;max_turns:&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;50&lt;/span&gt;   &lt;span class=&quot;hljs-comment&quot;&gt;# at the cap, Hermes asks for a summary; it doesn&#39;t blow up with a 502&lt;/span&gt;
  &lt;span class=&quot;hljs-comment&quot;&gt;# bridged to HERMES_MAX_ITERATIONS&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Sending JSON the other side doesn&#39;t consume is a placebo limit. We removed it from the body and left the knob where the runtime actually listens.&lt;/p&gt;
&lt;h2 id=&quot;what-actually-cuts-tokens-without-breaking-the-agent&quot; tabindex=&quot;-1&quot;&gt;What actually cuts tokens (without breaking the agent)&lt;/h2&gt;
&lt;p&gt;The cost of a turn is, roughly:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;cost ≈ context_tokens × n_iterations
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Tools make it worse: each tool call is another iteration, often with a bigger prompt. Three levers, not one.&lt;/p&gt;
&lt;h3 id=&quot;history-40--15&quot; tabindex=&quot;-1&quot;&gt;History 40 → 15&lt;/h3&gt;
&lt;p&gt;Every iteration resends the thread. 40 previous messages in a 20-turn loop is a brutal multiplier.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-ts&quot;&gt;&lt;span class=&quot;hljs-comment&quot;&gt;// server/config/agent-runtime.ts&lt;/span&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;hljs-variable constant_&quot;&gt;AGENT_RUNTIME_DEFAULT_CHAT_HISTORY_LIMIT&lt;/span&gt; = &lt;span class=&quot;hljs-number&quot;&gt;15&lt;/span&gt;

&lt;span class=&quot;hljs-keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;hljs-title function_&quot;&gt;getAgentRuntimeChatHistoryLimit&lt;/span&gt;(&lt;span class=&quot;hljs-params&quot;&gt;&lt;/span&gt;): &lt;span class=&quot;hljs-built_in&quot;&gt;number&lt;/span&gt; {
  &lt;span class=&quot;hljs-keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;hljs-title function_&quot;&gt;parsePositiveInt&lt;/span&gt;(
    process.&lt;span class=&quot;hljs-property&quot;&gt;env&lt;/span&gt;.&lt;span class=&quot;hljs-property&quot;&gt;AGENT_RUNTIME_CHAT_HISTORY_LIMIT&lt;/span&gt;,
    &lt;span class=&quot;hljs-variable constant_&quot;&gt;AGENT_RUNTIME_DEFAULT_CHAT_HISTORY_LIMIT&lt;/span&gt;,
  )
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And it has to be used on both paths (sync and stream). We had the constant set to 15 and the chat was still reading 40: another placebo.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-ts&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;const&lt;/span&gt; history = &lt;span class=&quot;hljs-keyword&quot;&gt;await&lt;/span&gt; chatMessagesRepository.&lt;span class=&quot;hljs-title function_&quot;&gt;listByConversation&lt;/span&gt;(
  organizationId,
  deploymentId,
  conversationId,
  &lt;span class=&quot;hljs-title function_&quot;&gt;getAgentRuntimeChatHistoryLimit&lt;/span&gt;(),
)
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;tool-discipline-in-the-prompt&quot; tabindex=&quot;-1&quot;&gt;Tool discipline in the prompt&lt;/h3&gt;
&lt;p&gt;The agent reached for terminal and code on questions that didn&#39;t need them. We added short rules to every turn&#39;s instructions:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-ts&quot;&gt;&lt;span class=&quot;hljs-comment&quot;&gt;// server/services/agent-context-assembler.ts&lt;/span&gt;
&lt;span class=&quot;hljs-string&quot;&gt;&#39;## Runtime efficiency rules&#39;&lt;/span&gt;,
&lt;span class=&quot;hljs-string&quot;&gt;&#39;1. Prefer a single, direct answer. Do not split a reply into multiple model turns unless the user explicitly asks for step-by-step reasoning.&#39;&lt;/span&gt;,
&lt;span class=&quot;hljs-string&quot;&gt;&#39;2. Only use tools (terminal, code execution, integrations) when they are strictly necessary to answer the user. For general chat, questions, summaries, or explanations, respond directly without calling tools unless the task requires an external system.&#39;&lt;/span&gt;,
&lt;span class=&quot;hljs-string&quot;&gt;&#39;3. If a tool call fails once, stop and report the failure to the user instead of retrying automatically.&#39;&lt;/span&gt;,
&lt;span class=&quot;hljs-string&quot;&gt;&#39;4. Do not run the same tool more than once per user message unless the user asks for it.&#39;&lt;/span&gt;,
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;It&#39;s not a rate limit. It&#39;s not paying for useless turns.&lt;/p&gt;
&lt;h3 id=&quot;a-real-cap-at-50-with-graceful-degradation&quot; tabindex=&quot;-1&quot;&gt;A real cap at 50, with graceful degradation&lt;/h3&gt;
&lt;p&gt;50 turns, in Hermes&#39;s ConfigMap, in both test and prod. On hitting the cap the runtime asks for a summary; the user doesn&#39;t get left with a silent 502. This already existed in the runtime; we just weren&#39;t using it.&lt;/p&gt;
&lt;h3 id=&quot;a-token-chip-in-the-composer&quot; tabindex=&quot;-1&quot;&gt;A token chip in the composer&lt;/h3&gt;
&lt;p&gt;Spend was an AWS invoice line. We put a token chip in the composer so the remaining balance is visible in the chat — a fuel gauge, not a surprise bill.&lt;/p&gt;
&lt;h2 id=&quot;what-actually-improved&quot; tabindex=&quot;-1&quot;&gt;What actually improved&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Operations&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Filter spend by &lt;code&gt;agent:AgentName&lt;/code&gt;, &lt;code&gt;env:prod&lt;/code&gt;, &lt;code&gt;org:…&lt;/code&gt;, and group a thread&#39;s calls to see iterations per response.&lt;/li&gt;
&lt;li&gt;Request rate, error rate, and fallbacks for the whole proxy in Grafana — not just the chat.&lt;/li&gt;
&lt;li&gt;Outage / error-rate / fallback alerts without drowning Discord with the rest of the cluster.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Product&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Fewer tokens per turn (less history, fewer unnecessary tools).&lt;/li&gt;
&lt;li&gt;Agents that can complete long chains (50, not 10).&lt;/li&gt;
&lt;li&gt;A token balance the user can see while they type.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Engineering&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The turn limit lives where the runtime actually reads it.&lt;/li&gt;
&lt;li&gt;Observability treated as a feature: the Hermes session header got a test, not just &quot;one more header.&quot; We also stopped treating a completed SSE stream as an error.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;We cut history and unused tools; we cannot yet quote a savings percentage. What we can query today is the map: how much this agent spends, which model is failing, how many calls one message generates. Savings in euros will follow; the visibility is already here.&lt;/p&gt;
&lt;h2 id=&quot;whats-still-missing-on-purpose&quot; tabindex=&quot;-1&quot;&gt;What&#39;s still missing (on purpose)&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Next:&lt;/strong&gt; budget alerts by tag — we already have the tags, just need the thresholds.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;After that:&lt;/strong&gt; a LiteLLM virtual key per agent (hard isolation) — the Resizes AI architecture already designs for it per deployment, it just isn&#39;t implemented yet.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Further out:&lt;/strong&gt; syncing LiteLLM spend with the product&#39;s token balance; Langfuse-style traces (which prompt, which tool, cost per step); a fast-path for &quot;hi&quot; that doesn&#39;t even enter the agent loop.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;We&#39;ve stopped flying blind. There&#39;s no autopilot yet.&lt;/p&gt;
&lt;h2 id=&quot;checklist-if-youre-running-agents-on-a-shared-proxy&quot; tabindex=&quot;-1&quot;&gt;Checklist if you&#39;re running agents on a shared proxy&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;Grafana / Prometheus over the whole proxy, not just your app.&lt;/li&gt;
&lt;li&gt;The turn limit has to live where the runtime reads it (runtime config, not the API body).&lt;/li&gt;
&lt;li&gt;Cut context and tools first; don&#39;t lower turns until the agent breaks.&lt;/li&gt;
&lt;li&gt;At the cap: synthesize. Don&#39;t return a 502.&lt;/li&gt;
&lt;li&gt;Hot-path telemetry needs the same rigor as the feature itself.&lt;/li&gt;
&lt;/ol&gt;
</content:encoded></item><item><title>Stop paying $0.40 per secret: cut AWS Secrets Manager cost and run secrets more efficiently</title><link>https://resiz.es/blog/aws-secrets-manager-to-1password</link><guid isPermaLink="false">https://blog.resiz.es/aws-secrets-manager-to-1password</guid><pubDate>Sun, 26 Jul 2026 00:00:00 GMT</pubDate><description>What Secrets Manager really costs at 50, 500, and 5,000 secrets — and how we help organisations move to a portable, cheaper operating model with 1Password and External Secrets.</description><content:encoded>&lt;p&gt;Most organisations do not have a “secrets strategy.” They have an AWS line item that grows every time someone creates another credential — and a platform team that still opens tickets to wire the next service into IAM.&lt;/p&gt;
&lt;p&gt;AWS Secrets Manager charges &lt;strong&gt;$0.40 per secret, every month&lt;/strong&gt;, plus API usage (&lt;a href=&quot;https://aws.amazon.com/secrets-manager/pricing/&quot;&gt;official pricing&lt;/a&gt;). There is no volume discount. Forgotten secrets still bill. Cross-region replicas bill again. Copy the same logical secret into &lt;code&gt;dev&lt;/code&gt;, &lt;code&gt;staging&lt;/code&gt;, and &lt;code&gt;prod&lt;/code&gt; and you pay three times.&lt;/p&gt;
&lt;p&gt;That is not only a FinOps problem. It is an &lt;strong&gt;efficiency&lt;/strong&gt; problem: two sources of truth (password manager for people, Secrets Manager for apps), cloud-locked access paths, and more glue each time you add a cluster.&lt;/p&gt;
&lt;p&gt;We help organisations &lt;strong&gt;quantify that cost, redesign how secrets are delivered, migrate safely, and leave teams with an operating model that is cheaper and easier to run&lt;/strong&gt;.&lt;/p&gt;
&lt;!--truncate--&gt;
&lt;hr&gt;
&lt;h2 id=&quot;what-this-is-costing-you&quot; tabindex=&quot;-1&quot;&gt;What this is costing you&lt;/h2&gt;
&lt;p&gt;Storage alone (API usually stays secondary if you cache):&lt;/p&gt;
&lt;div class=&quot;blog-table&quot; role=&quot;region&quot; aria-label=&quot;Article table&quot; tabindex=&quot;0&quot;&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Secrets in Secrets Manager&lt;/th&gt;
&lt;th&gt;Per month&lt;/th&gt;
&lt;th&gt;Per year&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;50&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;$20&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;$240&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;500&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;$200&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;$2,400&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;5,000&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;$2,000&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;$24,000&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;
&lt;p&gt;At 5,000 secrets you are looking at roughly &lt;strong&gt;$24k/year before&lt;/strong&gt; replicas, multi-account sprawl, or environment copies. Many estates behave like:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;yearly ≈ secrets × environments × 0.40 × 12
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;So 2,000 logical secrets × 3 environments is closer to &lt;strong&gt;$28,800/year&lt;/strong&gt; in storage — still before API calls.&lt;/p&gt;
&lt;p&gt;If you already pay for &lt;strong&gt;1Password Business&lt;/strong&gt; (or similar) for people, vault items used for automation do &lt;strong&gt;not&lt;/strong&gt; meter at $0.40 each. Connect hosting is typically a small Kubernetes footprint. The saving below is the AWS storage you can stop paying — not a claim that the destination stack costs nothing.&lt;/p&gt;
&lt;div class=&quot;blog-table&quot; role=&quot;region&quot; aria-label=&quot;Article table&quot; tabindex=&quot;0&quot;&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Scale&lt;/th&gt;
&lt;th&gt;Typical yearly AWS storage&lt;/th&gt;
&lt;th&gt;What that budget usually funds better&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;50 secrets&lt;/td&gt;
&lt;td&gt;~$240&lt;/td&gt;
&lt;td&gt;Small; still worth cleaning if you are building the right model anyway&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;500 secrets&lt;/td&gt;
&lt;td&gt;~$2,400&lt;/td&gt;
&lt;td&gt;A focused secrets platform cutover&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;5,000 secrets&lt;/td&gt;
&lt;td&gt;~$24,000&lt;/td&gt;
&lt;td&gt;Sustained platform capacity — or the bill you keep writing if you do nothing&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;Check your number:&lt;/strong&gt; Cost Explorer → &lt;code&gt;AmazonSecretsManager&lt;/code&gt;, then reconcile with secret count (including replicas and secrets in a deletion recovery window).&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&quot;efficiency-what-actually-improves-for-the-business&quot; tabindex=&quot;-1&quot;&gt;Efficiency: what actually improves for the business&lt;/h2&gt;
&lt;p&gt;Cost is the easy spreadsheet. Efficiency is why platform and security leaders care.&lt;/p&gt;
&lt;div class=&quot;blog-table&quot; role=&quot;region&quot; aria-label=&quot;Article table&quot; tabindex=&quot;0&quot;&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Today with Secrets Manager as system of record&lt;/th&gt;
&lt;th&gt;After a proper cutover&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Every new service needs an IAM path into AWS&lt;/td&gt;
&lt;td&gt;Services sync secrets through a standard cluster pattern&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Humans in 1Password, apps in AWS — two ACL and audit stories&lt;/td&gt;
&lt;td&gt;One vault model for people and workloads&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Adding a cluster means reinventing secret delivery&lt;/td&gt;
&lt;td&gt;Shared Connect + one vault / store per cluster&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Staging “shares” prod-ish secrets to avoid paying 3×&lt;/td&gt;
&lt;td&gt;Honest per-environment vaults without a per-secret AWS tax&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Spend grows with secret count forever&lt;/td&gt;
&lt;td&gt;Spend is seats + a small control plane, not $0.40 × N&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;Cloud agnosticism&lt;/strong&gt; is the strategic version of the same point: secrets stop being an AWS account feature and become a platform capability. You can run the same delivery model on EKS, another cloud, or on-prem clusters that can reach Connect — without redesigning IAM for every estate.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&quot;the-operating-model-we-put-in-place&quot; tabindex=&quot;-1&quot;&gt;The operating model we put in place&lt;/h2&gt;
&lt;p&gt;We implement a pattern built for multi-cluster organisations:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;One vault per environment / Kubernetes cluster&lt;/strong&gt; in 1Password.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;One Connect Server&lt;/strong&gt; (shared behind ingress when clusters can reach each other).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;One cluster-wide secret store per cluster&lt;/strong&gt;, with a &lt;strong&gt;read-only&lt;/strong&gt; token limited to that cluster’s vault.&lt;/li&gt;
&lt;li&gt;Workloads declare sync resources against that store — &lt;strong&gt;not&lt;/strong&gt; a custom store (and IAM role path) per team.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Runtime stays read-only. Write access is reserved for controlled admin and migration windows. That reduces blast radius and stops production clusters holding write credentials they do not need.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&quot;how-we-improve-this-in-your-organisation&quot; tabindex=&quot;-1&quot;&gt;How we improve this in your organisation&lt;/h2&gt;
&lt;p&gt;We run this as a delivery engagement, not a slide deck.&lt;/p&gt;
&lt;h3 id=&quot;1-cost-and-opportunity-snapshot-short-discovery&quot; tabindex=&quot;-1&quot;&gt;1. Cost and opportunity snapshot (short discovery)&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Inventory secrets across accounts and regions (replicas and pending deletions included).&lt;/li&gt;
&lt;li&gt;Produce &lt;strong&gt;your&lt;/strong&gt; monthly/yearly Secrets Manager figure at real counts — not a generic table.&lt;/li&gt;
&lt;li&gt;Separate what should move now from what should stay on AWS (for example native DB rotation still tied to Secrets Manager).&lt;/li&gt;
&lt;li&gt;Agree success criteria with platform, security, and FinOps.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;You leave this step with a number and a scope&lt;/strong&gt;, not a philosophy.&lt;/p&gt;
&lt;h3 id=&quot;2-target-design-for-your-estate&quot; tabindex=&quot;-1&quot;&gt;2. Target design for your estate&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Vault layout aligned to how you isolate environments and clusters.&lt;/li&gt;
&lt;li&gt;Connect topology and token boundaries (read-only for runtime).&lt;/li&gt;
&lt;li&gt;Standard onboarding path for application teams.&lt;/li&gt;
&lt;li&gt;Cutover order that protects production (usually non-prod first).&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;3-migration-and-cutover&quot; tabindex=&quot;-1&quot;&gt;3. Migration and cutover&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Move secrets into the right vaults with naming and ownership agreed up front.&lt;/li&gt;
&lt;li&gt;Dry runs, then staged cutovers per environment.&lt;/li&gt;
&lt;li&gt;Validate cluster sync before AWS copies are removed.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Delete (or schedule deletion of) AWS secrets&lt;/strong&gt; so the $0.40 lines actually disappear — migration without cleanup is only half the saving.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;4-handover-for-ongoing-efficiency&quot; tabindex=&quot;-1&quot;&gt;4. Handover for ongoing efficiency&lt;/h3&gt;
&lt;p&gt;Your teams should be able to:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Onboard a service without inventing a new IAM/secrets path.&lt;/li&gt;
&lt;li&gt;Add a cluster by attaching it to the shared model and its own vault.&lt;/li&gt;
&lt;li&gt;Govern human and machine access in one place.&lt;/li&gt;
&lt;li&gt;Treat secrets spend as a platform metric Finance can track.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2 id=&quot;when-we-would-tell-you-not-to-move-yet&quot; tabindex=&quot;-1&quot;&gt;When we would tell you not to move (yet)&lt;/h2&gt;
&lt;p&gt;We will say so if:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Almost all consumers are AWS-native and there is no multi-cluster plan.&lt;/li&gt;
&lt;li&gt;Critical rotation depends on Secrets Manager’s AWS-native flows and must stay put for now.&lt;/li&gt;
&lt;li&gt;Secret count is tiny and changing the operating model costs more than it saves today.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Otherwise — especially from &lt;strong&gt;hundreds of secrets&lt;/strong&gt; upward, or when 1Password is already on the books — the combination of &lt;strong&gt;lower recurring AWS cost&lt;/strong&gt; and &lt;strong&gt;a simpler delivery model&lt;/strong&gt; is usually worth a concrete plan.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&quot;talk-to-us&quot; tabindex=&quot;-1&quot;&gt;Talk to us&lt;/h2&gt;
&lt;p&gt;If you want to know what Secrets Manager is costing &lt;strong&gt;your&lt;/strong&gt; organisation and what a cleaner model would look like in your clusters, we can start with a short discovery: inventory, cost estimate, and a migration outline.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Outcome we aim for:&lt;/strong&gt; lower AWS secrets spend, one operating model for humans and workloads, and a platform your teams can extend without growing a per-secret cloud tax every month.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.resiz.es/contact&quot;&gt;Contact us&lt;/a&gt; to schedule that conversation.&lt;/p&gt;
</content:encoded></item><item><title>Kubernetes v1.36 - Mutable Pod Resources for Suspended Jobs</title><link>https://resiz.es/blog/kubernetes-v1-36-mutable-pod-resources</link><guid isPermaLink="false">https://blog.resiz.es/kubernetes-v1-36-mutable-pod-resources</guid><pubDate>Wed, 13 May 2026 00:00:00 GMT</pubDate><description>Batch and ML workloads often need resources that aren&#39;t known at Job creation time. The optimal allocation depends on cluster capacity, queue priorities, and hardware availability — all of which ca…</description><content:encoded>&lt;p&gt;Batch and ML workloads often need resources that aren&#39;t known at Job creation time. The optimal allocation depends on cluster capacity, queue priorities, and hardware availability — all of which can change between submission and execution.&lt;/p&gt;
&lt;p&gt;Kubernetes v1.36 promotes a feature to beta that solves this: &lt;strong&gt;mutable pod resources for suspended Jobs&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Before this, resource requirements in a Job&#39;s pod template were immutable. If a queue controller determined that a suspended Job should run with different resources, the only option was to delete and recreate the Job — losing metadata, status, and history.&lt;/p&gt;
&lt;!--truncate--&gt;
&lt;h2 id=&quot;why-this-matters&quot; tabindex=&quot;-1&quot;&gt;Why This Matters&lt;/h2&gt;
&lt;p&gt;The problem is straightforward. You submit a Job with estimated resources. The cluster is busy. A queue controller like Kueue sees that only half the GPUs are available. Without this feature, your options are:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Wait until full resources are available (blocking the queue)&lt;/li&gt;
&lt;li&gt;Delete and recreate the Job with lower resources (losing history)&lt;/li&gt;
&lt;li&gt;Fail the Job entirely&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;None of these work well for ML training or batch pipelines that need flexibility.&lt;/p&gt;
&lt;p&gt;This feature allows queue controllers and cluster administrators to adjust CPU, memory, GPU, and extended resource specifications on a Job while it&#39;s suspended — before it starts or resumes running.&lt;/p&gt;
&lt;h2 id=&quot;how-it-works&quot; tabindex=&quot;-1&quot;&gt;How It Works&lt;/h2&gt;
&lt;p&gt;The Kubernetes API server relaxes the immutability constraint on pod template resource fields specifically for suspended Jobs. No new API types were introduced.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Mutable fields:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;spec.template.spec.containers[*].resources.requests&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;spec.template.spec.containers[*].resources.limits&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;spec.template.spec.initContainers[*].resources.requests&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;spec.template.spec.initContainers[*].resources.limits&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Conditions for mutation:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The Job has &lt;code&gt;spec.suspend&lt;/code&gt; set to &lt;code&gt;true&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;For Jobs that were previously running, all active Pods must have terminated (&lt;code&gt;status.active&lt;/code&gt; equals 0)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Standard resource validation still applies. Limits must be greater than or equal to requests. Extended resources must be specified as whole numbers where required.&lt;/p&gt;
&lt;h2 id=&quot;practical-example&quot; tabindex=&quot;-1&quot;&gt;Practical Example&lt;/h2&gt;
&lt;p&gt;A machine learning training Job initially requests 4 GPUs:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;&lt;span class=&quot;hljs-attr&quot;&gt;apiVersion:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;batch/v1&lt;/span&gt;
&lt;span class=&quot;hljs-attr&quot;&gt;kind:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;Job&lt;/span&gt;
&lt;span class=&quot;hljs-attr&quot;&gt;metadata:&lt;/span&gt;
  &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;training-job-example-abcd123&lt;/span&gt;
  &lt;span class=&quot;hljs-attr&quot;&gt;labels:&lt;/span&gt;
    &lt;span class=&quot;hljs-attr&quot;&gt;app.kubernetes.io/name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;trainer&lt;/span&gt;
&lt;span class=&quot;hljs-attr&quot;&gt;spec:&lt;/span&gt;
  &lt;span class=&quot;hljs-attr&quot;&gt;suspend:&lt;/span&gt; &lt;span class=&quot;hljs-literal&quot;&gt;true&lt;/span&gt;
  &lt;span class=&quot;hljs-attr&quot;&gt;template:&lt;/span&gt;
    &lt;span class=&quot;hljs-attr&quot;&gt;spec:&lt;/span&gt;
      &lt;span class=&quot;hljs-attr&quot;&gt;containers:&lt;/span&gt;
      &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;trainer&lt;/span&gt;
        &lt;span class=&quot;hljs-attr&quot;&gt;image:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;example-registry.example.com/training:latest&lt;/span&gt;
        &lt;span class=&quot;hljs-attr&quot;&gt;resources:&lt;/span&gt;
          &lt;span class=&quot;hljs-attr&quot;&gt;requests:&lt;/span&gt;
            &lt;span class=&quot;hljs-attr&quot;&gt;cpu:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;8&quot;&lt;/span&gt;
            &lt;span class=&quot;hljs-attr&quot;&gt;memory:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;32Gi&quot;&lt;/span&gt;
            &lt;span class=&quot;hljs-attr&quot;&gt;example-hardware-vendor.com/gpu:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;4&quot;&lt;/span&gt;
          &lt;span class=&quot;hljs-attr&quot;&gt;limits:&lt;/span&gt;
            &lt;span class=&quot;hljs-attr&quot;&gt;cpu:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;8&quot;&lt;/span&gt;
            &lt;span class=&quot;hljs-attr&quot;&gt;memory:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;32Gi&quot;&lt;/span&gt;
            &lt;span class=&quot;hljs-attr&quot;&gt;example-hardware-vendor.com/gpu:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;4&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;A queue controller determines only 2 GPUs are available. It updates the Job:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;&lt;span class=&quot;hljs-attr&quot;&gt;resources:&lt;/span&gt;
  &lt;span class=&quot;hljs-attr&quot;&gt;requests:&lt;/span&gt;
    &lt;span class=&quot;hljs-attr&quot;&gt;cpu:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;4&quot;&lt;/span&gt;
    &lt;span class=&quot;hljs-attr&quot;&gt;memory:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;16Gi&quot;&lt;/span&gt;
    &lt;span class=&quot;hljs-attr&quot;&gt;example-hardware-vendor.com/gpu:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;2&quot;&lt;/span&gt;
  &lt;span class=&quot;hljs-attr&quot;&gt;limits:&lt;/span&gt;
    &lt;span class=&quot;hljs-attr&quot;&gt;cpu:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;4&quot;&lt;/span&gt;
    &lt;span class=&quot;hljs-attr&quot;&gt;memory:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;16Gi&quot;&lt;/span&gt;
    &lt;span class=&quot;hljs-attr&quot;&gt;example-hardware-vendor.com/gpu:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;2&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Then resumes the Job:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;kubectl patch job training-job-example-abcd123 -p &lt;span class=&quot;hljs-string&quot;&gt;&#39;{&quot;spec&quot;:{&quot;suspend&quot;:false}}&#39;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The Job runs with adjusted resources instead of blocking the queue.&lt;/p&gt;
&lt;h2 id=&quot;whats-new-in-beta&quot; tabindex=&quot;-1&quot;&gt;What&#39;s New in Beta&lt;/h2&gt;
&lt;p&gt;In Kubernetes v1.36, the &lt;code&gt;MutablePodResourcesForSuspendedJobs&lt;/code&gt; feature gate is &lt;strong&gt;enabled by default&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Clusters running v1.36 can use this feature without additional API server configuration. For v1.35 clusters, enable the feature gate manually.&lt;/p&gt;
&lt;h2 id=&quot;considerations&quot; tabindex=&quot;-1&quot;&gt;Considerations&lt;/h2&gt;
&lt;h3 id=&quot;running-jobs-that-get-suspended&quot; tabindex=&quot;-1&quot;&gt;Running Jobs that Get Suspended&lt;/h3&gt;
&lt;p&gt;If you suspend a Job that was already running, wait for all active Pods to terminate before modifying resources. The API server rejects mutations while &lt;code&gt;status.active&lt;/code&gt; is greater than zero.&lt;/p&gt;
&lt;h3 id=&quot;pod-replacement-policy&quot; tabindex=&quot;-1&quot;&gt;Pod Replacement Policy&lt;/h3&gt;
&lt;p&gt;For Jobs with failed Pods, consider setting &lt;code&gt;podReplacementPolicy: Failed&lt;/code&gt;. This ensures replacement Pods are only created after previous Pods have fully terminated, preventing resource contention from overlapping Pods.&lt;/p&gt;
&lt;h3 id=&quot;resourceclaims&quot; tabindex=&quot;-1&quot;&gt;ResourceClaims&lt;/h3&gt;
&lt;p&gt;Dynamic Resource Allocation (DRA) &lt;code&gt;resourceClaimTemplates&lt;/code&gt; remain immutable. If your workload uses DRA, you must recreate the claim templates separately to match resource changes.&lt;/p&gt;
&lt;h2 id=&quot;try-it-out&quot; tabindex=&quot;-1&quot;&gt;Try It Out&lt;/h2&gt;
&lt;pre tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;hljs-comment&quot;&gt;# Create a suspended Job&lt;/span&gt;
kubectl apply -f my-job.yaml --server-side

&lt;span class=&quot;hljs-comment&quot;&gt;# Edit the resource requests&lt;/span&gt;
kubectl edit job training-job-example-abcd123

&lt;span class=&quot;hljs-comment&quot;&gt;# Resume the Job&lt;/span&gt;
kubectl patch job training-job-example-abcd123 -p &lt;span class=&quot;hljs-string&quot;&gt;&#39;{&quot;spec&quot;:{&quot;suspend&quot;:false}}&#39;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;tldr&quot; tabindex=&quot;-1&quot;&gt;TL;DR&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Before:&lt;/strong&gt; Resource requirements in Job pod templates were immutable. Controllers had to delete and recreate Jobs to adjust resources.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Now:&lt;/strong&gt; Suspended Jobs can have their resource requests and limits modified, enabling dynamic resource allocation for batch and ML workloads.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Key benefits:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;✅ Queue controllers can adjust resources based on availability&lt;/li&gt;
&lt;li&gt;✅ Jobs can progress with reduced resources instead of blocking&lt;/li&gt;
&lt;li&gt;✅ No need to delete and recreate Jobs&lt;/li&gt;
&lt;li&gt;✅ Preserves Job metadata, status, and history&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;resources&quot; tabindex=&quot;-1&quot;&gt;Resources&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://kubernetes.io/blog/2026/04/27/kubernetes-v1-36-mutable-pod-resources-for-suspended-jobs/&quot;&gt;Kubernetes Blog - v1.36 Announcement&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://kep.k8s.io/5440&quot;&gt;KEP-5440 Tracking Issue&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://kueue.sigs.k8s.io/&quot;&gt;Kueue - Queue Controller&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://kubernetes.slack.com/archives/C18NZM5K9&quot;&gt;SIG Apps Slack&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://kubernetes.slack.com/archives/C032ZE66A2X&quot;&gt;WG Batch Slack&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</content:encoded></item><item><title>Team Topologies - How to Structure a Platform Team That Actually Works</title><link>https://resiz.es/blog/team-topologies-platform-team</link><guid isPermaLink="false">https://blog.resiz.es/team-topologies-platform-team</guid><pubDate>Tue, 28 Apr 2026 00:00:00 GMT</pubDate><description>Platform engineering is now a critical function in modern software organizations. Gartner predicts that 80% of large engineering organizations will have dedicated platform teams by 2026. But simply…</description><content:encoded>&lt;p&gt;Platform engineering is now a critical function in modern software organizations. Gartner predicts that 80% of large engineering organizations will have dedicated platform teams by 2026. But simply having a platform team isn&#39;t enough. The real challenge lies in structuring it successfully.&lt;/p&gt;
&lt;p&gt;Many engineering teams struggle with balancing autonomy and alignment, often becoming either isolated silos or overloaded bottlenecks that slow down development instead of accelerating it.&lt;/p&gt;
&lt;p&gt;This is where &lt;strong&gt;team topologies&lt;/strong&gt; come in. A strategic approach to designing platform teams that ensures they integrate smoothly with engineering workflows and maximize their impact.&lt;/p&gt;
&lt;!--truncate--&gt;
&lt;h2 id=&quot;what-are-team-topologies&quot; tabindex=&quot;-1&quot;&gt;What Are Team Topologies?&lt;/h2&gt;
&lt;p&gt;Team topologies is a conceptual framework to evolve organizational structures and achieve software team interactions for fast, reliable, and adaptive delivery. It eliminates silos in software development, enhancing productivity and optimizing resource allocation.&lt;/p&gt;
&lt;p&gt;The framework was introduced by Matthew Skelton and Manuel Pais in their book &lt;em&gt;Team Topologies: Organizing Business and Technology Teams for Fast Flow&lt;/em&gt;. It identifies &lt;strong&gt;four fundamental team types&lt;/strong&gt; and interaction modes to optimize product and service delivery.&lt;/p&gt;
&lt;p&gt;Traditional platform teams are structured around specific functions like infrastructure, security, and operations. While this provides specialization, it often leads to siloed work and communication barriers.&lt;/p&gt;
&lt;p&gt;Team topologies introduce a more dynamic structure with clearly defined roles and interactions — designed to help organizations structure their teams to support business goals and impact agility, developer productivity, and architectural requirements.&lt;/p&gt;
&lt;h2 id=&quot;the-four-team-types&quot; tabindex=&quot;-1&quot;&gt;The Four Team Types&lt;/h2&gt;
&lt;h3 id=&quot;1-stream-aligned-teams&quot; tabindex=&quot;-1&quot;&gt;1. Stream-Aligned Teams&lt;/h3&gt;
&lt;p&gt;Dedicated to a single product, delivering end-to-end value to customers. They maintain a continuous flow of software updates and are directly aligned with a specific business domain.&lt;/p&gt;
&lt;p&gt;Key characteristics:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Own the entire development lifecycle (design to deployment)&lt;/li&gt;
&lt;li&gt;Work independently to minimize dependencies&lt;/li&gt;
&lt;li&gt;Are the foundation — other team types are structured around them&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;2-enabling-teams&quot; tabindex=&quot;-1&quot;&gt;2. Enabling Teams&lt;/h3&gt;
&lt;p&gt;Help stream-aligned teams adopt new technologies and best practices without taking over their work. They act as mentors and consultants, reducing knowledge gaps.&lt;/p&gt;
&lt;p&gt;What they do:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Provide training, coaching, and mentoring&lt;/li&gt;
&lt;li&gt;Give informed recommendations about tooling and frameworks&lt;/li&gt;
&lt;li&gt;Focus on addressing problems, not providing solutions&lt;/li&gt;
&lt;li&gt;Increase autonomy of stream-aligned teams&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;3-complicated-subsystem-teams&quot; tabindex=&quot;-1&quot;&gt;3. Complicated Subsystem Teams&lt;/h3&gt;
&lt;p&gt;Handle highly specialized and computationally complex areas that need deep expertise:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Machine learning models&lt;/li&gt;
&lt;li&gt;Advanced algorithms&lt;/li&gt;
&lt;li&gt;Legacy system maintenance&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Stream-aligned teams don&#39;t need to build complex functionalities outside their core responsibilities. This team reduces their cognitive load.&lt;/p&gt;
&lt;h3 id=&quot;4-platform-teams&quot; tabindex=&quot;-1&quot;&gt;4. Platform Teams&lt;/h3&gt;
&lt;p&gt;Develop, build, maintain, and support internal tools, services, and infrastructure that help stream-aligned teams operate autonomously.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Key insight&lt;/strong&gt;: While stream-aligned teams retain full autonomy of building and running applications, platform teams provide internal services to abstract underlying complexity.&lt;/p&gt;
&lt;p&gt;This enhances developer productivity (DevEx) and ensures a cohesive experience across different products.&lt;/p&gt;
&lt;h2 id=&quot;why-you-need-platform-teams&quot; tabindex=&quot;-1&quot;&gt;Why You Need Platform Teams&lt;/h2&gt;
&lt;p&gt;One of the most significant hidden costs of cloud adoption is &lt;strong&gt;cognitive load&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;In the past, operations teams managed networking, databases, and security while developers focused on application code. Today, developers are expected to manage infrastructure, deployment pipelines, security, compliance, and observability — all while delivering new features.&lt;/p&gt;
&lt;p&gt;This cognitive burden slows development and increases errors.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&quot;The real challenge isn&#39;t just about shifting left or making teams more autonomous — it&#39;s about providing the right guardrails so developers aren&#39;t overwhelmed by the sheer number of things they need to manage.&quot; — Manuel Pais&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;strong&gt;Platform teams solve this by:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Offloading complexity&lt;/li&gt;
&lt;li&gt;Providing standardized solutions and &quot;paved roads&quot;&lt;/li&gt;
&lt;li&gt;Making best practices easy to adopt&lt;/li&gt;
&lt;li&gt;Building Internal Developer Platforms (IDPs) with self-service tools&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Instead of every developer becoming a cloud architect, they rely on platform teams to abstract complexity.&lt;/p&gt;
&lt;h2 id=&quot;best-practices-for-structuring-a-platform-team&quot; tabindex=&quot;-1&quot;&gt;Best Practices for Structuring a Platform Team&lt;/h2&gt;
&lt;h3 id=&quot;designate-a-platform-owner&quot; tabindex=&quot;-1&quot;&gt;Designate a Platform Owner&lt;/h3&gt;
&lt;p&gt;A platform owner with product management skills helps:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Define the platform&#39;s vision&lt;/li&gt;
&lt;li&gt;Understand user needs&lt;/li&gt;
&lt;li&gt;Prioritize development&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;treat-the-platform-as-a-product&quot; tabindex=&quot;-1&quot;&gt;Treat the Platform as a Product&lt;/h3&gt;
&lt;p&gt;Most organizations treat platform engineering as a behind-the-scenes support function. A successful platform team adopts a &lt;strong&gt;product mindset&lt;/strong&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Prioritize developer needs&lt;/li&gt;
&lt;li&gt;Gather feedback continuously&lt;/li&gt;
&lt;li&gt;Iterate on solutions&lt;/li&gt;
&lt;li&gt;Apply user research, roadmaps, versioning, and usability testing&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Build reusable, secure, and well-abstracted building blocks that simplify development while maintaining guardrails for security and compliance.&lt;/p&gt;
&lt;h3 id=&quot;start-small-mvp-and-tvp&quot; tabindex=&quot;-1&quot;&gt;Start Small: MVP and TVP&lt;/h3&gt;
&lt;p&gt;Don&#39;t try to build the perfect platform from scratch.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;MVP (Minimum Viable Product)&lt;/strong&gt;: A minimal, well-focused version that delivers early value based on continuous feedback&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;TVP (Thinnest Viable Platform)&lt;/strong&gt;: Allocate resources properly throughout the platform lifecycle&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;focus-on-developer-experience&quot; tabindex=&quot;-1&quot;&gt;Focus on Developer Experience&lt;/h3&gt;
&lt;p&gt;A well-structured platform team optimizes for DevEx by:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Providing self-service capabilities&lt;/li&gt;
&lt;li&gt;Offering standardized environments (test, staging, production)&lt;/li&gt;
&lt;li&gt;Reducing friction in the development process&lt;/li&gt;
&lt;li&gt;Using internal developer portals for unified logging, monitoring, and service discovery&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;foster-collaboration&quot; tabindex=&quot;-1&quot;&gt;Foster Collaboration&lt;/h3&gt;
&lt;p&gt;Encourage communication and feedback between the platform team and its users. Communities of Practice (CoPs) are a great way to build this learning culture.&lt;/p&gt;
&lt;h3 id=&quot;define-clear-metrics&quot; tabindex=&quot;-1&quot;&gt;Define Clear Metrics&lt;/h3&gt;
&lt;p&gt;Platform teams must track key performance metrics:&lt;/p&gt;
&lt;div class=&quot;blog-table&quot; role=&quot;region&quot; aria-label=&quot;Article table&quot; tabindex=&quot;0&quot;&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Metric&lt;/th&gt;
&lt;th&gt;What it measures&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Time to first deployment&lt;/td&gt;
&lt;td&gt;Onboarding friction&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Platform-related incidents&lt;/td&gt;
&lt;td&gt;System uptime and resilience&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Adoption rate&lt;/td&gt;
&lt;td&gt;Team usage&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Developer satisfaction&lt;/td&gt;
&lt;td&gt;DevEx quality&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;
&lt;h2 id=&quot;tldr&quot; tabindex=&quot;-1&quot;&gt;TL;DR&lt;/h2&gt;
&lt;p&gt;Platform engineering isn&#39;t just about managing infrastructure — it&#39;s about helping developers build and ship software efficiently.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Team topologies applied to platform teams:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;✅ Reduce cognitive load on developers&lt;/li&gt;
&lt;li&gt;✅ Foster collaboration between teams&lt;/li&gt;
&lt;li&gt;✅ Accelerate business outcomes&lt;/li&gt;
&lt;li&gt;✅ Deliver high-impact internal tooling&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Viewing platform engineering through team topologies provides a structured way to assess whether teams are set up for success and aligned with organizational goals.&lt;/p&gt;
&lt;h2 id=&quot;resources&quot; tabindex=&quot;-1&quot;&gt;Resources&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://teamtopologies.com/&quot;&gt;Team Topologies Book&lt;/a&gt; by Matthew Skelton and Manuel Pais&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://mia-platform.eu/blog/platform-teams/&quot;&gt;Platform Teams Guide&lt;/a&gt; — Mia-Platform&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://mia-platform.eu/blog/shift-down-to-the-platform/&quot;&gt;Shift Down to the Platform&lt;/a&gt; — Cognitive load explained&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
</content:encoded></item><item><title>GitHub Stacked PRs - How to Split Large Changes into Small PRs Without Losing Your Mind</title><link>https://resiz.es/blog/github-stacked-prs</link><guid isPermaLink="false">https://blog.resiz.es/github-stacked-prs</guid><pubDate>Fri, 17 Apr 2026 00:00:00 GMT</pubDate><description>The problem of giant PRs that nobody wants to review is universal. You open a pull request with 50 modified files and think: &quot;this is going to take days to review.&quot; Reviewers lose context, conflict…</description><content:encoded>&lt;p&gt;The problem of giant PRs that nobody wants to review is universal. You open a pull request with 50 modified files and think: &quot;this is going to take days to review.&quot; Reviewers lose context, conflicts pile up, and feedback gets fragmented.&lt;/p&gt;
&lt;p&gt;GitHub just launched &lt;strong&gt;gh-stack&lt;/strong&gt;, a native tool to manage &lt;strong&gt;Stacked PRs&lt;/strong&gt; — chained PRs that build on top of each other, independently reviewable but mergeable in cascade.&lt;/p&gt;
&lt;!--truncate--&gt;
&lt;h2 id=&quot;what-are-stacked-prs&quot; tabindex=&quot;-1&quot;&gt;What Are Stacked PRs?&lt;/h2&gt;
&lt;p&gt;A &lt;strong&gt;stack&lt;/strong&gt; is a chain of PRs where each PR has the previous PR&#39;s branch as its base:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot;&gt;&lt;code&gt;main ← PR1 (auth-layer) ← PR2 (api-routes) ← PR3 (frontend)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Key features:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Each PR shows &lt;strong&gt;only its diff&lt;/strong&gt;, not everything before it&lt;/li&gt;
&lt;li&gt;GitHub understands the full stack and shows a &lt;strong&gt;visual map&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Merge is &lt;strong&gt;in cascade&lt;/strong&gt;: merge PR1 → others automatically rebase&lt;/li&gt;
&lt;li&gt;Branch protection rules apply to the final branch (main), not intermediate ones&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;installation&quot; tabindex=&quot;-1&quot;&gt;Installation&lt;/h2&gt;
&lt;pre tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;hljs-comment&quot;&gt;# Install the extension&lt;/span&gt;
gh extension install github/gh-stack

&lt;span class=&quot;hljs-comment&quot;&gt;# Optional alias to type less&lt;/span&gt;
gh stack &lt;span class=&quot;hljs-built_in&quot;&gt;alias&lt;/span&gt;
&lt;span class=&quot;hljs-comment&quot;&gt;# Now you can use `gs` instead of `gh stack`&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;For AI coding agents&lt;/strong&gt; (GitHub Copilot, etc.):&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;npx skills add github/gh-stack
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This gives your AI agent context to create and manage stacks.&lt;/p&gt;
&lt;h2 id=&quot;basic-workflow&quot; tabindex=&quot;-1&quot;&gt;Basic Workflow&lt;/h2&gt;
&lt;h3 id=&quot;1-start-a-stack&quot; tabindex=&quot;-1&quot;&gt;1. Start a stack&lt;/h3&gt;
&lt;pre tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;hljs-built_in&quot;&gt;cd&lt;/span&gt; my-project
gh stack init
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;It will ask you to name your first branch. The stack uses the default branch (main) as trunk.&lt;/p&gt;
&lt;h3 id=&quot;2-work-on-the-first-layer&quot; tabindex=&quot;-1&quot;&gt;2. Work on the first layer&lt;/h3&gt;
&lt;pre tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;hljs-comment&quot;&gt;# ... write code ...&lt;/span&gt;
git add .
git commit -m &lt;span class=&quot;hljs-string&quot;&gt;&quot;Add auth middleware&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;3-add-layers-to-the-stack&quot; tabindex=&quot;-1&quot;&gt;3. Add layers to the stack&lt;/h3&gt;
&lt;pre tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;gh stack add api-routes

&lt;span class=&quot;hljs-comment&quot;&gt;# ... write code ...&lt;/span&gt;
git add .
git commit -m &lt;span class=&quot;hljs-string&quot;&gt;&quot;Add API routes&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;4-push-and-create-prs&quot; tabindex=&quot;-1&quot;&gt;4. Push and create PRs&lt;/h3&gt;
&lt;pre tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;gh stack push      &lt;span class=&quot;hljs-comment&quot;&gt;# Push all branches&lt;/span&gt;
gh stack submit    &lt;span class=&quot;hljs-comment&quot;&gt;# Create PRs and link them as a stack&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;5-view-the-status&quot; tabindex=&quot;-1&quot;&gt;5. View the status&lt;/h3&gt;
&lt;pre tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;gh stack view
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Shows all branches, links to PRs, CI status, and last commit.&lt;/p&gt;
&lt;h2 id=&quot;cascade-merge-the-magic-behind-it&quot; tabindex=&quot;-1&quot;&gt;Cascade Merge: The Magic Behind It&lt;/h2&gt;
&lt;p&gt;When you&#39;re ready to merge:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Partial merge:&lt;/strong&gt; You can merge only the lower PRs. The rest automatically rebase.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Full merge:&lt;/strong&gt; Merge all PRs in the stack with one click.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Automatic rebase:&lt;/strong&gt; After merge, remaining PRs update themselves.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;Visual example:&lt;/strong&gt;&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot;&gt;&lt;code&gt;main ← PR1 (auth) ← PR2 (api) ← PR3 (frontend)
       ↓ merge PR1
main ←────────────── PR2 (api) ← PR3 (frontend)
                         ↓ merge PR2
main ←──────────────────────────── PR3 (frontend)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;No branch conflicts. GitHub handles everything.&lt;/p&gt;
&lt;h2 id=&quot;ideal-use-cases&quot; tabindex=&quot;-1&quot;&gt;Ideal Use Cases&lt;/h2&gt;
&lt;h3 id=&quot;large-features-in-parallel-development&quot; tabindex=&quot;-1&quot;&gt;Large features in parallel development&lt;/h3&gt;
&lt;p&gt;You&#39;re working on a feature with 3 parts: backend, API, frontend. With stacks:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Create PR1 with the backend&lt;/li&gt;
&lt;li&gt;While it&#39;s being reviewed, add PR2 with the API (on top of PR1)&lt;/li&gt;
&lt;li&gt;While both are being reviewed, add PR3 with frontend (on top of PR2)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Everything gets reviewed in parallel, but each reviewer only sees their part.&lt;/p&gt;
&lt;h3 id=&quot;layered-refactors&quot; tabindex=&quot;-1&quot;&gt;Layered refactors&lt;/h3&gt;
&lt;p&gt;You want to refactor the auth system:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;PR1: New folder structure&lt;/li&gt;
&lt;li&gt;PR2: Move logic to services&lt;/li&gt;
&lt;li&gt;PR3: Update tests&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Each change is independently reviewable.&lt;/p&gt;
&lt;h3 id=&quot;multi-team-reviews&quot; tabindex=&quot;-1&quot;&gt;Multi-team reviews&lt;/h3&gt;
&lt;p&gt;One team reviews the backend, another the frontend. With stacks, each team only sees what concerns them.&lt;/p&gt;
&lt;h2 id=&quot;quick-cli-reference&quot; tabindex=&quot;-1&quot;&gt;Quick CLI Reference&lt;/h2&gt;
&lt;div class=&quot;blog-table&quot; role=&quot;region&quot; aria-label=&quot;Article table&quot; tabindex=&quot;0&quot;&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Command&lt;/th&gt;
&lt;th&gt;What it does&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;gs init&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Start a new stack&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;gs add &amp;lt;name&amp;gt;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Add a layer to the stack&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;gs push&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Push all branches&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;gs submit&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Create PRs on GitHub&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;gs view&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Show stack status&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;gs rebase&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Rebase the entire stack&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;gs merge&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Merge stack PRs&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;
&lt;h2 id=&quot;comparison-with-other-tools&quot; tabindex=&quot;-1&quot;&gt;Comparison with Other Tools&lt;/h2&gt;
&lt;div class=&quot;blog-table&quot; role=&quot;region&quot; aria-label=&quot;Article table&quot; tabindex=&quot;0&quot;&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Tool&lt;/th&gt;
&lt;th&gt;gh-stack&lt;/th&gt;
&lt;th&gt;Graphite&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Integration&lt;/td&gt;
&lt;td&gt;Native to GitHub&lt;/td&gt;
&lt;td&gt;External service&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;CLI&lt;/td&gt;
&lt;td&gt;&lt;code&gt;gh stack&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;gt&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;UI in GitHub&lt;/td&gt;
&lt;td&gt;Yes, stack map&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Configuration&lt;/td&gt;
&lt;td&gt;Zero setup&lt;/td&gt;
&lt;td&gt;Requires setup&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Price&lt;/td&gt;
&lt;td&gt;Free&lt;/td&gt;
&lt;td&gt;Freemium&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;
&lt;h2 id=&quot;tldr&quot; tabindex=&quot;-1&quot;&gt;TL;DR&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;gh-stack&lt;/strong&gt; solves the large PR problem by letting you:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;✅ Split changes into focused layers&lt;/li&gt;
&lt;li&gt;✅ Maintain context in each review&lt;/li&gt;
&lt;li&gt;✅ Cascade merge without headaches&lt;/li&gt;
&lt;li&gt;✅ Work in parallel without blockers&lt;/li&gt;
&lt;li&gt;✅ Everything integrated natively in GitHub&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Install and try:&lt;/strong&gt;&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;gh extension install github/gh-stack
&lt;span class=&quot;hljs-built_in&quot;&gt;cd&lt;/span&gt; your-repo
gh stack init
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;resources&quot; tabindex=&quot;-1&quot;&gt;Resources&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://github.github.com/gh-stack/&quot;&gt;Official Documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.github.com/gh-stack/getting-started/quick-start/&quot;&gt;Quick Start Guide&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.github.com/gh-stack/reference/cli/&quot;&gt;CLI Reference&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</content:encoded></item><item><title>Automating Dependency Updates with Renovate Bot (for Any Language)</title><link>https://resiz.es/blog/automating-dependency-updates-renovate-bot</link><guid isPermaLink="false">https://blog.resiz.es/automating-dependency-updates-renovate-bot</guid><pubDate>Mon, 10 Nov 2025 00:00:00 GMT</pubDate><description>Automating Dependency Updates with Renovate Bot (for Any Language) Keeping dependencies up to date is one of those things that everyone agrees is important… and yet no one enjoys doing. Between ver…</description><content:encoded>&lt;h2 id=&quot;automating-dependency-updates-with-renovate-bot-for-any-language&quot; tabindex=&quot;-1&quot;&gt;Automating Dependency Updates with Renovate Bot (for Any Language)&lt;/h2&gt;
&lt;p&gt;Keeping dependencies up to date is one of those things that everyone agrees is important… and yet no one enjoys doing.&lt;/p&gt;
&lt;p&gt;Between version pinning, breaking changes, and endless &lt;code&gt;npm audit&lt;/code&gt; noise, it’s easy for dependency updates to pile up. The result? A pile of technical debt that will keep growing and growing.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Renovate Bot is one of those tools that quietly removes that pain&lt;/strong&gt;. It just runs in the background, opens clean pull requests when something is outdated, and — if you let it — merges them once your tests pass. You barely have to think about it.&lt;/p&gt;
&lt;!--truncate--&gt;
&lt;h2 id=&quot;what-is-renovate&quot; tabindex=&quot;-1&quot;&gt;What is renovate&lt;/h2&gt;
&lt;p&gt;Renovate is an open-source tool (by Mend) that &lt;strong&gt;automates dependency updates&lt;/strong&gt; across basically any language or ecosystem. It supports npm, pip, Terraform, Docker, Maven, Go modules, and a bunch more.&lt;/p&gt;
&lt;p&gt;At a high level, Renovate:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Scans your repo for dependencies.&lt;/li&gt;
&lt;li&gt;Checks if newer versions are available.&lt;/li&gt;
&lt;li&gt;Creates pull requests with the updates.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;It is possible to fully customize how this process works: &lt;em&gt;When&lt;/em&gt; it runs, &lt;em&gt;how&lt;/em&gt; PRs are grouped or &lt;em&gt;which&lt;/em&gt; dependencies not to update.&lt;/p&gt;
&lt;h2 id=&quot;why-it-matters&quot; tabindex=&quot;-1&quot;&gt;Why it matters&lt;/h2&gt;
&lt;h3 id=&quot;security-first-angle&quot; tabindex=&quot;-1&quot;&gt;Security-First Angle&lt;/h3&gt;
&lt;p&gt;Even if your app passes SAST or container scans, outdated dependencies can hide vulnerabilities.
This is what’s called &lt;strong&gt;dependency drift&lt;/strong&gt; — everything still runs, but the libraries you’re using have quietly accumulated known CVEs over time.&lt;/p&gt;
&lt;p&gt;For example, a project might still be using &lt;code&gt;lodash@4.17.19&lt;/code&gt; from a few years ago, even though several security patches have been released since. You won’t notice until an audit tool starts screaming, or worse — until someone exploits it.&lt;/p&gt;
&lt;p&gt;Renovate helps close that gap. As soon as a patched version is available, it can automatically open a PR. In many teams, these small bumps (minor or patch releases) are auto-merged if tests pass.&lt;/p&gt;
&lt;p&gt;It’s not a replacement for scanners like &lt;strong&gt;Trivy, Semgrep, or Trufflehog&lt;/strong&gt; — it’s the thing that &lt;strong&gt;keeps their results relevant&lt;/strong&gt;. They catch issues, Renovate makes sure those issues don’t come back.&lt;/p&gt;
&lt;h3 id=&quot;productivity-and-workflow-enhancements&quot; tabindex=&quot;-1&quot;&gt;Productivity and Workflow Enhancements&lt;/h3&gt;
&lt;p&gt;There’s also the human side. &lt;strong&gt;Manually tracking versions is boring&lt;/strong&gt;, repetitive work that burns cognitive energy.
A typical microservice might have 30–50 dependencies — checking each one regularly can take hours every month.&lt;/p&gt;
&lt;p&gt;With Renovate, that time disappears. You just get small, tidy pull requests that you can merge when ready (or let CI handle it).&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&quot;renovate-or-dependabot&quot; tabindex=&quot;-1&quot;&gt;Renovate or Dependabot?&lt;/h2&gt;
&lt;p&gt;So far, we’ve talked about all the cool parts of Renovate — but there’s one big drawback: because it’s so customizable, the configuration can get a bit dense.&lt;/p&gt;
&lt;p&gt;On the other hand, you’ve probably heard of Dependabot — hard not to, since GitHub shows it to you almost every day. But is it better or worse than Renovate? Which one should you actually use?&lt;/p&gt;
&lt;p&gt;At first glance, both bots do the same thing: keep your dependencies up to date. But &lt;strong&gt;Dependabot’s main goal is simplicity&lt;/strong&gt; — a couple of clicks and you’re done. The trade-off is that you get zero configuration and, often, a flood of pull requests all at once, which can add a lot of overhead for your team.&lt;/p&gt;
&lt;p&gt;Personally, &lt;strong&gt;I stick with Renovate&lt;/strong&gt; because it lets me fine-tune the behavior exactly how I want it. If you prefer, you can still keep Dependabot around just for security alerts, or complement Renovate with a proper SAST stack (like the one we use &lt;a href=&quot;https://resiz.es/blog/static-code-analysis&quot;&gt;here...&lt;/a&gt;)&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&quot;how-renovate-works&quot; tabindex=&quot;-1&quot;&gt;How renovate works&lt;/h2&gt;
&lt;p&gt;When Renovate runs, it:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Looks for dependency files in your repo (package.json, requirements.txt, .tf, etc.).&lt;/li&gt;
&lt;li&gt;Checks the latest versions from the relevant registry.&lt;/li&gt;
&lt;li&gt;Compares against your current versions and your config rules.&lt;/li&gt;
&lt;li&gt;Opens a PR with changelogs, diffs, and a test run.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;That’s it. The magic comes from how much you can configure it.
&lt;img src=&quot;https://resiz.es/assets/blog/posts/2025-11-10-renovate/PR-screenshot.png&quot; alt=&quot;A sample PR created by Renovate&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&quot;step-by-step-integration-guide&quot; tabindex=&quot;-1&quot;&gt;Step-by-Step integration guide&lt;/h2&gt;
&lt;h3 id=&quot;option-1-github-app-simple-setup&quot; tabindex=&quot;-1&quot;&gt;Option 1: GitHub App (simple setup)&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;Go to &lt;a href=&quot;https://github.com/apps/renovate&quot;&gt;github.com/apps/renovate&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Install it on your repo&lt;/li&gt;
&lt;li&gt;Merge the onboarding PR it creates&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;That’s it. Renovate will start sending PRs.&lt;/p&gt;
&lt;h3 id=&quot;option-2-github-action-fit-to-your-needs&quot; tabindex=&quot;-1&quot;&gt;Option 2: GitHub Action (fit to your needs)&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Create your own GitHub App for renovate&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;ul&gt;
&lt;li&gt;Click on your profile picture → &lt;code&gt;Settings&lt;/code&gt; → &lt;code&gt;Your Organization&lt;/code&gt; → &lt;code&gt;Settings&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Clock on the &lt;code&gt;Developer settings&lt;/code&gt; → &lt;code&gt;GitHub Apps&lt;/code&gt; → &lt;code&gt;New GitHub App&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Fulfill the form:
&lt;ul&gt;
&lt;li&gt;The &lt;code&gt;GitHub App name&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;Description&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;Homepage URL&lt;/code&gt;: Set your organization or your personal profile URL.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Any problem? Take a look at the &lt;a href=&quot;https://docs.github.com/en/apps/creating-github-apps/registering-a-github-app/registering-a-github-app&quot;&gt;GitHub&#39;s Documentation on Creating GitHub Apps&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;ol start=&quot;2&quot;&gt;
&lt;li&gt;&lt;strong&gt;Add your own GitHub Secrets as a Organization Level Secret&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;RENOVATE_APP_ID&lt;/code&gt;: The ID of your GitHub App.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;RENOVATE_APP_PRIVATE_KEY&lt;/code&gt;: The full private key of your GitHub App.&lt;/li&gt;
&lt;/ul&gt;
&lt;ol start=&quot;3&quot;&gt;
&lt;li&gt;&lt;strong&gt;Create your own &lt;code&gt;renovate.json&lt;/code&gt;:&lt;/strong&gt;
You can use this as a template and adapt it to your needs later on. Add it to your repo&#39;s root level:&lt;/li&gt;
&lt;/ol&gt;
&lt;pre tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;&lt;span class=&quot;hljs-punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;hljs-attr&quot;&gt;&quot;$schema&quot;&lt;/span&gt;&lt;span class=&quot;hljs-punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;https://docs.renovatebot.com/renovate-schema.json&quot;&lt;/span&gt;&lt;span class=&quot;hljs-punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;hljs-attr&quot;&gt;&quot;extends&quot;&lt;/span&gt;&lt;span class=&quot;hljs-punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;hljs-punctuation&quot;&gt;[&lt;/span&gt;
        &lt;span class=&quot;hljs-string&quot;&gt;&quot;config:recommended&quot;&lt;/span&gt;&lt;span class=&quot;hljs-punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;hljs-string&quot;&gt;&quot;:dependencyDashboard&quot;&lt;/span&gt;&lt;span class=&quot;hljs-punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;hljs-string&quot;&gt;&quot;:semanticCommits&quot;&lt;/span&gt;&lt;span class=&quot;hljs-punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;hljs-string&quot;&gt;&quot;:automergeBranch&quot;&lt;/span&gt;
    &lt;span class=&quot;hljs-punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;hljs-punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;hljs-attr&quot;&gt;&quot;timezone&quot;&lt;/span&gt;&lt;span class=&quot;hljs-punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;Europe/London&quot;&lt;/span&gt;&lt;span class=&quot;hljs-punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;hljs-attr&quot;&gt;&quot;schedule&quot;&lt;/span&gt;&lt;span class=&quot;hljs-punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;hljs-punctuation&quot;&gt;[&lt;/span&gt;
        &lt;span class=&quot;hljs-string&quot;&gt;&quot;at any time&quot;&lt;/span&gt;
    &lt;span class=&quot;hljs-punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;hljs-punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;hljs-attr&quot;&gt;&quot;labels&quot;&lt;/span&gt;&lt;span class=&quot;hljs-punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;hljs-punctuation&quot;&gt;[&lt;/span&gt;
        &lt;span class=&quot;hljs-string&quot;&gt;&quot;renovate&quot;&lt;/span&gt;&lt;span class=&quot;hljs-punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;hljs-string&quot;&gt;&quot;terraform&quot;&lt;/span&gt;
    &lt;span class=&quot;hljs-punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;hljs-punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;hljs-attr&quot;&gt;&quot;assignees&quot;&lt;/span&gt;&lt;span class=&quot;hljs-punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;hljs-punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;hljs-punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;hljs-punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;hljs-attr&quot;&gt;&quot;reviewers&quot;&lt;/span&gt;&lt;span class=&quot;hljs-punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;hljs-punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;hljs-punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;hljs-punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;hljs-attr&quot;&gt;&quot;prConcurrentLimit&quot;&lt;/span&gt;&lt;span class=&quot;hljs-punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;hljs-punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;hljs-attr&quot;&gt;&quot;prHourlyLimit&quot;&lt;/span&gt;&lt;span class=&quot;hljs-punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;hljs-punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;hljs-attr&quot;&gt;&quot;rebaseWhen&quot;&lt;/span&gt;&lt;span class=&quot;hljs-punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;conflicted&quot;&lt;/span&gt;&lt;span class=&quot;hljs-punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;hljs-attr&quot;&gt;&quot;lockFileMaintenance&quot;&lt;/span&gt;&lt;span class=&quot;hljs-punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;hljs-punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;hljs-attr&quot;&gt;&quot;enabled&quot;&lt;/span&gt;&lt;span class=&quot;hljs-punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;hljs-literal&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;false&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;hljs-punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;hljs-punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;hljs-attr&quot;&gt;&quot;digest&quot;&lt;/span&gt;&lt;span class=&quot;hljs-punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;hljs-punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;hljs-attr&quot;&gt;&quot;automerge&quot;&lt;/span&gt;&lt;span class=&quot;hljs-punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;hljs-literal&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;true&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;hljs-punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;hljs-punctuation&quot;&gt;,&lt;/span&gt;

    &lt;span class=&quot;hljs-attr&quot;&gt;&quot;packageRules&quot;&lt;/span&gt;&lt;span class=&quot;hljs-punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;hljs-punctuation&quot;&gt;[&lt;/span&gt;
        &lt;span class=&quot;hljs-punctuation&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;hljs-attr&quot;&gt;&quot;description&quot;&lt;/span&gt;&lt;span class=&quot;hljs-punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;Terraform providers and modules&quot;&lt;/span&gt;&lt;span class=&quot;hljs-punctuation&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;hljs-attr&quot;&gt;&quot;matchManagers&quot;&lt;/span&gt;&lt;span class=&quot;hljs-punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;hljs-punctuation&quot;&gt;[&lt;/span&gt;
                &lt;span class=&quot;hljs-string&quot;&gt;&quot;terraform&quot;&lt;/span&gt;
            &lt;span class=&quot;hljs-punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;hljs-punctuation&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;hljs-attr&quot;&gt;&quot;commitMessageTopic&quot;&lt;/span&gt;&lt;span class=&quot;hljs-punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;Terraform {{depName}}&quot;&lt;/span&gt;&lt;span class=&quot;hljs-punctuation&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;hljs-attr&quot;&gt;&quot;pinDigests&quot;&lt;/span&gt;&lt;span class=&quot;hljs-punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;hljs-literal&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;false&lt;/span&gt;&lt;/span&gt;
        &lt;span class=&quot;hljs-punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;hljs-punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;hljs-punctuation&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;hljs-attr&quot;&gt;&quot;matchManagers&quot;&lt;/span&gt;&lt;span class=&quot;hljs-punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;hljs-punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;hljs-string&quot;&gt;&quot;nvm&quot;&lt;/span&gt;&lt;span class=&quot;hljs-punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;node-version&quot;&lt;/span&gt;&lt;span class=&quot;hljs-punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;asdf&quot;&lt;/span&gt;&lt;span class=&quot;hljs-punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;hljs-punctuation&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;hljs-attr&quot;&gt;&quot;groupName&quot;&lt;/span&gt;&lt;span class=&quot;hljs-punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;Node.js version&quot;&lt;/span&gt;&lt;span class=&quot;hljs-punctuation&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;hljs-attr&quot;&gt;&quot;groupSlug&quot;&lt;/span&gt;&lt;span class=&quot;hljs-punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;node-version&quot;&lt;/span&gt;&lt;span class=&quot;hljs-punctuation&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;hljs-attr&quot;&gt;&quot;semanticCommitType&quot;&lt;/span&gt;&lt;span class=&quot;hljs-punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;chore&quot;&lt;/span&gt;&lt;span class=&quot;hljs-punctuation&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;hljs-attr&quot;&gt;&quot;semanticCommitScope&quot;&lt;/span&gt;&lt;span class=&quot;hljs-punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;node&quot;&lt;/span&gt;&lt;span class=&quot;hljs-punctuation&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;hljs-attr&quot;&gt;&quot;commitMessageTopic&quot;&lt;/span&gt;&lt;span class=&quot;hljs-punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;Node.js version&quot;&lt;/span&gt;&lt;span class=&quot;hljs-punctuation&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;hljs-attr&quot;&gt;&quot;commitMessageExtra&quot;&lt;/span&gt;&lt;span class=&quot;hljs-punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;update Node.js runtime version&quot;&lt;/span&gt;
          &lt;span class=&quot;hljs-punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;hljs-punctuation&quot;&gt;,&lt;/span&gt;
          &lt;span class=&quot;hljs-punctuation&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;hljs-attr&quot;&gt;&quot;matchManagers&quot;&lt;/span&gt;&lt;span class=&quot;hljs-punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;hljs-punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;hljs-string&quot;&gt;&quot;npm&quot;&lt;/span&gt;&lt;span class=&quot;hljs-punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;hljs-punctuation&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;hljs-attr&quot;&gt;&quot;groupName&quot;&lt;/span&gt;&lt;span class=&quot;hljs-punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;npm dependencies&quot;&lt;/span&gt;&lt;span class=&quot;hljs-punctuation&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;hljs-attr&quot;&gt;&quot;semanticCommitType&quot;&lt;/span&gt;&lt;span class=&quot;hljs-punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;chore&quot;&lt;/span&gt;&lt;span class=&quot;hljs-punctuation&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;hljs-attr&quot;&gt;&quot;semanticCommitScope&quot;&lt;/span&gt;&lt;span class=&quot;hljs-punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;deps&quot;&lt;/span&gt;
          &lt;span class=&quot;hljs-punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;hljs-punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;hljs-punctuation&quot;&gt;,&lt;/span&gt;
  
    &lt;span class=&quot;hljs-attr&quot;&gt;&quot;npm&quot;&lt;/span&gt;&lt;span class=&quot;hljs-punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;hljs-punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;hljs-attr&quot;&gt;&quot;enabled&quot;&lt;/span&gt;&lt;span class=&quot;hljs-punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;hljs-literal&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;true&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;hljs-punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;hljs-punctuation&quot;&gt;,&lt;/span&gt;
  
    &lt;span class=&quot;hljs-attr&quot;&gt;&quot;nvm&quot;&lt;/span&gt;&lt;span class=&quot;hljs-punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;hljs-punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;hljs-attr&quot;&gt;&quot;enabled&quot;&lt;/span&gt;&lt;span class=&quot;hljs-punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;hljs-literal&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;true&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;hljs-punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;hljs-punctuation&quot;&gt;,&lt;/span&gt;
  
    &lt;span class=&quot;hljs-attr&quot;&gt;&quot;asdf&quot;&lt;/span&gt;&lt;span class=&quot;hljs-punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;hljs-punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;hljs-attr&quot;&gt;&quot;enabled&quot;&lt;/span&gt;&lt;span class=&quot;hljs-punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;hljs-literal&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;true&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;hljs-punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;hljs-punctuation&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;ol start=&quot;4&quot;&gt;
&lt;li&gt;&lt;strong&gt;Invoke our reusable workflow from your repo:&lt;/strong&gt; You can use our reusable workflow from our &lt;a href=&quot;https://github.com/resizes/github-actions/blob/main/.github/workflows/renovate.yml&quot;&gt;GitHub Actions repo&lt;/a&gt;:&lt;/li&gt;
&lt;/ol&gt;
&lt;pre tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;&lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;Renovate&lt;/span&gt;

&lt;span class=&quot;hljs-attr&quot;&gt;on:&lt;/span&gt;
  &lt;span class=&quot;hljs-attr&quot;&gt;schedule:&lt;/span&gt;
  &lt;span class=&quot;hljs-comment&quot;&gt;# Run every Monday at 5:00 AM UTC&lt;/span&gt;
  &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;cron:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&#39;0 5 * * 1&#39;&lt;/span&gt;
  &lt;span class=&quot;hljs-attr&quot;&gt;workflow_dispatch:&lt;/span&gt;
    &lt;span class=&quot;hljs-attr&quot;&gt;inputs:&lt;/span&gt;
      &lt;span class=&quot;hljs-attr&quot;&gt;log_level:&lt;/span&gt;
        &lt;span class=&quot;hljs-attr&quot;&gt;description:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&#39;Log level&#39;&lt;/span&gt;
        &lt;span class=&quot;hljs-attr&quot;&gt;required:&lt;/span&gt; &lt;span class=&quot;hljs-literal&quot;&gt;false&lt;/span&gt;
        &lt;span class=&quot;hljs-attr&quot;&gt;default:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&#39;info&#39;&lt;/span&gt;
        &lt;span class=&quot;hljs-attr&quot;&gt;type:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;choice&lt;/span&gt;
        &lt;span class=&quot;hljs-attr&quot;&gt;options:&lt;/span&gt;
        &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;info&lt;/span&gt;
        &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;debug&lt;/span&gt;
        &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;trace&lt;/span&gt;
      &lt;span class=&quot;hljs-attr&quot;&gt;dry_run:&lt;/span&gt;
        &lt;span class=&quot;hljs-attr&quot;&gt;description:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&#39;Dry run (no PRs will be created)&#39;&lt;/span&gt;
        &lt;span class=&quot;hljs-attr&quot;&gt;required:&lt;/span&gt; &lt;span class=&quot;hljs-literal&quot;&gt;false&lt;/span&gt;
        &lt;span class=&quot;hljs-attr&quot;&gt;default:&lt;/span&gt; &lt;span class=&quot;hljs-literal&quot;&gt;false&lt;/span&gt;
        &lt;span class=&quot;hljs-attr&quot;&gt;type:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;boolean&lt;/span&gt;
      &lt;span class=&quot;hljs-attr&quot;&gt;force_refresh:&lt;/span&gt;
        &lt;span class=&quot;hljs-attr&quot;&gt;description:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&#39;Force refresh all dependencies&#39;&lt;/span&gt;
        &lt;span class=&quot;hljs-attr&quot;&gt;required:&lt;/span&gt; &lt;span class=&quot;hljs-literal&quot;&gt;false&lt;/span&gt;
        &lt;span class=&quot;hljs-attr&quot;&gt;default:&lt;/span&gt; &lt;span class=&quot;hljs-literal&quot;&gt;false&lt;/span&gt;
        &lt;span class=&quot;hljs-attr&quot;&gt;type:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;boolean&lt;/span&gt;

&lt;span class=&quot;hljs-attr&quot;&gt;permissions:&lt;/span&gt;
  &lt;span class=&quot;hljs-attr&quot;&gt;contents:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;write&lt;/span&gt; &lt;span class=&quot;hljs-comment&quot;&gt;# To create branches and commits&lt;/span&gt;
  &lt;span class=&quot;hljs-attr&quot;&gt;pull-requests:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;write&lt;/span&gt; &lt;span class=&quot;hljs-comment&quot;&gt;# To create and update pull requests&lt;/span&gt;
  &lt;span class=&quot;hljs-attr&quot;&gt;issues:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;write&lt;/span&gt; &lt;span class=&quot;hljs-comment&quot;&gt;# For dependency dashboard (if enabled)&lt;/span&gt;
  &lt;span class=&quot;hljs-attr&quot;&gt;checks:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;read&lt;/span&gt; &lt;span class=&quot;hljs-comment&quot;&gt;# To read check status&lt;/span&gt;
  &lt;span class=&quot;hljs-attr&quot;&gt;statuses:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;read&lt;/span&gt; &lt;span class=&quot;hljs-comment&quot;&gt;# To read commit statuses&lt;/span&gt;
  &lt;span class=&quot;hljs-attr&quot;&gt;actions:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;read&lt;/span&gt; &lt;span class=&quot;hljs-comment&quot;&gt;# To read workflow runs&lt;/span&gt;
  &lt;span class=&quot;hljs-attr&quot;&gt;security-events:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;read&lt;/span&gt; &lt;span class=&quot;hljs-comment&quot;&gt;# To read security events&lt;/span&gt;

&lt;span class=&quot;hljs-attr&quot;&gt;jobs:&lt;/span&gt;
  &lt;span class=&quot;hljs-attr&quot;&gt;renovate:&lt;/span&gt;
    &lt;span class=&quot;hljs-attr&quot;&gt;uses:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;resizes/github-actions/.github/workflows/renovate.yml@v1&lt;/span&gt;
    &lt;span class=&quot;hljs-attr&quot;&gt;with:&lt;/span&gt;
      &lt;span class=&quot;hljs-attr&quot;&gt;log_level:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;${{&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;inputs.log_level&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;}}&lt;/span&gt;
      &lt;span class=&quot;hljs-attr&quot;&gt;dry_run:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;${{&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;inputs.dry_run&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;}}&lt;/span&gt;
      &lt;span class=&quot;hljs-attr&quot;&gt;force_refresh:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;${{&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;inputs.force_refresh&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;}}&lt;/span&gt;
      &lt;span class=&quot;hljs-attr&quot;&gt;runner:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&#39;ubuntu-latest&#39;&lt;/span&gt;
      &lt;span class=&quot;hljs-attr&quot;&gt;github_app_id:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;${{&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;secrets.RENOVATE_APP_ID&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;}}&lt;/span&gt;
      &lt;span class=&quot;hljs-attr&quot;&gt;owner:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&#39;Resizes&#39;&lt;/span&gt;
      &lt;span class=&quot;hljs-attr&quot;&gt;repositories:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;|
        &amp;lt;Your repository&amp;gt;
&lt;/span&gt;    &lt;span class=&quot;hljs-attr&quot;&gt;secrets:&lt;/span&gt;
      &lt;span class=&quot;hljs-attr&quot;&gt;github_app_private_key:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;${{&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;secrets.RENOVATE_APP_PRIVATE_KEY&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;}}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;hr&gt;
&lt;h2 id=&quot;real-examples&quot; tabindex=&quot;-1&quot;&gt;Real examples&lt;/h2&gt;
&lt;h3 id=&quot;nodejs-monorepo&quot; tabindex=&quot;-1&quot;&gt;Node.js monorepo&lt;/h3&gt;
&lt;p&gt;We use Renovate across several Node.js services. Instead of 10+ small PRs every week, we group all devDependency bumps into one.
&lt;strong&gt;Result: less noise, faster merges.&lt;/strong&gt;&lt;/p&gt;
&lt;h3 id=&quot;terraform-infra-repo&quot; tabindex=&quot;-1&quot;&gt;Terraform infra repo&lt;/h3&gt;
&lt;p&gt;Renovate updates our AWS provider versions automatically.
We used to forget about this for months — now infra updates are steady and predictable.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&quot;sample-renovatejson-entries&quot; tabindex=&quot;-1&quot;&gt;Sample renovate.json entries&lt;/h2&gt;
&lt;p&gt;So you saw before a full example on how to configure Renovate and you may have felt overwhelmed. But, let&#39;s take a look at some basic examples so you can build your own:&lt;/p&gt;
&lt;h3 id=&quot;the-just-works-setup&quot; tabindex=&quot;-1&quot;&gt;The ”Just Works” Setup&lt;/h3&gt;
&lt;p&gt;For example, you can use this as a quick configuration. It will follow the best practices while automerging minor and patch updates at a maximum rate of 2 PRs per hour.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;&lt;span class=&quot;hljs-punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;hljs-attr&quot;&gt;&quot;extends&quot;&lt;/span&gt;&lt;span class=&quot;hljs-punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;hljs-punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;hljs-string&quot;&gt;&quot;config:best-practices&quot;&lt;/span&gt;&lt;span class=&quot;hljs-punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;hljs-punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;hljs-attr&quot;&gt;&quot;automerge&quot;&lt;/span&gt;&lt;span class=&quot;hljs-punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;hljs-literal&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;true&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;hljs-punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;hljs-attr&quot;&gt;&quot;major&quot;&lt;/span&gt;&lt;span class=&quot;hljs-punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;hljs-punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;&quot;automerge&quot;&lt;/span&gt;&lt;span class=&quot;hljs-punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;hljs-literal&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;false&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;hljs-punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;hljs-punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;hljs-attr&quot;&gt;&quot;prHourlyLimit&quot;&lt;/span&gt;&lt;span class=&quot;hljs-punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt;
&lt;span class=&quot;hljs-punctuation&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;grouping-prs&quot; tabindex=&quot;-1&quot;&gt;Grouping PRs&lt;/h3&gt;
&lt;p&gt;So if you actually use the example above, for sure you have noticed that there is a lot of noise going on. So let&#39;s group some version updates in the same PR:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;&lt;span class=&quot;hljs-punctuation&quot;&gt;{&lt;/span&gt;
  (...)
  &lt;span class=&quot;hljs-attr&quot;&gt;&quot;packageRules&quot;&lt;/span&gt;&lt;span class=&quot;hljs-punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;hljs-punctuation&quot;&gt;[&lt;/span&gt;
    &lt;span class=&quot;hljs-punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;hljs-attr&quot;&gt;&quot;groupName&quot;&lt;/span&gt;&lt;span class=&quot;hljs-punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;Dev Dependencies&quot;&lt;/span&gt;&lt;span class=&quot;hljs-punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;hljs-attr&quot;&gt;&quot;matchDepTypes&quot;&lt;/span&gt;&lt;span class=&quot;hljs-punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;hljs-punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;hljs-string&quot;&gt;&quot;devDependencies&quot;&lt;/span&gt;&lt;span class=&quot;hljs-punctuation&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;hljs-punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;hljs-punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;hljs-punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;hljs-attr&quot;&gt;&quot;groupName&quot;&lt;/span&gt;&lt;span class=&quot;hljs-punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;AWS SDKs&quot;&lt;/span&gt;&lt;span class=&quot;hljs-punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;hljs-attr&quot;&gt;&quot;matchPackagePatterns&quot;&lt;/span&gt;&lt;span class=&quot;hljs-punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;hljs-punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;hljs-string&quot;&gt;&quot;^aws&quot;&lt;/span&gt;&lt;span class=&quot;hljs-punctuation&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;hljs-punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;hljs-punctuation&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;hljs-punctuation&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now, all the devDependencies will be shown in a single PR. Same with all AWS related too.&lt;/p&gt;
&lt;h3 id=&quot;prs-only-when-team-is-working&quot; tabindex=&quot;-1&quot;&gt;PRs only when team is working&lt;/h3&gt;
&lt;p&gt;Renovate may have opened a PR at a moment where no one was at the office and thought &lt;em&gt;could the PRs be created at a schedule?&lt;/em&gt;. Good news - you can!&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;&lt;span class=&quot;hljs-punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;hljs-attr&quot;&gt;&quot;schedule&quot;&lt;/span&gt;&lt;span class=&quot;hljs-punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;hljs-punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;hljs-string&quot;&gt;&quot;after 9am every monday&quot;&lt;/span&gt;&lt;span class=&quot;hljs-punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;before 5pm every monday&quot;&lt;/span&gt;&lt;span class=&quot;hljs-punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;hljs-punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;hljs-attr&quot;&gt;&quot;timezone&quot;&lt;/span&gt;&lt;span class=&quot;hljs-punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;UTC&quot;&lt;/span&gt;
&lt;span class=&quot;hljs-punctuation&quot;&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;
&lt;hr&gt;
&lt;h2 id=&quot;tips-from-experience&quot; tabindex=&quot;-1&quot;&gt;Tips From Experience&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Don’t enable automerge on day one — &lt;strong&gt;watch how your CI handles updates&lt;/strong&gt; first.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Group dependencies&lt;/strong&gt; logically, by framework or team ownership. This will decrease the noise in your team&#39;s inboxes.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Label security updates&lt;/strong&gt; clearly to make them easy to spot.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Merge the onboarding PR&lt;/strong&gt; — it’s not optional.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2 id=&quot;links-to-public-github-action-and-readme&quot; tabindex=&quot;-1&quot;&gt;Links to public GitHub Action and README&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/resizes/github-actions/blob/main/.github/workflows/renovate.yml&quot;&gt;GitHub Action&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/resizes/github-actions/blob/main/.github/workflows/&quot;&gt;README&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</content:encoded></item><item><title>Automating AWS IAM Identity Center with Terraform for Multi-Account Environments</title><link>https://resiz.es/blog/iam-identity-center</link><guid isPermaLink="false">https://blog.resiz.es/iam-identity-center</guid><pubDate>Tue, 28 Oct 2025 00:00:00 GMT</pubDate><description>Automating AWS IAM Identity Center with Terraform in Multi-Account Environments Managing access in AWS can seem simple at first: a few accounts, a handful of users, and permissions that are easy to…</description><content:encoded>&lt;h2 id=&quot;automating-aws-iam-identity-center-with-terraform-in-multi-account-environments&quot; tabindex=&quot;-1&quot;&gt;Automating AWS IAM Identity Center with Terraform in Multi-Account Environments&lt;/h2&gt;
&lt;p&gt;Managing access in AWS can seem simple at first: a few accounts, a handful of users, and permissions that are easy to control from the console. But as an organization grows — as accounts, teams, and roles multiply — that manual management becomes a problem. Errors accumulate, inconsistencies appear, and traceability fades.&lt;br&gt;
Who has access to what? What permissions does each user actually have? What changes were applied last week? These once-trivial questions become increasingly difficult to answer.&lt;/p&gt;
&lt;p&gt;That’s where &lt;strong&gt;AWS IAM Identity Center&lt;/strong&gt; (formerly AWS Single Sign-On) comes in. This service centralizes the management of identities and permissions across all your AWS accounts, letting you define from a single place &lt;strong&gt;who can access what&lt;/strong&gt;, and with which level of privilege. It also simplifies auditing and compliance by maintaining a consistent record of assignments and permissions.&lt;/p&gt;
&lt;p&gt;However, the existence of IAM Identity Center alone doesn’t solve scalability challenges — &lt;strong&gt;manual configuration doesn’t scale&lt;/strong&gt;. Each user, group, and permission set must be configured account by account, multiplying effort and increasing the likelihood of mistakes. Keeping environments consistent is difficult, and auditing changes becomes a tedious, unreliable process.&lt;br&gt;
In short: manual management isn’t sustainable in the long run.&lt;/p&gt;
&lt;p&gt;The solution lies in &lt;strong&gt;automating with Terraform&lt;/strong&gt;, leveraging the &lt;em&gt;Infrastructure as Code (IaC)&lt;/em&gt; approach. With Terraform, your entire configuration is defined in version-controlled files — you can review, replicate, and apply changes in a consistent and auditable way. This not only reduces errors but also turns access management into a scalable, controlled, and well-documented process.&lt;/p&gt;
&lt;!--truncate--&gt;
&lt;hr&gt;
&lt;p&gt;&lt;strong&gt;Before you start&lt;/strong&gt;, make sure you have the following:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;An &lt;strong&gt;AWS Organization&lt;/strong&gt; fully configured with all features enabled.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;IAM Identity Center&lt;/strong&gt; activated in the management account.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Terraform&lt;/strong&gt; installed, and credentials with permissions to access the &lt;strong&gt;Organizations&lt;/strong&gt; and &lt;strong&gt;SSO Admin&lt;/strong&gt; APIs.&lt;/li&gt;
&lt;li&gt;(Optional) A &lt;strong&gt;CI/CD pipeline&lt;/strong&gt; to apply changes centrally and maintain traceability.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2 id=&quot;structuring-iam-identity-center-automation-with-terraform&quot; tabindex=&quot;-1&quot;&gt;Structuring IAM Identity Center Automation with Terraform&lt;/h2&gt;
&lt;p&gt;When you think of IAM Identity Center through the Terraform lens, the goal is to mirror its real-world structure in code. Each entity (users, groups, permissions, and assignments) becomes a block you can define, modify, and version.&lt;/p&gt;
&lt;p&gt;👤 &lt;strong&gt;Users&lt;/strong&gt;&lt;br&gt;
Users represent the people who need access to your AWS accounts. In Terraform, you define their basic data — name, email, full name — and associate them with groups. This avoids assigning permissions individually to each user and allows for consistent role-based management.&lt;/p&gt;
&lt;p&gt;👥 &lt;strong&gt;Groups&lt;/strong&gt;&lt;br&gt;
Groups gather users who share similar responsibilities or functions, such as “Developers”, “Billing”, or “SecurityOps”. Instead of granting permissions user by user, you assign them to groups, which greatly simplifies management and reduces human error.&lt;/p&gt;
&lt;p&gt;🧾 &lt;strong&gt;Permission Sets&lt;/strong&gt;&lt;br&gt;
Permission sets are the core component: they define &lt;em&gt;what a user or group can do&lt;/em&gt;. They can consist of AWS-managed policies (like &lt;code&gt;ReadOnlyAccess&lt;/code&gt;) or &lt;strong&gt;custom inline policies&lt;/strong&gt; that grant specific access — for example, read-only access to certain S3 buckets or the ability to list EC2 instances.&lt;br&gt;
This modular design lets you reuse the same permission sets across different accounts or groups, ensuring consistency and simplifying audits.&lt;/p&gt;
&lt;p&gt;🗂️ &lt;strong&gt;Account Assignments&lt;/strong&gt;&lt;br&gt;
Finally, account assignments connect groups and permission sets to specific AWS accounts. A single group can have different access levels depending on the account — for example, “Developer” with read-only access in production but write access in staging.&lt;br&gt;
This clear relationship between &lt;em&gt;who&lt;/em&gt;, &lt;em&gt;what&lt;/em&gt;, and &lt;em&gt;where&lt;/em&gt; turns access management into a predictable and auditable system.&lt;/p&gt;
&lt;h3 id=&quot;terraform-configuration-example&quot; tabindex=&quot;-1&quot;&gt;Terraform Configuration Example&lt;/h3&gt;
&lt;p&gt;Here’s an example showing how to define a group, a user, a permission set, and an account assignment in a single module — giving you a &lt;strong&gt;complete picture&lt;/strong&gt; of how the structure fits together:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-hcl&quot;&gt;module &quot;aws-iam-identity-center&quot; {
  source  = &quot;aws-ia/iam-identity-center/aws&quot;
  version = &quot;1.0.2&quot;

  # -----------------------------
  # Groups
  # -----------------------------
  sso_groups = {
    Developers = {
      group_name        = &quot;Developers&quot;
      group_description = &quot;Group for development team&quot;
    }
  }

  # -----------------------------
  # Users
  # -----------------------------
  sso_users = {
    ana = {
      group_membership = [&quot;Developers&quot;]
      user_name        = &quot;ana&quot;
      given_name       = &quot;Ana&quot;
      family_name      = &quot;Perez&quot;
      email            = &quot;ana@example.com&quot;
    }
  }

  # -----------------------------
  # Permission Sets
  # -----------------------------
  permission_sets = {
    ReadS3AndEC2 = {
      description      = &quot;Read-only access to S3 and EC2&quot;
      session_duration = &quot;PT8H&quot;
      inline_policy    = jsonencode({
        Version = &quot;2012-10-17&quot;
        Statement = [
          {
            Effect   = &quot;Allow&quot;
            Action   = [&quot;s3:Get*&quot;, &quot;s3:List*&quot;]
            Resource = &quot;*&quot;
          },
          {
            Effect   = &quot;Allow&quot;
            Action   = [&quot;ec2:DescribeInstances&quot;, &quot;ec2:DescribeTags&quot;]
            Resource = &quot;*&quot;
          }
        ]
      })
    }
  }

  # -----------------------------
  # Account Assignments
  # -----------------------------
  account_assignments = {
    Developers = {
      principal_name  = &quot;Developers&quot;
      principal_type  = &quot;GROUP&quot;
      principal_idp   = &quot;INTERNAL&quot;
      permission_sets = [&quot;ReadS3AndEC2&quot;]
      account_ids     = [aws_organizations_account.root.id]
    }
  }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;hr&gt;
&lt;p&gt;🌟 &lt;strong&gt;Best Practices for a Secure and Scalable Setup&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Automation is just the first step. To maintain a strong and sustainable setup, follow these design principles:&lt;/p&gt;
&lt;hr&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Separate environments (dev, staging, prod)&lt;/strong&gt;&lt;br&gt;
Managing each environment separately allows you to test and validate changes before they affect production.&lt;br&gt;
For example, create specific groups and permission sets per environment — this prevents misconfigurations and ensures access matches the context.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Apply the principle of least privilege&lt;/strong&gt;&lt;br&gt;
Each user or group should have only the permissions necessary to perform their role.&lt;br&gt;
This limits potential damage from mistakes or unauthorized access, strengthens overall security, and helps meet compliance requirements.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Integrate Terraform into CI/CD pipelines&lt;/strong&gt;&lt;br&gt;
Automated pipelines (e.g., using &lt;strong&gt;GitHub Actions&lt;/strong&gt;) can validate and apply Terraform changes safely.&lt;br&gt;
Before running &lt;code&gt;terraform apply&lt;/code&gt;, the pipeline should:
&lt;ul&gt;
&lt;li&gt;Check formatting (&lt;code&gt;terraform fmt&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Validate syntax (&lt;code&gt;terraform validate&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Run a plan preview (&lt;code&gt;terraform plan&lt;/code&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This ensures every modification goes through review before reaching production, maintaining traceability and governance over who changes what and when.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;&lt;strong&gt;Example GitHub Actions workflow for Terraform:&lt;/strong&gt;&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;&lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;Terraform&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;CI/CD&lt;/span&gt;

&lt;span class=&quot;hljs-attr&quot;&gt;on:&lt;/span&gt;
  &lt;span class=&quot;hljs-attr&quot;&gt;push:&lt;/span&gt;
    &lt;span class=&quot;hljs-attr&quot;&gt;branches:&lt;/span&gt;
      &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;main&lt;/span&gt;
  &lt;span class=&quot;hljs-attr&quot;&gt;pull_request:&lt;/span&gt;

&lt;span class=&quot;hljs-attr&quot;&gt;jobs:&lt;/span&gt;
  &lt;span class=&quot;hljs-attr&quot;&gt;terraform:&lt;/span&gt;
    &lt;span class=&quot;hljs-attr&quot;&gt;runs-on:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;ubuntu-latest&lt;/span&gt;

    &lt;span class=&quot;hljs-attr&quot;&gt;steps:&lt;/span&gt;
      &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;Checkout&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;code&lt;/span&gt;
        &lt;span class=&quot;hljs-attr&quot;&gt;uses:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;actions/checkout@v4&lt;/span&gt;

      &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;Set&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;up&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;Terraform&lt;/span&gt;
        &lt;span class=&quot;hljs-attr&quot;&gt;uses:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;hashicorp/setup-terraform@v3&lt;/span&gt;
        &lt;span class=&quot;hljs-attr&quot;&gt;with:&lt;/span&gt;
          &lt;span class=&quot;hljs-attr&quot;&gt;terraform_version:&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;1.8&lt;/span&gt;&lt;span class=&quot;hljs-number&quot;&gt;.5&lt;/span&gt;

      &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;Terraform&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;Format&lt;/span&gt;
        &lt;span class=&quot;hljs-attr&quot;&gt;run:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;terraform&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;fmt&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;-check&lt;/span&gt;

      &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;Terraform&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;Validate&lt;/span&gt;
        &lt;span class=&quot;hljs-attr&quot;&gt;run:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;terraform&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;validate&lt;/span&gt;

      &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;Terraform&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;Plan&lt;/span&gt;
        &lt;span class=&quot;hljs-attr&quot;&gt;run:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;terraform&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;plan&lt;/span&gt;

      &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;Terraform&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;Apply&lt;/span&gt;
        &lt;span class=&quot;hljs-attr&quot;&gt;if:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;github.ref&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&#39;refs/heads/main&#39;&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;github.event_name&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&#39;push&#39;&lt;/span&gt;
        &lt;span class=&quot;hljs-attr&quot;&gt;run:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;terraform&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;apply&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;-auto-approve&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;hr&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Use inline policies sparingly&lt;/strong&gt;&lt;br&gt;
Inline policies are powerful for fine-tuned permissions but can increase complexity if overused.&lt;br&gt;
Prefer &lt;strong&gt;AWS-managed&lt;/strong&gt; or &lt;strong&gt;organization-wide policies&lt;/strong&gt;, and reserve inline policies for highly specific cases (e.g., access to a single S3 bucket or specific resource tags).&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Version and review every change&lt;/strong&gt;&lt;br&gt;
Keep your Terraform configuration in a &lt;strong&gt;Git repository&lt;/strong&gt;.&lt;br&gt;
This enables full change history, branch-based testing, and easy rollback if needed.&lt;br&gt;
It also allows multiple teams to collaborate safely without overwriting each other’s changes.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;p&gt;🎯 &lt;strong&gt;Conclusion&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Automating &lt;strong&gt;AWS IAM Identity Center&lt;/strong&gt; with &lt;strong&gt;Terraform&lt;/strong&gt; completely transforms how you manage access in multi-account environments.&lt;br&gt;
You move from a manual, error-prone model to a centralized, reproducible, and auditable system.&lt;br&gt;
This lets you &lt;strong&gt;scale without losing control&lt;/strong&gt;, keep environments consistent, and &lt;strong&gt;strengthen security&lt;/strong&gt; through least-privilege principles.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;&lt;strong&gt;This approach delivers scalability, security, and efficiency:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Scalability&lt;/strong&gt; – manage hundreds of accounts with a single, consistent codebase.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Security&lt;/strong&gt; – every change is reviewed and governed by the principle of least privilege.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Efficiency&lt;/strong&gt; – fewer manual tasks and faster onboarding for new users and environments.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;p&gt;In short, if your organization is growing and manual access management has become a bottleneck, automating &lt;strong&gt;IAM Identity Center&lt;/strong&gt; with &lt;strong&gt;Terraform&lt;/strong&gt; isn’t just a best practice — it’s the &lt;strong&gt;natural next step toward a secure, controlled, and agile cloud environment&lt;/strong&gt;.&lt;/p&gt;
</content:encoded></item><item><title>Where Code Meets Platform: Baking Security Into Every Build</title><link>https://resiz.es/blog/static-code-analysis</link><guid isPermaLink="false">https://blog.resiz.es/static-code-analysis</guid><pubDate>Wed, 08 Oct 2025 00:00:00 GMT</pubDate><description>Shift-left Philosophy: Why Security Matters You might remember the recent supply chain attack that hit NPM packages — maybe your team even felt the impact. It was a good reminder that one vulnerabl…</description><content:encoded>&lt;h2 id=&quot;shift-left-philosophy-why-security-matters&quot; tabindex=&quot;-1&quot;&gt;Shift-left Philosophy: Why Security Matters&lt;/h2&gt;
&lt;p&gt;You might remember the recent supply chain attack that hit NPM packages — maybe your team even felt the impact. It was a good reminder that one vulnerable dependency can ripple across entire systems.&lt;/p&gt;
&lt;p&gt;Modern software is a tangled web of dependencies, containers, and distributed codebases. Things move fast, and it’s easy to miss outdated packages or accidentally introduce new risks. All of that adds up to a big security challenge.&lt;/p&gt;
&lt;!--truncate--&gt;
&lt;p&gt;&lt;strong&gt;Shift-left security&lt;/strong&gt; aims to solve this — catching issues early in the development process, before they make it to production. It’s not just about fixing problems; it’s about &lt;strong&gt;preventing them in the first place&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;So, if security needs to start early, how do we actually make that happen? That’s where &lt;strong&gt;Application Security Testing (AST)&lt;/strong&gt; comes in.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&quot;application-security-testing-what-it-is-and-why-it-matters&quot; tabindex=&quot;-1&quot;&gt;Application Security Testing: What It Is and Why It Matters&lt;/h2&gt;
&lt;p&gt;AST tools aren’t just there to tick compliance boxes — they help teams find problems early, reduce risk, and protect users before code ships.&lt;/p&gt;
&lt;p&gt;There are a few key parts to it:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;SAST (Static Application Security Testing):&lt;/strong&gt; Scans your source code for insecure patterns like unsafe inputs or weak function calls — all before your app even runs.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Secret Scanning:&lt;/strong&gt; Finds sensitive information (API keys, passwords, certificates) that might have accidentally ended up in your repos.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Software Composition Analysis (SCA):&lt;/strong&gt; Checks your dependencies and open-source libraries for known vulnerabilities or outdated versions.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Together, these tools give you &lt;strong&gt;a clear view of where your risks are&lt;/strong&gt; — across code, dependencies, and secrets. More importantly, they don’t just tell you something’s wrong; they help you &lt;strong&gt;stop vulnerabilities before they become real issues&lt;/strong&gt;.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&quot;integrating-security-into-your-workflow&quot; tabindex=&quot;-1&quot;&gt;Integrating Security into Your Workflow&lt;/h2&gt;
&lt;p&gt;Having the right tools is important, but the real magic happens when you &lt;strong&gt;bake them into your everyday workflow&lt;/strong&gt;. By plugging AST tools into your &lt;strong&gt;CI/CD pipeline&lt;/strong&gt;, every commit, pull request, or build can be scanned automatically.&lt;/p&gt;
&lt;p&gt;That means security checks happen as part of normal development — not as an afterthought. Issues are caught early, feedback goes straight to developers, and teams can &lt;strong&gt;shift left&lt;/strong&gt;, turning security from a one-time event into part of their daily rhythm.&lt;/p&gt;
&lt;p&gt;Automating these checks also cuts down on human error, keeps standards consistent, and helps teams build a &lt;strong&gt;culture of proactive security&lt;/strong&gt; that grows with the organization.&lt;/p&gt;
&lt;p&gt;In practice, this means security becomes a &lt;strong&gt;natural checkpoint in your delivery flow&lt;/strong&gt;. For example, imagine your CI/CD pipeline detects a critical vulnerability in a dependency just before deployment. The release is automatically blocked — frustrating in the moment, indeed, but it might have just prevented a production outage or data leak. With clear reporting and well-defined exceptions, the team can decide whether to patch, replace, or (in rare, justified cases) move forward with a temporary risk waiver.
That’s real-world shift-left security: catching problems when they’re still easy to fix, not after customers are affected.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&quot;tools-used&quot; tabindex=&quot;-1&quot;&gt;Tools Used&lt;/h2&gt;
&lt;p&gt;Once the workflow is in place, the right tools make it stick. Here’s what we use to cover all the bases:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Trivy (SCA):&lt;/strong&gt; Scans container images and dependencies for known vulnerabilities before anything hits production.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;TruffleHog (Secret Scanning):&lt;/strong&gt; Spots secrets, credentials, and sensitive data accidentally pushed to your repos.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Semgrep (SAST):&lt;/strong&gt; Uses custom static analysis rules to flag insecure code patterns and enforce best practices.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;We’ve integrated these tools directly into the CI/CD pipeline, so every commit or pull request triggers automatic scans. Developers get quick feedback through clear reports, so they can fix issues fast — without slowing down the build.&lt;/p&gt;
&lt;p&gt;By combining automation with visibility, these tools don’t just &lt;strong&gt;find problems&lt;/strong&gt; — they help teams &lt;strong&gt;build more secure software by default&lt;/strong&gt;.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&quot;minimizing-risk-do-you-really-need-that-dependency&quot; tabindex=&quot;-1&quot;&gt;Minimizing Risk: Do You Really Need That Dependency?&lt;/h2&gt;
&lt;p&gt;Every new dependency is a potential risk. Even popular libraries can bring in vulnerabilities, and unmaintained ones often turn into hidden liabilities. This is what we call your &lt;strong&gt;risk surface&lt;/strong&gt; — all the points where your application could be attacked.&lt;/p&gt;
&lt;p&gt;To keep that surface small, start with one simple habit: ask, &lt;strong&gt;“Do we really need this?”&lt;/strong&gt; before adding a new dependency. Check if it’s maintained, trusted, and necessary. The same goes for old dependencies — review them regularly and remove what you don’t use.&lt;/p&gt;
&lt;p&gt;Tools like SCA scanners make this easier by flagging known issues automatically, but awareness and judgment still matter most. &lt;strong&gt;Reducing risk isn’t just about fixing what’s broken — it’s about keeping things clean in the first place.&lt;/strong&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&quot;starting-small-and-staying-realistic&quot; tabindex=&quot;-1&quot;&gt;Starting Small and Staying Realistic&lt;/h2&gt;
&lt;p&gt;Rolling out all these practices at once can feel like a lot — especially for smaller teams. But security doesn’t have to be all or nothing. It’s better to &lt;strong&gt;start small and grow steadily&lt;/strong&gt;. Begin with the areas that matter most: core repos, key dependencies, or code that handles sensitive data. From there, add more automation and rules as your team gets comfortable.&lt;/p&gt;
&lt;p&gt;Education is just as important as tooling. Developers should understand what scan results mean and how to act on them. Over time, these habits turn security from something “extra” into something &lt;strong&gt;everyone naturally does&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;As your setup matures, it helps to define which checks are &lt;strong&gt;mandatory&lt;/strong&gt; and which are &lt;strong&gt;recommended&lt;/strong&gt;. For instance, secret scanning and dependency analysis might be non-negotiable in all projects, while SAST could start as “recommended” until coverage improves. This distinction sets clear expectations — security isn’t about blocking progress, but about managing risk with context.&lt;/p&gt;
&lt;p&gt;Over time, these habits don’t just make your software safer — they build trust. Each secure release reinforces your team’s reliability and your company’s reputation. &lt;strong&gt;Security becomes part of your brand, not just your build.&lt;/strong&gt;&lt;/p&gt;
</content:encoded></item><item><title>Easily open TCP and UDP protocols on the same port</title><link>https://resiz.es/blog/open-tcp-udp-same-port</link><guid isPermaLink="false">https://blog.resiz.es/open-tcp-udp-same-port</guid><pubDate>Fri, 04 Jul 2025 00:00:00 GMT</pubDate><description>If you’ve ever tried to expose both TCP and UDP on the same port using Kubernetes with AWS Load Balancers, you’ve probably run into a common limitation: you can only choose one protocol per port, w…</description><content:encoded>&lt;p&gt;If you’ve ever tried to expose both TCP and UDP on the same port using Kubernetes with AWS Load Balancers, you’ve probably run into a common limitation: you can only choose one protocol per port, which complicates applications that need both (such as real-time communications or gaming).&lt;/p&gt;
&lt;p&gt;The good news is that AWS has released a feature that allows configuring listeners for both TCP and UDP on the same port, avoiding complex workarounds.&lt;/p&gt;
&lt;!--truncate--&gt;
&lt;p&gt;To implement this, it’s important to verify two things:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;That your &lt;strong&gt;AWS Load Balancer Controller&lt;/strong&gt; is version &lt;strong&gt;v2.13.0 or higher&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;That the &lt;strong&gt;Helm chart&lt;/strong&gt; is &lt;strong&gt;1.13.0 or higher&lt;/strong&gt; to ensure compatibility.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Once that’s set, you only need to do two steps to enable both protocols on the same port:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;In the ALB Controller’s &lt;code&gt;values.yaml&lt;/code&gt; file, add:&lt;pre tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;&lt;span class=&quot;hljs-attr&quot;&gt;controllerConfig:&lt;/span&gt;
    &lt;span class=&quot;hljs-attr&quot;&gt;featureGates:&lt;/span&gt;
        &lt;span class=&quot;hljs-attr&quot;&gt;EnableTCPUDPListener:&lt;/span&gt; &lt;span class=&quot;hljs-literal&quot;&gt;true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;In the LoadBalancer type Service manifest where you want to enable this functionality, add this annotation:&lt;pre tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;&lt;span class=&quot;hljs-attr&quot;&gt;service.beta.kubernetes.io/aws-load-balancer-enable-tcp-udp-listener:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&#39;true&#39;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;After that, you just need to define the port twice in your Service: once for TCP and once for UDP. Here is a complete example of a Service manifest that opens the same port for both TCP and UDP:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;&lt;span class=&quot;hljs-attr&quot;&gt;apiVersion:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;v1&lt;/span&gt;
&lt;span class=&quot;hljs-attr&quot;&gt;kind:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;Service&lt;/span&gt;
&lt;span class=&quot;hljs-attr&quot;&gt;metadata:&lt;/span&gt;
  &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;ejemplo-tcp-udp&lt;/span&gt;
  &lt;span class=&quot;hljs-attr&quot;&gt;annotations:&lt;/span&gt;
    &lt;span class=&quot;hljs-attr&quot;&gt;service.beta.kubernetes.io/aws-load-balancer-enable-tcp-udp-listener:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;true&quot;&lt;/span&gt;
&lt;span class=&quot;hljs-attr&quot;&gt;spec:&lt;/span&gt;
  &lt;span class=&quot;hljs-attr&quot;&gt;type:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;LoadBalancer&lt;/span&gt;
  &lt;span class=&quot;hljs-attr&quot;&gt;selector:&lt;/span&gt;
    &lt;span class=&quot;hljs-attr&quot;&gt;app:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;mi-aplicacion&lt;/span&gt;
  &lt;span class=&quot;hljs-attr&quot;&gt;ports:&lt;/span&gt;
    &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;tcp-12345&lt;/span&gt;
      &lt;span class=&quot;hljs-attr&quot;&gt;protocol:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;TCP&lt;/span&gt;
      &lt;span class=&quot;hljs-attr&quot;&gt;port:&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;12345&lt;/span&gt;
      &lt;span class=&quot;hljs-attr&quot;&gt;targetPort:&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;12345&lt;/span&gt;
    &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;udp-12345&lt;/span&gt;
      &lt;span class=&quot;hljs-attr&quot;&gt;protocol:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;UDP&lt;/span&gt;
      &lt;span class=&quot;hljs-attr&quot;&gt;port:&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;12345&lt;/span&gt;
      &lt;span class=&quot;hljs-attr&quot;&gt;targetPort:&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;12345&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;
&lt;p&gt;⚠️ &lt;strong&gt;If you already had the load balancer created and you add this functionality now, I recommend deleting it and recreating it&lt;/strong&gt; to ensure the configuration is applied correctly.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id=&quot;-references&quot; tabindex=&quot;-1&quot;&gt;💬 References&lt;/h3&gt;
&lt;p&gt;This new feature addresses several community-reported issues, such as &lt;a href=&quot;https://github.com/kubernetes-sigs/aws-load-balancer-controller/issues/2759&quot;&gt;#2759&lt;/a&gt; and &lt;a href=&quot;https://github.com/kubernetes-sigs/aws-load-balancer-controller/issues/1608&quot;&gt;1608&lt;/a&gt;. I hope this is helpful to those following those threads!&lt;/p&gt;
</content:encoded></item><item><title>Success Story - Software Enhancement in a Green Energy Solutions Company</title><link>https://resiz.es/blog/success-story-sotysolar</link><guid isPermaLink="false">https://blog.resiz.es/success-story-sotysolar</guid><pubDate>Fri, 27 Jun 2025 00:00:00 GMT</pubDate><description>Be Energy Part S.L leads the solar panel installation sector in Europe with their innovative green solutions. The company modernized their technology stack through an Internal Developer Platform de…</description><content:encoded>&lt;p&gt;&lt;a href=&quot;https://sotysolar.es/&quot;&gt;Be Energy Part S.L&lt;/a&gt; leads the solar panel installation sector in Europe with their innovative green solutions. The company modernized their technology stack through an Internal Developer Platform developed in collaboration with &lt;a href=&quot;https://resiz.es/&quot;&gt;Resizes Platform&lt;/a&gt;. This strategic partnership delivered significant improvements across multiple dimensions:&lt;/p&gt;
&lt;!--truncate--&gt;
&lt;h2 id=&quot;key-results-at-a-glance&quot; tabindex=&quot;-1&quot;&gt;&lt;strong&gt;Key Results at a Glance&lt;/strong&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;🚀 2+ Hours Saved&lt;/strong&gt; per deployment cycle (75% reduction)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;💰 30% Cost Reduction&lt;/strong&gt; in infrastructure spending&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;⚡ 60% Faster Build Times&lt;/strong&gt; with optimized containerization&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;🔄 99.9% Uptime&lt;/strong&gt; achieved with self-healing infrastructure&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;🌱 40% Reduction&lt;/strong&gt; in carbon footprint through efficient resource usage&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;📈 3x Increase&lt;/strong&gt; in deployment frequency&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;the-challenge&quot; tabindex=&quot;-1&quot;&gt;The Challenge&lt;/h2&gt;
&lt;p&gt;With over 12,000 solar panels installed across Spain and Portugal, &lt;a href=&quot;https://sotysolar.es/&quot;&gt;SotySolar&lt;/a&gt; was ready to scale their operations while maintaining their commitment to sustainability. Their existing infrastructure, based on traditional virtual machines and manual processes, was becoming a bottleneck for growth.&lt;/p&gt;
&lt;p&gt;The company needed a solution that would enable them to:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Scale their services efficiently without proportional cost increases&lt;/li&gt;
&lt;li&gt;Reduce deployment downtime and improve delivery speed&lt;/li&gt;
&lt;li&gt;Maintain their environmental commitments through optimized resource usage&lt;/li&gt;
&lt;li&gt;Implement modern software development practices&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;the-solution-a-comprehensive-platform-transformation&quot; tabindex=&quot;-1&quot;&gt;The Solution: A Comprehensive Platform Transformation&lt;/h2&gt;
&lt;h2 id=&quot;implementation-timeline&quot; tabindex=&quot;-1&quot;&gt;&lt;strong&gt;Implementation Timeline&lt;/strong&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Phase 1 (Months 1-2)&lt;/strong&gt;: Infrastructure assessment and migration planning&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Phase 2 (Months 3-4)&lt;/strong&gt;: AWS migration and Kubernetes adoption&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Phase 3 (Months 5-6)&lt;/strong&gt;: CI/CD optimization and security hardening&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Phase 4 (Months 7-9)&lt;/strong&gt;: Performance tuning and monitoring implementation&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;cloud-infrastructure-migration-a-strategic-journey&quot; tabindex=&quot;-1&quot;&gt;Cloud Infrastructure Migration: A Strategic Journey&lt;/h2&gt;
&lt;p&gt;When &lt;a href=&quot;https://sotysolar.es/&quot;&gt;SotySolar&lt;/a&gt; first approached &lt;a href=&quot;https://resiz.es/&quot;&gt;Resizes Platform&lt;/a&gt;, their infrastructure was running on DigitalOcean – a choice that had served them well during their initial growth phase. However, as their solar panel installations scaled beyond 12,000 units across Spain and Portugal, they recognized the need for a more robust infrastructure solution.&lt;/p&gt;
&lt;p&gt;The migration to Amazon Web Services represented a strategic upgrade rather than a rescue operation. AWS offered the enterprise-grade managed services ecosystem that &lt;a href=&quot;https://sotysolar.es/&quot;&gt;SotySolar&lt;/a&gt; needed to support their ambitious expansion plans while maintaining their core commitment to environmental sustainability.&lt;/p&gt;
&lt;h3 id=&quot;technical-architecture&quot; tabindex=&quot;-1&quot;&gt;&lt;strong&gt;Technical Architecture&lt;/strong&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Container Orchestration&lt;/strong&gt;: Amazon EKS (Kubernetes 1.28)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Database Layer&lt;/strong&gt;: AWS Aurora PostgreSQL (v15) + MongoDB 7.x (3-replica cluster)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Caching&lt;/strong&gt;: ElastiCache Redis 7.x&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Storage&lt;/strong&gt;: S3 with cross-region replication&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Security&lt;/strong&gt;: AWS Secrets Manager + IAM roles&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Monitoring&lt;/strong&gt;: CloudWatch + Prometheus + Grafana&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The migration strategy focused on leveraging AWS&#39;s comprehensive portfolio of managed services. Instead of maintaining their own database servers, &lt;a href=&quot;https://sotysolar.es/&quot;&gt;SotySolar&lt;/a&gt; could rely on AWS Aurora and RDS for their relational data needs, while ElastiCache would handle their Redis requirements. The Amazon EKS service would orchestrate their containerized applications, and AWS Secrets Manager would secure their sensitive configuration data.&lt;/p&gt;
&lt;p&gt;AWS&#39;s commitment to sustainability aligned perfectly with &lt;a href=&quot;https://sotysolar.es/&quot;&gt;SotySolar&lt;/a&gt;&#39;s mission. With AWS&#39;s pledge to match 100% of their energy usage with renewable sources by 2025 and achieve carbon neutrality by 2040, the migration represented a strategic alignment with partners who shared their environmental values.&lt;/p&gt;
&lt;p&gt;The transformation from virtual machines to Kubernetes represented a significant operational improvement. Kubernetes enabled &lt;a href=&quot;https://sotysolar.es/&quot;&gt;SotySolar&lt;/a&gt; to define their entire application infrastructure as code, using declarative configurations that could be version-controlled, peer-reviewed, and automatically deployed. This shift meant that their development, staging, and production environments could be guaranteed to be identical, eliminating environment inconsistencies.&lt;/p&gt;
&lt;p&gt;The container orchestration capabilities of Kubernetes also unlocked new levels of resource efficiency. Where virtual machines had required dedicated resources regardless of actual usage, containers could be packed more efficiently onto the same hardware, with Kubernetes automatically managing the scheduling and resource allocation.&lt;/p&gt;
&lt;h2 id=&quot;modern-development-practices-from-manual-to-automated&quot; tabindex=&quot;-1&quot;&gt;Modern Development Practices: From Manual to Automated&lt;/h2&gt;
&lt;p&gt;The transformation of &lt;a href=&quot;https://sotysolar.es/&quot;&gt;SotySolar&lt;/a&gt;&#39;s development practices began with the introduction of GitOps methodology. For the first time, every aspect of their infrastructure could be described in code, stored in Git repositories, and treated with the same rigor as their application code. This meant that infrastructure changes could be proposed through pull requests, reviewed by the team, and automatically deployed once approved.&lt;/p&gt;
&lt;p&gt;ArgoCD became the conductor of this new orchestrated approach, continuously monitoring Git repositories and ensuring that the running infrastructure matched exactly what was defined in code. When developers pushed changes to their repositories, they could watch as ArgoCD automatically synchronized these changes across their environments.&lt;/p&gt;
&lt;p&gt;The database modernization journey involved careful strategic planning. &lt;a href=&quot;https://sotysolar.es/&quot;&gt;SotySolar&lt;/a&gt;&#39;s existing MongoDB installation, running on version 5.x, was approaching end-of-life support [October 2024]. &lt;a href=&quot;https://resiz.es/&quot;&gt;Resizes Platform&lt;/a&gt; crafted an incremental upgrade strategy that would minimize risk while maximizing the benefits of newer database features. The journey to MongoDB 7.x unlocked advanced indexing capabilities, improved query performance, and enhanced security features.&lt;/p&gt;
&lt;p&gt;The migration to AWS Aurora, RDS and ElastiCache represented &lt;a href=&quot;https://sotysolar.es/&quot;&gt;SotySolar&lt;/a&gt;&#39;s graduation to enterprise-grade data management. Instead of managing database servers, applying security patches, and configuring backup systems, the team could now rely on AWS&#39;s managed services to handle these operational concerns automatically.&lt;/p&gt;
&lt;p&gt;Each database in the new architecture was designed with high availability from the ground up. The 3-replica MongoDB configuration meant that even if an entire AWS zone failed, &lt;a href=&quot;https://sotysolar.es/&quot;&gt;SotySolar&lt;/a&gt;&#39;s applications would continue operating without interruption.&lt;/p&gt;
&lt;h2 id=&quot;performance-optimizations-the-quest-for-speed-and-efficiency&quot; tabindex=&quot;-1&quot;&gt;Performance Optimizations: The Quest for Speed and Efficiency&lt;/h2&gt;
&lt;p&gt;The performance optimization journey began with addressing build time inefficiencies. An 8-minute container build process was disrupting the natural flow of development and creating delays in the feedback loop that drives productive software development.&lt;/p&gt;
&lt;p&gt;The solution required a fundamental rethinking of how &lt;a href=&quot;https://sotysolar.es/&quot;&gt;SotySolar&lt;/a&gt;&#39;s applications were packaged and deployed. &lt;a href=&quot;https://resiz.es/&quot;&gt;Resizes Platform&lt;/a&gt; implemented multi-stage Docker builds that transformed the wasteful process into an elegant, efficient pipeline. The first stage would handle all the heavy lifting – downloading dependencies, compiling code, and preparing assets. The second stage would take only the essential runtime artifacts and create a lean, optimized image. This approach reduced the final image size by 60% while dramatically improving build times through intelligent layer caching strategies.&lt;/p&gt;
&lt;p&gt;The creation of custom base images marked another breakthrough in the optimization journey. Instead of starting from generic operating system images and installing the same packages repeatedly, &lt;a href=&quot;https://sotysolar.es/&quot;&gt;SotySolar&lt;/a&gt; could now begin with purpose-built base images that already contained their specific PHP runtime, extensions, and optimizations.&lt;/p&gt;
&lt;p&gt;The migration to ARM64 architecture represented a strategic alignment with modern computing trends. By rebuilding their applications to run natively on ARM64, they eliminated translation overhead and achieved better performance while reducing resource consumption.&lt;/p&gt;
&lt;p&gt;The implementation of self-hosted runners on Kubernetes transformed the CI/CD infrastructure. Custom Docker images pre-loaded with all necessary tools meant that jobs could begin executing immediately, eliminating the setup overhead that had been consuming precious development time. The Kubernetes-based deployment enabled automatic scaling based on the depth of the job queue.&lt;/p&gt;
&lt;p&gt;Database performance optimization involved upgrading from MongoDB 5.x to 7.x, which unlocked advanced indexing strategies and query optimization features. The implementation of connection pooling addressed performance bottlenecks by optimizing connection reuse while ensuring efficient database server resource utilization.&lt;/p&gt;
&lt;p&gt;The 3-replica architecture provided high availability and enabled read scaling that could dramatically improve application performance for read-heavy workloads.&lt;/p&gt;
&lt;h2 id=&quot;technical-enhancements-and-security-building-a-fortress-of-trust&quot; tabindex=&quot;-1&quot;&gt;Technical Enhancements and Security: Building a Fortress of Trust&lt;/h2&gt;
&lt;p&gt;The security transformation of &lt;a href=&quot;https://sotysolar.es/&quot;&gt;SotySolar&lt;/a&gt;&#39;s infrastructure began with the migration to AWS Secrets Manager. Every hardcoded credential was extracted from the codebase and moved to the centralized secrets management system. This process ensured that sensitive data was safely stored and automatically injected at runtime, with automated rotation capabilities providing additional security.&lt;/p&gt;
&lt;p&gt;The network security architecture implemented defense in depth, where each layer provided protection against different types of threats. The migration to private subnets meant that &lt;a href=&quot;https://sotysolar.es/&quot;&gt;SotySolar&lt;/a&gt;&#39;s most critical components – their databases and application servers – became invisible to the outside world, accessible only through controlled pathways.&lt;/p&gt;
&lt;p&gt;The implementation of security groups as programmable firewalls allowed &lt;a href=&quot;https://sotysolar.es/&quot;&gt;SotySolar&lt;/a&gt; to define their security policies as code, version-controlled and peer-reviewed just like their application code. This approach eliminated the common problem of security configurations drifting over time or being inconsistently applied across environments.&lt;/p&gt;
&lt;h2 id=&quot;message-processing-and-reliability-never-losing-a-beat&quot; tabindex=&quot;-1&quot;&gt;Message Processing and Reliability: Never Losing a Beat&lt;/h2&gt;
&lt;p&gt;The transformation of &lt;a href=&quot;https://sotysolar.es/&quot;&gt;SotySolar&lt;/a&gt;&#39;s message processing system involved implementing Dead Letter Queues (DLQs) to create a robust, resilient message processing architecture. Now, when messages couldn&#39;t be processed successfully, they weren&#39;t lost – they were carefully preserved in the DLQ for investigation and reprocessing.&lt;/p&gt;
&lt;p&gt;The AWS SQS migration brought enterprise-grade message durability to &lt;a href=&quot;https://sotysolar.es/&quot;&gt;SotySolar&lt;/a&gt;&#39;s operations. Messages were now automatically replicated across multiple data centers, with guaranteed delivery semantics that eliminated the possibility of message loss due to hardware failures. The configurable retry logic with exponential backoff meant that temporary system issues wouldn&#39;t result in message loss.&lt;/p&gt;
&lt;h2 id=&quot;data-storage-building-digital-vaults&quot; tabindex=&quot;-1&quot;&gt;Data Storage: Building Digital Vaults&lt;/h2&gt;
&lt;p&gt;The S3 bucket architecture represented &lt;a href=&quot;https://sotysolar.es/&quot;&gt;SotySolar&lt;/a&gt;&#39;s evolution from simple file storage to enterprise-grade data management. The new S3 architecture was designed like a digital vault system, with different security zones for different types of data. Public-facing content like marketing materials and product images were stored in buckets with appropriate public access policies, while sensitive customer data and business documents were secured in private buckets with strict access controls and encryption requirements.&lt;/p&gt;
&lt;p&gt;The implementation of bucket policies as Infrastructure as Code meant that security configurations were no longer ad-hoc decisions made during crisis situations. Every access rule was documented, reviewed, and consistently applied across all environments. The cross-region replication strategy ensured that even if an entire AWS region failed, &lt;a href=&quot;https://sotysolar.es/&quot;&gt;SotySolar&lt;/a&gt;&#39;s critical data would remain accessible from backup locations.&lt;/p&gt;
&lt;h2 id=&quot;observability-eyes-and-ears-of-the-system&quot; tabindex=&quot;-1&quot;&gt;Observability: Eyes and Ears of the System&lt;/h2&gt;
&lt;p&gt;The comprehensive monitoring stack implemented by &lt;a href=&quot;https://resiz.es/&quot;&gt;Resizes Platform&lt;/a&gt; provided real-time visibility into how &lt;a href=&quot;https://sotysolar.es/&quot;&gt;SotySolar&lt;/a&gt;&#39;s applications were performing, automatically detecting slow queries, memory leaks, and error spikes before they could impact customer experience.&lt;/p&gt;
&lt;p&gt;The distributed tracing capabilities transformed the debugging experience. When issues occurred, the team could now trace individual requests through their entire system architecture, seeing exactly where delays occurred or errors originated.&lt;/p&gt;
&lt;p&gt;The intelligent alerting system learned &lt;a href=&quot;https://sotysolar.es/&quot;&gt;SotySolar&lt;/a&gt;&#39;s normal operational patterns and could distinguish between genuine problems requiring immediate attention and normal operational variations that didn&#39;t warrant immediate escalation.&lt;/p&gt;
&lt;h2 id=&quot;quality-assurance-building-confidence&quot; tabindex=&quot;-1&quot;&gt;Quality Assurance: Building Confidence&lt;/h2&gt;
&lt;p&gt;The testing strategy transformation represented &lt;a href=&quot;https://sotysolar.es/&quot;&gt;SotySolar&lt;/a&gt;&#39;s graduation to confidence-based releases. The comprehensive automated testing suite meant that potential issues could be caught and resolved during development, long before they could impact customers.&lt;/p&gt;
&lt;p&gt;The implementation of chaos engineering took this confidence to the next level. By deliberately introducing controlled failures into their systems, &lt;a href=&quot;https://sotysolar.es/&quot;&gt;SotySolar&lt;/a&gt; could verify that their disaster recovery procedures actually worked and that their applications could gracefully handle the unexpected failures that inevitably occur in production environments.&lt;/p&gt;
&lt;h2 id=&quot;business-impact-and-results&quot; tabindex=&quot;-1&quot;&gt;Business Impact and Results&lt;/h2&gt;
&lt;h2 id=&quot;competitive-advantage-achieved&quot; tabindex=&quot;-1&quot;&gt;&lt;strong&gt;Competitive Advantage Achieved&lt;/strong&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Market Leadership&lt;/strong&gt;: First solar company in Spain with enterprise-grade cloud infrastructure&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Innovation Speed&lt;/strong&gt;: 3x faster feature delivery compared to industry average&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Operational Excellence&lt;/strong&gt;: 99.9% uptime during peak solar installation season&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Cost Leadership&lt;/strong&gt;: 30% lower infrastructure costs than competitors&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;operational-efficiency&quot; tabindex=&quot;-1&quot;&gt;Operational Efficiency&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Faster Deployments&lt;/strong&gt;: 2+ hour reduction in deployment cycles enables more frequent releases and faster time-to-market&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Improved Reliability&lt;/strong&gt;: Self-healing Kubernetes infrastructure minimizes downtime and manual intervention&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Enhanced Scalability&lt;/strong&gt;: Autoscaling capabilities automatically adjust resources based on demand&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;financial-benefits&quot; tabindex=&quot;-1&quot;&gt;Financial Benefits&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Cost Optimization&lt;/strong&gt;: FinOps practices provide visibility and control over cloud spending&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Resource Efficiency&lt;/strong&gt;: Automated provisioning ensures optimal resource utilization&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Predictable Scaling&lt;/strong&gt;: Infrastructure adapts to needs without over-provisioning&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;environmental-impact&quot; tabindex=&quot;-1&quot;&gt;Environmental Impact&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Reduced Carbon Footprint&lt;/strong&gt;: AWS&#39;s renewable energy commitment and efficient resource usage align with &lt;a href=&quot;https://sotysolar.es/&quot;&gt;SotySolar&lt;/a&gt;&#39;s sustainability goals&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Optimized Resource Consumption&lt;/strong&gt;: Kubernetes autoscaling provisions only necessary resources, minimizing waste&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Green Technology Leadership&lt;/strong&gt;: Modern infrastructure supports &lt;a href=&quot;https://sotysolar.es/&quot;&gt;SotySolar&lt;/a&gt;&#39;s position as an environmental technology leader&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;looking-forward&quot; tabindex=&quot;-1&quot;&gt;Looking Forward&lt;/h2&gt;
&lt;p&gt;This collaboration between &lt;a href=&quot;https://sotysolar.es/&quot;&gt;Be Energy Part S.L&lt;/a&gt; and &lt;a href=&quot;https://resiz.es/&quot;&gt;Resizes Platform&lt;/a&gt; demonstrates how modern cloud-native technologies can drive both business efficiency and environmental responsibility. The Internal Developer Platform provides &lt;a href=&quot;https://sotysolar.es/&quot;&gt;SotySolar&lt;/a&gt; with a robust foundation for continued growth while maintaining their commitment to sustainable practices.&lt;/p&gt;
&lt;p&gt;The success of this partnership showcases the power of combining technical expertise with aligned values – proving that efficient technology solutions and environmental stewardship can work hand in hand.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&quot;ready-to-transform-your-infrastructure&quot; tabindex=&quot;-1&quot;&gt;&lt;strong&gt;Ready to Transform Your Infrastructure?&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;🚀 Reduce deployment times by 2+ hours and achieve 99.9% uptime&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;💰 Cut infrastructure costs by 30% while improving performance&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;🌱 Align your technology with your sustainability goals&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://resiz.es/&quot;&gt;Contact Resizes Platform&lt;/a&gt; to learn how we can help your organization achieve similar results.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;📞 &lt;a href=&quot;https://calendar.app.google/AYCwMMtZH58pyZPn7&quot;&gt;Schedule a Technical Consultation&lt;/a&gt;&lt;/strong&gt; | &lt;strong&gt;💬 &lt;a href=&quot;https://discord.gg/HjvRtMvT&quot;&gt;Join Our Discord Community&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;blockquote&gt;&lt;/blockquote&gt;
&lt;hr&gt;
&lt;p&gt;El proyecto &quot;Migración Tecnológica de Be Energy Part S.L. para la implantación de Resizes Platform&quot; se ha desarrollado por la empresa Resizes Platform Engineering SL, cofinanciado por el Ayuntamiento de Gijón a través de Gijón Impulsa en el marco del programa de Incentivos Impulsa - Subvenciones al Emprendimiento e Innovación, Línea II. Innovación Abierta.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://resiz.es/assets/blog/posts/2025-06-27-sotysolar-success-story/gijon-impulsa.png&quot; alt=&quot;Gijón Impulsa Logo&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;&lt;/p&gt;
</content:encoded></item><item><title>Monitor your EKS without dying in the effort!</title><link>https://resiz.es/blog/monitoring-kubernetes-cluster</link><guid isPermaLink="false">https://blog.resiz.es/monitoring-kubernetes-cluster</guid><pubDate>Mon, 07 Apr 2025 00:00:00 GMT</pubDate><description>Monitoring a Kubernetes cluster is essential to know what is going on or to be able to detect if something is wrong in time. There are multiple tools available for this purpose, but in this impleme…</description><content:encoded>&lt;p&gt;Monitoring a Kubernetes cluster is essential to know what is going on or to be able to detect if something is wrong in time. There are multiple tools available for this purpose, but in this implementation, we&#39;ll use &lt;strong&gt;Metrics Server&lt;/strong&gt;, &lt;strong&gt;Alloy&lt;/strong&gt;, &lt;strong&gt;Loki&lt;/strong&gt;, &lt;strong&gt;Kube Prometheus Stack&lt;/strong&gt;, and &lt;strong&gt;Alertmanager&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;This setup will be deployed on an EKS cluster, with all configurations managed through Terraform and Helm charts.&lt;/p&gt;
&lt;!--truncate--&gt;
&lt;h2 id=&quot;infrastructure-overview&quot; tabindex=&quot;-1&quot;&gt;Infrastructure Overview&lt;/h2&gt;
&lt;p&gt;The monitoring stack consists of several components such as:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Metrics Server&lt;/strong&gt;: For basic resource metrics collection&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Alloy&lt;/strong&gt;: To collect and forward metrics and logs&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Loki&lt;/strong&gt;: For log storage and querying&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Prometheus Operator&lt;/strong&gt;: To automatically manage Prometheus and Alertmanager configurations in Kubernetes.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Grafana&lt;/strong&gt;: For visualisation of metrics and logs (integrated with Prometheus and Loki).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Alertmanager&lt;/strong&gt;: For handling alerts and notifications&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;All components will be deployed using Helm charts with configurations stored in our platform repository.&lt;/p&gt;
&lt;h2 id=&quot;metrics-server&quot; tabindex=&quot;-1&quot;&gt;Metrics Server&lt;/h2&gt;
&lt;p&gt;Metrics Server is a tool used in Kubernetes that collects basic resource usage metrics (such as CPU and memory) from the nodes and pods in the cluster.
To implement it, we will create a &lt;code&gt;Chart.yaml&lt;/code&gt; and a &lt;code&gt;values.yaml&lt;/code&gt; similar to these:&lt;/p&gt;
&lt;p&gt;Chart.yaml:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;&lt;span class=&quot;hljs-attr&quot;&gt;apiVersion:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;v2&lt;/span&gt;
&lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;metrics-server&lt;/span&gt;
&lt;span class=&quot;hljs-attr&quot;&gt;description:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;metrics-server&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;helm&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;chart&lt;/span&gt;
&lt;span class=&quot;hljs-attr&quot;&gt;type:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;application&lt;/span&gt;
&lt;span class=&quot;hljs-attr&quot;&gt;version:&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;3.12&lt;/span&gt;&lt;span class=&quot;hljs-number&quot;&gt;.1&lt;/span&gt; &lt;span class=&quot;hljs-comment&quot;&gt;# Change to the current version&lt;/span&gt;
&lt;span class=&quot;hljs-attr&quot;&gt;dependencies:&lt;/span&gt;
&lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;metrics-server&lt;/span&gt;
  &lt;span class=&quot;hljs-attr&quot;&gt;version:&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;3.12&lt;/span&gt;&lt;span class=&quot;hljs-number&quot;&gt;.1&lt;/span&gt; &lt;span class=&quot;hljs-comment&quot;&gt;# Change to the current version&lt;/span&gt;
  &lt;span class=&quot;hljs-attr&quot;&gt;repository:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;https://kubernetes-sigs.github.io/metrics-server&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In this case, the &lt;code&gt;values.yaml&lt;/code&gt; file can be empty without any issues (although you still need to create the file, even if it is empty). Then, run &lt;code&gt;helm dependency update&lt;/code&gt;. This will create the necessary &lt;code&gt;Chart.lock&lt;/code&gt; and &lt;code&gt;.tgz&lt;/code&gt; files.&lt;/p&gt;
&lt;h2 id=&quot;alloy&quot; tabindex=&quot;-1&quot;&gt;Alloy&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Alloy&lt;/strong&gt; is designed to collect and send metrics, logs, etc., to different destinations, such as &lt;strong&gt;Grafana&lt;/strong&gt;, &lt;strong&gt;Loki&lt;/strong&gt;, or &lt;strong&gt;Prometheus&lt;/strong&gt;.
It is the successor to &lt;strong&gt;Grafana Agent&lt;/strong&gt;, so its configuration is similar (but not identical).&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Unlike &lt;strong&gt;Grafana Agent&lt;/strong&gt;, which used &lt;code&gt;.river&lt;/code&gt; files for configuration, Alloy uses &lt;code&gt;.alloy&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;In this case, we will use &lt;strong&gt;Alloy&lt;/strong&gt; to send logs to &lt;strong&gt;Loki&lt;/strong&gt;. To do this, start by creating our &lt;code&gt;Chart.yaml&lt;/code&gt; and &lt;code&gt;values.yaml&lt;/code&gt;.
These are just examples; you should modify them according to your needs:&lt;/p&gt;
&lt;p&gt;Chart.yaml:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;&lt;span class=&quot;hljs-attr&quot;&gt;apiVersion:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;v2&lt;/span&gt;
&lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;alloy&lt;/span&gt;
&lt;span class=&quot;hljs-attr&quot;&gt;description:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;A&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;Helm&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;chart&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;Alloy&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;(Promtail)&lt;/span&gt;
&lt;span class=&quot;hljs-attr&quot;&gt;version:&lt;/span&gt;  &lt;span class=&quot;hljs-number&quot;&gt;0.12&lt;/span&gt;&lt;span class=&quot;hljs-number&quot;&gt;.3&lt;/span&gt; &lt;span class=&quot;hljs-comment&quot;&gt;# Change to the current version&lt;/span&gt;
&lt;span class=&quot;hljs-attr&quot;&gt;dependencies:&lt;/span&gt;
&lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;alloy&lt;/span&gt;
  &lt;span class=&quot;hljs-attr&quot;&gt;version:&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;0.12&lt;/span&gt;&lt;span class=&quot;hljs-number&quot;&gt;.3&lt;/span&gt; &lt;span class=&quot;hljs-comment&quot;&gt;# Change to the current version&lt;/span&gt;
  &lt;span class=&quot;hljs-attr&quot;&gt;repository:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;https://grafana.github.io/helm-charts&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;values.yaml:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;&lt;span class=&quot;hljs-attr&quot;&gt;alloy:&lt;/span&gt;

  &lt;span class=&quot;hljs-attr&quot;&gt;ingress:&lt;/span&gt;
    &lt;span class=&quot;hljs-attr&quot;&gt;enabled:&lt;/span&gt; &lt;span class=&quot;hljs-literal&quot;&gt;false&lt;/span&gt;
    &lt;span class=&quot;hljs-attr&quot;&gt;annotations:&lt;/span&gt;
      &lt;span class=&quot;hljs-attr&quot;&gt;kubernetes.io/external-dns.create:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;true&quot;&lt;/span&gt;
    &lt;span class=&quot;hljs-attr&quot;&gt;ingressClassName:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;external&quot;&lt;/span&gt;
    &lt;span class=&quot;hljs-attr&quot;&gt;faroPort:&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;80&lt;/span&gt;
    &lt;span class=&quot;hljs-attr&quot;&gt;hosts:&lt;/span&gt;
      &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;alloy.example.com&lt;/span&gt; &lt;span class=&quot;hljs-comment&quot;&gt;# Change to your domain&lt;/span&gt;

  &lt;span class=&quot;hljs-attr&quot;&gt;alloy:&lt;/span&gt;
    &lt;span class=&quot;hljs-attr&quot;&gt;configMap:&lt;/span&gt;
      &lt;span class=&quot;hljs-attr&quot;&gt;create:&lt;/span&gt; &lt;span class=&quot;hljs-literal&quot;&gt;false&lt;/span&gt;
      &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;alloy&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;After this, run &lt;code&gt;helm dependency update&lt;/code&gt; to create both the &lt;code&gt;Chart.lock&lt;/code&gt; and the &lt;code&gt;.tgz&lt;/code&gt; file.
Then, the next step is to create a template called &lt;code&gt;config.yaml&lt;/code&gt;. This template will be used to instruct &lt;strong&gt;Alloy&lt;/strong&gt; to load the configuration from the files that will later be placed in a folder named &lt;strong&gt;config&lt;/strong&gt;.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;&lt;span class=&quot;hljs-attr&quot;&gt;apiVersion:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;v1&lt;/span&gt;
&lt;span class=&quot;hljs-attr&quot;&gt;kind:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;ConfigMap&lt;/span&gt;
&lt;span class=&quot;hljs-attr&quot;&gt;metadata:&lt;/span&gt;
  &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;alloy&lt;/span&gt;
&lt;span class=&quot;hljs-attr&quot;&gt;data:&lt;/span&gt;
  &lt;span class=&quot;hljs-attr&quot;&gt;config.alloy:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;|
    {{- range $file, $content := .Files.Glob &quot;config/*&quot; }}
    // {{ $file }}
    {{ $content | toString | indent 4 }}
    {{- end }}
&lt;/span&gt;
    &lt;span class=&quot;hljs-string&quot;&gt;loki.source.file&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;logs&quot;&lt;/span&gt; {
      &lt;span class=&quot;hljs-string&quot;&gt;targets&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;=&lt;/span&gt; [
        {&lt;span class=&quot;hljs-string&quot;&gt;__path__&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;/var/log/*.log&quot;&lt;/span&gt;},
      ]
      &lt;span class=&quot;hljs-string&quot;&gt;forward_to&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;=&lt;/span&gt; [&lt;span class=&quot;hljs-string&quot;&gt;loki.write.default.receiver&lt;/span&gt;]
    }

    &lt;span class=&quot;hljs-string&quot;&gt;loki.write&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;default&quot;&lt;/span&gt; {
    &lt;span class=&quot;hljs-string&quot;&gt;endpoint&lt;/span&gt; {
        &lt;span class=&quot;hljs-string&quot;&gt;url&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;loki-gateway.monitoring.svc.cluster.local&quot;&lt;/span&gt;  
        
        &lt;span class=&quot;hljs-string&quot;&gt;basic_auth&lt;/span&gt; {
            &lt;span class=&quot;hljs-string&quot;&gt;username&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;loki&quot;&lt;/span&gt;  
            &lt;span class=&quot;hljs-string&quot;&gt;password&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;loki_password&quot;&lt;/span&gt;  
        }
      }
    }
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now create the &lt;strong&gt;config&lt;/strong&gt; folder mentioned earlier. Inside it, we will store two files—one containing the general configuration and another with the specific configuration for &lt;strong&gt;Loki&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;default.alloy:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot;&gt;&lt;code&gt;logging {
    level  = &quot;info&quot;
    format = &quot;logfmt&quot;
}

discovery.kubernetes &quot;pods&quot; {
    role = &quot;pod&quot;
}

discovery.kubernetes &quot;services&quot; {
    role = &quot;service&quot;
}

discovery.kubernetes &quot;nodes&quot; {
    role = &quot;node&quot;
}

discovery.relabel &quot;pods_k8s_labels&quot; {
    targets = discovery.kubernetes.pods.targets
    
    rule {
        action = &quot;labelmap&quot;
        regex = &quot;__meta_kubernetes_namespace$&quot;
        replacement = &quot;namespace&quot;
    }
}
discovery.relabel &quot;services_k8s_labels&quot; {
    targets = discovery.kubernetes.services.targets
    rule {
        action = &quot;labelmap&quot;
        regex = &quot;__meta_kubernetes_(.+)&quot;
    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;loki.alloy:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot;&gt;&lt;code&gt;loki.source.kubernetes &quot;pods&quot; {
    targets    = discovery.relabel.pods_k8s_labels.output
    forward_to = [loki.write.loki.receiver]
}
loki.write &quot;loki&quot; {
    endpoint {
        url = &quot;http://loki-gateway.monitoring.svc:80/loki/api/v1/push&quot;
        basic_auth {
            username = &quot;loki&quot;
            password = &quot;loki_password&quot;
        }
    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;loki&quot; tabindex=&quot;-1&quot;&gt;Loki&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Loki&lt;/strong&gt; is a log storage and query system that can be integrated with &lt;strong&gt;Grafana&lt;/strong&gt;.
To get started, it is necessary to create a bucket where all the collected logs will be stored :&lt;/p&gt;
&lt;p&gt;loki.tf :&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-hcl&quot;&gt;module &quot;loki_oidc_role&quot; {
  source    = &quot;terraform-aws-modules/iam/aws//modules/iam-role-for-service-accounts-eks&quot;
  version   = &quot;~&amp;gt; 5.0&quot;
  role_name = &quot;loki-oidc-role&quot;
  oidc_providers = {
    oidc_provider = {
      provider_arn               = module.eks.oidc_provider_arn
      namespace_service_accounts = [&quot;monitoring:loki&quot;]
    }
  }
}

resource &quot;aws_iam_policy&quot; &quot;loki-policy&quot; {
  name        = &quot;loki&quot;
  path        = &quot;/&quot;
  description = &quot;Loki IAM Policy to have access to S3 buckets&quot;

  policy = jsonencode({
    Version = &quot;2012-10-17&quot;
    Statement = [
      {
        &quot;Sid&quot; : &quot;lokiPermissions&quot;,
        &quot;Effect&quot; : &quot;Allow&quot;,
        &quot;Action&quot; : [
          &quot;s3:PutObject&quot;,
          &quot;s3:GetObject&quot;,
          &quot;s3:ListBucket&quot;,
          &quot;s3:DeleteObject&quot;,
          &quot;s3:GetObjectTagging&quot;,
          &quot;s3:PutObjectTagging&quot;
        ],
        &quot;Resource&quot; : [
          &quot;arn:aws:s3:::${local.customer}-loki-chunks/*&quot;,
          &quot;arn:aws:s3:::${local.customer}-loki-chunks&quot;
        ]
      }
    ]
  })
}

resource &quot;aws_iam_role_policy_attachment&quot; &quot;loki-attach&quot; {
  role       = module.loki_oidc_role.iam_role_name
  policy_arn = aws_iam_policy.loki-policy.arn
}

resource &quot;aws_s3_bucket&quot; &quot;loki_chunks&quot; {
  bucket        = &quot;${local.customer}-loki-chunks&quot;
  force_destroy = true
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Once the bucket is created, the next step is to generate the &lt;code&gt;Chart.yaml&lt;/code&gt; and &lt;code&gt;values.yaml&lt;/code&gt; files.&lt;/p&gt;
&lt;p&gt;Chart.yaml :&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;&lt;span class=&quot;hljs-attr&quot;&gt;apiVersion:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;v2&lt;/span&gt;
&lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;loki&lt;/span&gt;
&lt;span class=&quot;hljs-attr&quot;&gt;description:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;loki-distributed&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;helm&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;chart&lt;/span&gt;
&lt;span class=&quot;hljs-attr&quot;&gt;type:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;application&lt;/span&gt;
&lt;span class=&quot;hljs-attr&quot;&gt;version:&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;0.80&lt;/span&gt;&lt;span class=&quot;hljs-number&quot;&gt;.2&lt;/span&gt; &lt;span class=&quot;hljs-comment&quot;&gt;#Change to the current version&lt;/span&gt;
&lt;span class=&quot;hljs-attr&quot;&gt;dependencies:&lt;/span&gt;
&lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;loki-distributed&lt;/span&gt;
  &lt;span class=&quot;hljs-attr&quot;&gt;version:&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;0.80&lt;/span&gt;&lt;span class=&quot;hljs-number&quot;&gt;.2&lt;/span&gt; &lt;span class=&quot;hljs-comment&quot;&gt;#Change to the current version&lt;/span&gt;
  &lt;span class=&quot;hljs-attr&quot;&gt;repository:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;https://grafana.github.io/helm-charts&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;values.yaml :&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;&lt;span class=&quot;hljs-attr&quot;&gt;loki-distributed:&lt;/span&gt;
  &lt;span class=&quot;hljs-attr&quot;&gt;nameOverride:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;loki&lt;/span&gt;
  &lt;span class=&quot;hljs-attr&quot;&gt;loki:&lt;/span&gt;
    &lt;span class=&quot;hljs-attr&quot;&gt;structuredConfig:&lt;/span&gt;
      &lt;span class=&quot;hljs-attr&quot;&gt;auth_enabled:&lt;/span&gt; &lt;span class=&quot;hljs-literal&quot;&gt;false&lt;/span&gt; &lt;span class=&quot;hljs-comment&quot;&gt;# Enable with X-Scope-OrgID header&lt;/span&gt;
      &lt;span class=&quot;hljs-attr&quot;&gt;compactor:&lt;/span&gt;
        &lt;span class=&quot;hljs-attr&quot;&gt;shared_store:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;s3&lt;/span&gt;
        &lt;span class=&quot;hljs-attr&quot;&gt;compaction_interval:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;10m&lt;/span&gt;
        &lt;span class=&quot;hljs-attr&quot;&gt;retention_enabled:&lt;/span&gt; &lt;span class=&quot;hljs-literal&quot;&gt;true&lt;/span&gt;
        &lt;span class=&quot;hljs-attr&quot;&gt;retention_delete_delay:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;1m&lt;/span&gt;
        &lt;span class=&quot;hljs-attr&quot;&gt;retention_delete_worker_count:&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;150&lt;/span&gt;
        &lt;span class=&quot;hljs-attr&quot;&gt;delete_request_cancel_period:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;10m&lt;/span&gt;

      &lt;span class=&quot;hljs-attr&quot;&gt;limits_config:&lt;/span&gt;
        &lt;span class=&quot;hljs-attr&quot;&gt;retention_period:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;1y&lt;/span&gt;

      &lt;span class=&quot;hljs-attr&quot;&gt;schema_config:&lt;/span&gt;
        &lt;span class=&quot;hljs-attr&quot;&gt;configs:&lt;/span&gt;
        &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;from:&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;2020-09-07&lt;/span&gt;
          &lt;span class=&quot;hljs-attr&quot;&gt;store:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;boltdb-shipper&lt;/span&gt;
          &lt;span class=&quot;hljs-attr&quot;&gt;object_store:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;s3&lt;/span&gt;
          &lt;span class=&quot;hljs-attr&quot;&gt;schema:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;v12&lt;/span&gt;
          &lt;span class=&quot;hljs-attr&quot;&gt;index:&lt;/span&gt;
            &lt;span class=&quot;hljs-attr&quot;&gt;prefix:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;loki_index_&lt;/span&gt;
            &lt;span class=&quot;hljs-attr&quot;&gt;period:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;24h&lt;/span&gt;

      &lt;span class=&quot;hljs-attr&quot;&gt;storage_config:&lt;/span&gt;
        &lt;span class=&quot;hljs-attr&quot;&gt;filesystem:&lt;/span&gt; &lt;span class=&quot;hljs-literal&quot;&gt;null&lt;/span&gt;
        &lt;span class=&quot;hljs-attr&quot;&gt;boltdb_shipper:&lt;/span&gt;
          &lt;span class=&quot;hljs-attr&quot;&gt;build_per_tenant_index:&lt;/span&gt; &lt;span class=&quot;hljs-literal&quot;&gt;true&lt;/span&gt;
          &lt;span class=&quot;hljs-attr&quot;&gt;shared_store:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;s3&lt;/span&gt;
        &lt;span class=&quot;hljs-attr&quot;&gt;aws:&lt;/span&gt;
          &lt;span class=&quot;hljs-attr&quot;&gt;region:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;us-east-1&lt;/span&gt; &lt;span class=&quot;hljs-comment&quot;&gt;# change to your region &lt;/span&gt;
          &lt;span class=&quot;hljs-attr&quot;&gt;bucketnames:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;example-loki-chunks&lt;/span&gt;
          &lt;span class=&quot;hljs-attr&quot;&gt;insecure:&lt;/span&gt; &lt;span class=&quot;hljs-literal&quot;&gt;false&lt;/span&gt;
          &lt;span class=&quot;hljs-attr&quot;&gt;s3forcepathstyle:&lt;/span&gt; &lt;span class=&quot;hljs-literal&quot;&gt;false&lt;/span&gt;

  &lt;span class=&quot;hljs-attr&quot;&gt;serviceAccount:&lt;/span&gt;
    &lt;span class=&quot;hljs-attr&quot;&gt;annotations:&lt;/span&gt;
      &lt;span class=&quot;hljs-attr&quot;&gt;eks.amazonaws.com/role-arn:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;arn:aws:iam::examplenumberaccount:role/loki-oidc-role&lt;/span&gt; &lt;span class=&quot;hljs-comment&quot;&gt;# change to your AWS account&lt;/span&gt;

  &lt;span class=&quot;hljs-attr&quot;&gt;gateway:&lt;/span&gt;
    &lt;span class=&quot;hljs-attr&quot;&gt;basicAuth:&lt;/span&gt;
      &lt;span class=&quot;hljs-attr&quot;&gt;enabled:&lt;/span&gt; &lt;span class=&quot;hljs-literal&quot;&gt;true&lt;/span&gt;
      &lt;span class=&quot;hljs-attr&quot;&gt;username:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;loki&lt;/span&gt;
      &lt;span class=&quot;hljs-attr&quot;&gt;password:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;loki_password&lt;/span&gt;

  &lt;span class=&quot;hljs-attr&quot;&gt;compactor:&lt;/span&gt;
    &lt;span class=&quot;hljs-attr&quot;&gt;enabled:&lt;/span&gt; &lt;span class=&quot;hljs-literal&quot;&gt;true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;After this, as with the previous tools, we will run &lt;code&gt;helm dependency update&lt;/code&gt; to create the &lt;code&gt;Chart.lock&lt;/code&gt; and &lt;code&gt;.tgz&lt;/code&gt; file.&lt;/p&gt;
&lt;h2 id=&quot;kube-prometheus-stack&quot; tabindex=&quot;-1&quot;&gt;Kube Prometheus Stack&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Kube Prometheus Stack&lt;/strong&gt; is a monitoring toolset designed for &lt;em&gt;Kubernetes&lt;/em&gt;, which automatically deploys components such as &lt;strong&gt;Prometheus&lt;/strong&gt;, &lt;strong&gt;Alertmanager&lt;/strong&gt;, and &lt;strong&gt;Grafana&lt;/strong&gt; in your cluster.
This solution, packaged as a Helm Chart, provides everything necessary to collect metrics, configure alerts, and visualize data, with predefined dashboards for &lt;em&gt;Kubernetes&lt;/em&gt;, nodes, and applications.
Here is an example of how its files would look:&lt;/p&gt;
&lt;p&gt;Chart.yaml :&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;&lt;span class=&quot;hljs-attr&quot;&gt;apiVersion:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;v2&lt;/span&gt;
&lt;span class=&quot;hljs-attr&quot;&gt;description:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;kube-prometheus-stack&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;collects&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;Kubernetes&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;manifests,&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;Grafana&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;dashboards,&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;and&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;Prometheus&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;rules&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;combined&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;with&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;documentation&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;and&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;scripts&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;to&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;provide&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;easy-to-operate&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;end-to-end&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;Kubernetes&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;cluster&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;monitoring&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;with&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;Prometheus&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;using&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;the&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;Prometheus&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;Operator.&lt;/span&gt;
&lt;span class=&quot;hljs-attr&quot;&gt;icon:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;https://raw.githubusercontent.com/prometheus/prometheus.github.io/master/assets/prometheus_logo-cb55bb5c346.png&lt;/span&gt;
&lt;span class=&quot;hljs-attr&quot;&gt;type:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;application&lt;/span&gt;

&lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;kube-prometheus-stack&lt;/span&gt;
&lt;span class=&quot;hljs-attr&quot;&gt;version:&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;69.8&lt;/span&gt;&lt;span class=&quot;hljs-number&quot;&gt;.2&lt;/span&gt; &lt;span class=&quot;hljs-comment&quot;&gt;#Change to the current version&lt;/span&gt;
&lt;span class=&quot;hljs-attr&quot;&gt;appVersion:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;v0.78.2&lt;/span&gt;
&lt;span class=&quot;hljs-attr&quot;&gt;kubeVersion:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;&amp;gt;=1.19.0-0&quot;&lt;/span&gt;
&lt;span class=&quot;hljs-attr&quot;&gt;home:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;https://github.com/prometheus-operator/kube-prometheus&lt;/span&gt;

&lt;span class=&quot;hljs-attr&quot;&gt;dependencies:&lt;/span&gt; 
  &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;kube-prometheus-stack&lt;/span&gt; 
    &lt;span class=&quot;hljs-attr&quot;&gt;version:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;69.8.2&quot;&lt;/span&gt; &lt;span class=&quot;hljs-comment&quot;&gt;#Change to the current version&lt;/span&gt;
    &lt;span class=&quot;hljs-attr&quot;&gt;repository:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;https://prometheus-community.github.io/helm-charts&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;values.yaml :&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;&lt;span class=&quot;hljs-attr&quot;&gt;kube-prometheus-stack:&lt;/span&gt; 
  &lt;span class=&quot;hljs-comment&quot;&gt;# Remove some rules we cannot scrape&lt;/span&gt;
  &lt;span class=&quot;hljs-attr&quot;&gt;defaultRules:&lt;/span&gt;
    &lt;span class=&quot;hljs-attr&quot;&gt;rules:&lt;/span&gt;
      &lt;span class=&quot;hljs-attr&quot;&gt;etcd:&lt;/span&gt; &lt;span class=&quot;hljs-literal&quot;&gt;false&lt;/span&gt;
      &lt;span class=&quot;hljs-attr&quot;&gt;kubeScheduler:&lt;/span&gt; &lt;span class=&quot;hljs-literal&quot;&gt;false&lt;/span&gt;
    &lt;span class=&quot;hljs-attr&quot;&gt;disabled:&lt;/span&gt;
      &lt;span class=&quot;hljs-attr&quot;&gt;TargetDown:&lt;/span&gt; &lt;span class=&quot;hljs-literal&quot;&gt;true&lt;/span&gt;
      &lt;span class=&quot;hljs-attr&quot;&gt;KubePodNotReady:&lt;/span&gt; &lt;span class=&quot;hljs-literal&quot;&gt;true&lt;/span&gt;
      &lt;span class=&quot;hljs-attr&quot;&gt;KubeContainerWaiting:&lt;/span&gt; &lt;span class=&quot;hljs-literal&quot;&gt;true&lt;/span&gt;
      &lt;span class=&quot;hljs-attr&quot;&gt;KubeHpaMaxedOut:&lt;/span&gt; &lt;span class=&quot;hljs-literal&quot;&gt;true&lt;/span&gt;
      &lt;span class=&quot;hljs-attr&quot;&gt;KubeDeploymentReplicasMismatch:&lt;/span&gt; &lt;span class=&quot;hljs-literal&quot;&gt;true&lt;/span&gt;
      &lt;span class=&quot;hljs-attr&quot;&gt;KubePodNotReady:&lt;/span&gt; &lt;span class=&quot;hljs-literal&quot;&gt;true&lt;/span&gt;
      &lt;span class=&quot;hljs-attr&quot;&gt;NodeSystemSaturation:&lt;/span&gt; &lt;span class=&quot;hljs-literal&quot;&gt;true&lt;/span&gt;
  &lt;span class=&quot;hljs-attr&quot;&gt;alertmanager:&lt;/span&gt;
    &lt;span class=&quot;hljs-attr&quot;&gt;ingress:&lt;/span&gt;
      &lt;span class=&quot;hljs-attr&quot;&gt;enabled:&lt;/span&gt; &lt;span class=&quot;hljs-literal&quot;&gt;true&lt;/span&gt;
      &lt;span class=&quot;hljs-attr&quot;&gt;ingressClassName:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;external&quot;&lt;/span&gt;
      &lt;span class=&quot;hljs-attr&quot;&gt;annotations:&lt;/span&gt;
        &lt;span class=&quot;hljs-attr&quot;&gt;nginx.ingress.kubernetes.io/force-ssl-redirect:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;true&quot;&lt;/span&gt;
        &lt;span class=&quot;hljs-attr&quot;&gt;kubernetes.io/external-dns.create:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;true&quot;&lt;/span&gt;
      &lt;span class=&quot;hljs-attr&quot;&gt;pathType:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;ImplementationSpecific&lt;/span&gt;
      &lt;span class=&quot;hljs-attr&quot;&gt;hosts:&lt;/span&gt;
        &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;alertmanager.example.com&lt;/span&gt; &lt;span class=&quot;hljs-comment&quot;&gt;#Change to your domain&lt;/span&gt;
      &lt;span class=&quot;hljs-attr&quot;&gt;paths:&lt;/span&gt;
        &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;/&lt;/span&gt;
    &lt;span class=&quot;hljs-attr&quot;&gt;config:&lt;/span&gt;
      &lt;span class=&quot;hljs-attr&quot;&gt;global:&lt;/span&gt;
        &lt;span class=&quot;hljs-attr&quot;&gt;resolve_timeout:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;5m&lt;/span&gt;
      &lt;span class=&quot;hljs-attr&quot;&gt;route:&lt;/span&gt;
        &lt;span class=&quot;hljs-attr&quot;&gt;group_by:&lt;/span&gt; [&lt;span class=&quot;hljs-string&quot;&gt;&quot;alertname&quot;&lt;/span&gt;, &lt;span class=&quot;hljs-string&quot;&gt;&quot;severity&quot;&lt;/span&gt;, &lt;span class=&quot;hljs-string&quot;&gt;&quot;job&quot;&lt;/span&gt;]
        &lt;span class=&quot;hljs-attr&quot;&gt;group_wait:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;30s&lt;/span&gt;
        &lt;span class=&quot;hljs-attr&quot;&gt;group_interval:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;5m&lt;/span&gt;
        &lt;span class=&quot;hljs-attr&quot;&gt;repeat_interval:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;12h&lt;/span&gt;
        &lt;span class=&quot;hljs-attr&quot;&gt;receiver:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;blackhole&lt;/span&gt;
        &lt;span class=&quot;hljs-attr&quot;&gt;routes:&lt;/span&gt;
          &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;receiver:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;blackhole&quot;&lt;/span&gt;
            &lt;span class=&quot;hljs-attr&quot;&gt;matchers:&lt;/span&gt;
              &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;alertname&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;InfoInhibitor&lt;/span&gt;
            &lt;span class=&quot;hljs-attr&quot;&gt;group_wait:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;0s&lt;/span&gt;
            &lt;span class=&quot;hljs-attr&quot;&gt;group_interval:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;1m&lt;/span&gt;
            &lt;span class=&quot;hljs-attr&quot;&gt;repeat_interval:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;30s&lt;/span&gt;
      &lt;span class=&quot;hljs-attr&quot;&gt;receivers:&lt;/span&gt;
        &lt;span class=&quot;hljs-comment&quot;&gt;# Just an empty receiver&lt;/span&gt;
        &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;blackhole&quot;&lt;/span&gt;
    &lt;span class=&quot;hljs-attr&quot;&gt;alertmanagerSpec:&lt;/span&gt;
      &lt;span class=&quot;hljs-attr&quot;&gt;alertmanagerConfigSelector:&lt;/span&gt;
        &lt;span class=&quot;hljs-attr&quot;&gt;matchLabels:&lt;/span&gt;
          &lt;span class=&quot;hljs-attr&quot;&gt;release:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;kube-prometheus-stack&lt;/span&gt;
      &lt;span class=&quot;hljs-attr&quot;&gt;alertmanagerConfigNamespaceSelector:&lt;/span&gt; {}

      &lt;span class=&quot;hljs-attr&quot;&gt;nodeSelector:&lt;/span&gt;
        &lt;span class=&quot;hljs-attr&quot;&gt;topology.kubernetes.io/zone:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;us-east-1c&lt;/span&gt;  &lt;span class=&quot;hljs-comment&quot;&gt;# Change to your region&lt;/span&gt;
      
      &lt;span class=&quot;hljs-attr&quot;&gt;affinity:&lt;/span&gt;
        &lt;span class=&quot;hljs-attr&quot;&gt;nodeAffinity:&lt;/span&gt;
          &lt;span class=&quot;hljs-attr&quot;&gt;requiredDuringSchedulingIgnoredDuringExecution:&lt;/span&gt;
            &lt;span class=&quot;hljs-attr&quot;&gt;nodeSelectorTerms:&lt;/span&gt;
              &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;matchExpressions:&lt;/span&gt;
                &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;key:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;topology.kubernetes.io/zone&lt;/span&gt;
                  &lt;span class=&quot;hljs-attr&quot;&gt;operator:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;In&lt;/span&gt;
                  &lt;span class=&quot;hljs-attr&quot;&gt;values:&lt;/span&gt;
                  &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt;  &lt;span class=&quot;hljs-string&quot;&gt;us-east-1c&lt;/span&gt;  &lt;span class=&quot;hljs-comment&quot;&gt;# Change to your region&lt;/span&gt;

  &lt;span class=&quot;hljs-attr&quot;&gt;grafana:&lt;/span&gt;
    &lt;span class=&quot;hljs-attr&quot;&gt;enabled:&lt;/span&gt; &lt;span class=&quot;hljs-literal&quot;&gt;true&lt;/span&gt;

    &lt;span class=&quot;hljs-attr&quot;&gt;nodeSelector:&lt;/span&gt;
      &lt;span class=&quot;hljs-attr&quot;&gt;topology.kubernetes.io/zone:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;us-east-1c&lt;/span&gt;  &lt;span class=&quot;hljs-comment&quot;&gt;# Change to your region&lt;/span&gt;
  
    &lt;span class=&quot;hljs-attr&quot;&gt;dashboards:&lt;/span&gt;
      &lt;span class=&quot;hljs-attr&quot;&gt;default:&lt;/span&gt;
        &lt;span class=&quot;hljs-attr&quot;&gt;node-exporter:&lt;/span&gt;
          &lt;span class=&quot;hljs-attr&quot;&gt;gnetId:&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;1860&lt;/span&gt;
          &lt;span class=&quot;hljs-attr&quot;&gt;revision:&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;32&lt;/span&gt;
        &lt;span class=&quot;hljs-attr&quot;&gt;nodejs:&lt;/span&gt;
          &lt;span class=&quot;hljs-attr&quot;&gt;gnetId:&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;11159&lt;/span&gt;
          &lt;span class=&quot;hljs-attr&quot;&gt;revision:&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;
          &lt;span class=&quot;hljs-attr&quot;&gt;datasource:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;Prometheus&lt;/span&gt;

    &lt;span class=&quot;hljs-attr&quot;&gt;affinity:&lt;/span&gt;
      &lt;span class=&quot;hljs-attr&quot;&gt;nodeAffinity:&lt;/span&gt;
        &lt;span class=&quot;hljs-attr&quot;&gt;requiredDuringSchedulingIgnoredDuringExecution:&lt;/span&gt;
          &lt;span class=&quot;hljs-attr&quot;&gt;nodeSelectorTerms:&lt;/span&gt;
            &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;matchExpressions:&lt;/span&gt;
              &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;key:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;topology.kubernetes.io/zone&lt;/span&gt;	
                &lt;span class=&quot;hljs-attr&quot;&gt;operator:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;In&lt;/span&gt;
                &lt;span class=&quot;hljs-attr&quot;&gt;values:&lt;/span&gt;
                &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;us-east-1c&lt;/span&gt; &lt;span class=&quot;hljs-comment&quot;&gt;# Change to your region &lt;/span&gt;
    &lt;span class=&quot;hljs-attr&quot;&gt;sidecar:&lt;/span&gt; 
      &lt;span class=&quot;hljs-attr&quot;&gt;dashboards:&lt;/span&gt;
        &lt;span class=&quot;hljs-attr&quot;&gt;label:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;grafana_dashboard&lt;/span&gt;
        &lt;span class=&quot;hljs-attr&quot;&gt;labelValue:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;&quot;&lt;/span&gt;
        &lt;span class=&quot;hljs-attr&quot;&gt;folderAnnotation:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;grafana-folder&lt;/span&gt;
        &lt;span class=&quot;hljs-attr&quot;&gt;annotations:&lt;/span&gt; 
          &lt;span class=&quot;hljs-attr&quot;&gt;grafana-folder:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;/tmp/dashboards/Kube-Prometheus-Stack&quot;&lt;/span&gt;
        &lt;span class=&quot;hljs-attr&quot;&gt;provider:&lt;/span&gt;
          &lt;span class=&quot;hljs-comment&quot;&gt;# Disallow updating provisioned dashboards from the UI&lt;/span&gt;
          &lt;span class=&quot;hljs-attr&quot;&gt;allowUiUpdates:&lt;/span&gt; &lt;span class=&quot;hljs-literal&quot;&gt;false&lt;/span&gt;
          &lt;span class=&quot;hljs-attr&quot;&gt;foldersFromFilesStructure:&lt;/span&gt; &lt;span class=&quot;hljs-literal&quot;&gt;true&lt;/span&gt;
      &lt;span class=&quot;hljs-attr&quot;&gt;datasources:&lt;/span&gt;  
        &lt;span class=&quot;hljs-attr&quot;&gt;uid:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;prometheus&lt;/span&gt;
        &lt;span class=&quot;hljs-attr&quot;&gt;alertmanager:&lt;/span&gt; 
          &lt;span class=&quot;hljs-attr&quot;&gt;uid:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;alertmanager&lt;/span&gt;
    &lt;span class=&quot;hljs-attr&quot;&gt;additionalDataSources:&lt;/span&gt;
      &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;Loki&lt;/span&gt;
        &lt;span class=&quot;hljs-attr&quot;&gt;type:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;loki&lt;/span&gt;
        &lt;span class=&quot;hljs-attr&quot;&gt;access:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;proxy&lt;/span&gt;
        &lt;span class=&quot;hljs-attr&quot;&gt;url:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;http://loki-gateway.monitoring.svc&lt;/span&gt;
        &lt;span class=&quot;hljs-attr&quot;&gt;user:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;loki&lt;/span&gt;
        &lt;span class=&quot;hljs-attr&quot;&gt;secureJsonData:&lt;/span&gt;
          &lt;span class=&quot;hljs-attr&quot;&gt;password:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;loki_password&lt;/span&gt;

    &lt;span class=&quot;hljs-attr&quot;&gt;ingress:&lt;/span&gt;
      &lt;span class=&quot;hljs-attr&quot;&gt;enabled:&lt;/span&gt; &lt;span class=&quot;hljs-literal&quot;&gt;true&lt;/span&gt;
      &lt;span class=&quot;hljs-attr&quot;&gt;ingressClassName:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;external&quot;&lt;/span&gt;   
      &lt;span class=&quot;hljs-attr&quot;&gt;annotations:&lt;/span&gt; 
        &lt;span class=&quot;hljs-attr&quot;&gt;nginx.ingress.kubernetes.io/force-ssl-redirect:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;true&quot;&lt;/span&gt;
        &lt;span class=&quot;hljs-attr&quot;&gt;kubernetes.io/external-dns.create:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;true&quot;&lt;/span&gt;
      &lt;span class=&quot;hljs-attr&quot;&gt;hosts:&lt;/span&gt;
        &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;grafana.example.com&lt;/span&gt; &lt;span class=&quot;hljs-comment&quot;&gt;#Change to your domain&lt;/span&gt;

  &lt;span class=&quot;hljs-comment&quot;&gt;# Remove some scrapings we cannot perform&lt;/span&gt;
  &lt;span class=&quot;hljs-attr&quot;&gt;kubeControllerManager:&lt;/span&gt;
    &lt;span class=&quot;hljs-attr&quot;&gt;enabled:&lt;/span&gt; &lt;span class=&quot;hljs-literal&quot;&gt;false&lt;/span&gt;
  &lt;span class=&quot;hljs-attr&quot;&gt;kubeEtcd:&lt;/span&gt;
    &lt;span class=&quot;hljs-attr&quot;&gt;enabled:&lt;/span&gt; &lt;span class=&quot;hljs-literal&quot;&gt;false&lt;/span&gt;
  &lt;span class=&quot;hljs-attr&quot;&gt;kubeScheduler:&lt;/span&gt;
    &lt;span class=&quot;hljs-attr&quot;&gt;enabled:&lt;/span&gt; &lt;span class=&quot;hljs-literal&quot;&gt;false&lt;/span&gt;
  &lt;span class=&quot;hljs-attr&quot;&gt;kubeProxy:&lt;/span&gt;
    &lt;span class=&quot;hljs-attr&quot;&gt;enabled:&lt;/span&gt; &lt;span class=&quot;hljs-literal&quot;&gt;false&lt;/span&gt;

  &lt;span class=&quot;hljs-attr&quot;&gt;prometheus:&lt;/span&gt;
    &lt;span class=&quot;hljs-attr&quot;&gt;enabled:&lt;/span&gt; &lt;span class=&quot;hljs-literal&quot;&gt;true&lt;/span&gt;
    &lt;span class=&quot;hljs-attr&quot;&gt;ingress:&lt;/span&gt;
      &lt;span class=&quot;hljs-attr&quot;&gt;ingressClassName:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;external&quot;&lt;/span&gt;
      &lt;span class=&quot;hljs-attr&quot;&gt;enabled:&lt;/span&gt; &lt;span class=&quot;hljs-literal&quot;&gt;true&lt;/span&gt;
      &lt;span class=&quot;hljs-attr&quot;&gt;annotations:&lt;/span&gt;
        &lt;span class=&quot;hljs-attr&quot;&gt;nginx.ingress.kubernetes.io/force-ssl-redirect:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;true&quot;&lt;/span&gt;
        &lt;span class=&quot;hljs-attr&quot;&gt;kubernetes.io/external-dns.create:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&#39;true&#39;&lt;/span&gt;
      &lt;span class=&quot;hljs-attr&quot;&gt;pathType:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;ImplementationSpecific&lt;/span&gt;
      &lt;span class=&quot;hljs-attr&quot;&gt;hosts:&lt;/span&gt;
        &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;prometheus.example.com&lt;/span&gt; &lt;span class=&quot;hljs-comment&quot;&gt;#Change to your domain&lt;/span&gt;
      &lt;span class=&quot;hljs-attr&quot;&gt;paths:&lt;/span&gt;
        &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;/&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Finally, run &lt;code&gt;helm dependency update&lt;/code&gt; to create the charts.&lt;/p&gt;
&lt;h2 id=&quot;alertmanager&quot; tabindex=&quot;-1&quot;&gt;Alertmanager&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Alertmanager&lt;/strong&gt; is a tool used to manage and send alerts or notifications to different platforms, such as emails, messaging systems, or, in this case, Discord channels.&lt;/p&gt;
&lt;p&gt;To add this functionality, we first need to create a webhook for the Discord channel where you want to receive these alerts. To do this, go to the &lt;em&gt;&quot;edit this channel&quot;&lt;/em&gt; settings of the chosen channel and then navigate to &lt;strong&gt;integrations&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://resiz.es/assets/blog/posts/2025-04-07-monitoring/alertmanager.png&quot; alt=&quot;AlertManager&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;&lt;/p&gt;
&lt;p&gt;Once in the &lt;strong&gt;integrations&lt;/strong&gt; window, go to &lt;strong&gt;webhooks&lt;/strong&gt;, where you can see all existing webhooks or create a new one. To add this webhook, you need to copy its URL.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://resiz.es/assets/blog/posts/2025-04-07-monitoring/webhook.png&quot; alt=&quot;webhook&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;&lt;/p&gt;
&lt;p&gt;After locating our &lt;strong&gt;webhook&lt;/strong&gt;, go to your cluster and create a new secret to store it, ensuring that the webhook URL is not publicly exposed.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-sh&quot;&gt;kubectl -n monitoring create secret generic discord-webhook \ --from-literal=url=&lt;span class=&quot;hljs-string&quot;&gt;&#39;https://discord.com/api/webhooks/...&#39;&lt;/span&gt; &lt;span class=&quot;hljs-comment&quot;&gt;#replace with your webhook URL&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You can verify that your secret has been created correctly with the following command:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-sh&quot;&gt;kubectl get secrets -n monitoring
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Next, navigate to the &lt;code&gt;values.yaml&lt;/code&gt; file of the kube-prometheus-stack (the one we created earlier). In this file, locate the Alertmanager section and add the following configurations:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;  &lt;span class=&quot;hljs-comment&quot;&gt;# Alertmanager configuration with secure webhook&lt;/span&gt;
  &lt;span class=&quot;hljs-attr&quot;&gt;alertmanager:&lt;/span&gt;
    &lt;span class=&quot;hljs-attr&quot;&gt;ingress:&lt;/span&gt;
      &lt;span class=&quot;hljs-attr&quot;&gt;enabled:&lt;/span&gt; &lt;span class=&quot;hljs-literal&quot;&gt;true&lt;/span&gt;
      &lt;span class=&quot;hljs-attr&quot;&gt;ingressClassName:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;external&quot;&lt;/span&gt;
      &lt;span class=&quot;hljs-attr&quot;&gt;annotations:&lt;/span&gt;
        &lt;span class=&quot;hljs-attr&quot;&gt;nginx.ingress.kubernetes.io/force-ssl-redirect:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;true&quot;&lt;/span&gt;
        &lt;span class=&quot;hljs-attr&quot;&gt;kubernetes.io/external-dns.create:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;true&quot;&lt;/span&gt;
      &lt;span class=&quot;hljs-attr&quot;&gt;pathType:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;ImplementationSpecific&lt;/span&gt;
      &lt;span class=&quot;hljs-attr&quot;&gt;hosts:&lt;/span&gt;
        &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;alertmanager.example.com&lt;/span&gt;
      &lt;span class=&quot;hljs-attr&quot;&gt;paths:&lt;/span&gt;
        &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;/&lt;/span&gt;
    &lt;span class=&quot;hljs-attr&quot;&gt;config:&lt;/span&gt;
      &lt;span class=&quot;hljs-attr&quot;&gt;global:&lt;/span&gt;
        &lt;span class=&quot;hljs-attr&quot;&gt;resolve_timeout:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;5m&lt;/span&gt;
      &lt;span class=&quot;hljs-attr&quot;&gt;route:&lt;/span&gt;
        &lt;span class=&quot;hljs-attr&quot;&gt;group_by:&lt;/span&gt; [&lt;span class=&quot;hljs-string&quot;&gt;&#39;alertname&#39;&lt;/span&gt;]
        &lt;span class=&quot;hljs-attr&quot;&gt;group_wait:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;30s&lt;/span&gt;
        &lt;span class=&quot;hljs-attr&quot;&gt;group_interval:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;5m&lt;/span&gt;
        &lt;span class=&quot;hljs-attr&quot;&gt;repeat_interval:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;12h&lt;/span&gt;
        &lt;span class=&quot;hljs-attr&quot;&gt;receiver:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&#39;discord&#39;&lt;/span&gt; &lt;span class=&quot;hljs-comment&quot;&gt;## The receiver, in this case, is Discord.&lt;/span&gt;
        &lt;span class=&quot;hljs-attr&quot;&gt;routes:&lt;/span&gt;
        &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;match:&lt;/span&gt; &lt;span class=&quot;hljs-comment&quot;&gt;## Route for this receiver&lt;/span&gt;
            &lt;span class=&quot;hljs-attr&quot;&gt;severity:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;warning&lt;/span&gt;
          &lt;span class=&quot;hljs-attr&quot;&gt;receiver:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&#39;discord&#39;&lt;/span&gt;
          &lt;span class=&quot;hljs-attr&quot;&gt;continue:&lt;/span&gt; &lt;span class=&quot;hljs-literal&quot;&gt;false&lt;/span&gt;
        &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;match:&lt;/span&gt;
            &lt;span class=&quot;hljs-attr&quot;&gt;alertname:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;InfoInhibitor&lt;/span&gt;
          &lt;span class=&quot;hljs-attr&quot;&gt;receiver:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&#39;blackhole&#39;&lt;/span&gt;
          &lt;span class=&quot;hljs-attr&quot;&gt;group_wait:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;0s&lt;/span&gt;
          &lt;span class=&quot;hljs-attr&quot;&gt;group_interval:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;1m&lt;/span&gt;
          &lt;span class=&quot;hljs-attr&quot;&gt;repeat_interval:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;30s&lt;/span&gt;
      &lt;span class=&quot;hljs-attr&quot;&gt;receivers:&lt;/span&gt;
      &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&#39;blackhole&#39;&lt;/span&gt;
      &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&#39;discord&#39;&lt;/span&gt; &lt;span class=&quot;hljs-comment&quot;&gt;## Specification of this receiver (webhook)&lt;/span&gt;
        &lt;span class=&quot;hljs-attr&quot;&gt;discord_configs:&lt;/span&gt;
        &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;webhook_url:&lt;/span&gt;
            &lt;span class=&quot;hljs-attr&quot;&gt;secretKeyRef:&lt;/span&gt; &lt;span class=&quot;hljs-comment&quot;&gt;## Using the previously created secret&lt;/span&gt;
              &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;discord-webhook&lt;/span&gt;
              &lt;span class=&quot;hljs-attr&quot;&gt;key:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;url&lt;/span&gt;
    &lt;span class=&quot;hljs-attr&quot;&gt;alertmanagerSpec:&lt;/span&gt;
      &lt;span class=&quot;hljs-attr&quot;&gt;alertmanagerConfigSelector:&lt;/span&gt;
        &lt;span class=&quot;hljs-attr&quot;&gt;matchLabels:&lt;/span&gt;
          &lt;span class=&quot;hljs-attr&quot;&gt;release:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;kube-prometheus-stack&lt;/span&gt;
      &lt;span class=&quot;hljs-attr&quot;&gt;alertmanagerConfigNamespaceSelector:&lt;/span&gt; {}
      &lt;span class=&quot;hljs-attr&quot;&gt;nodeSelector:&lt;/span&gt;
        &lt;span class=&quot;hljs-attr&quot;&gt;topology.kubernetes.io/zone:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;eu-west-1c&lt;/span&gt;
      &lt;span class=&quot;hljs-attr&quot;&gt;affinity:&lt;/span&gt;
        &lt;span class=&quot;hljs-attr&quot;&gt;nodeAffinity:&lt;/span&gt;
          &lt;span class=&quot;hljs-attr&quot;&gt;requiredDuringSchedulingIgnoredDuringExecution:&lt;/span&gt;
            &lt;span class=&quot;hljs-attr&quot;&gt;nodeSelectorTerms:&lt;/span&gt;
              &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;matchExpressions:&lt;/span&gt;
                &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;key:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;topology.kubernetes.io/zone&lt;/span&gt;
                  &lt;span class=&quot;hljs-attr&quot;&gt;operator:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;In&lt;/span&gt;
                  &lt;span class=&quot;hljs-attr&quot;&gt;values:&lt;/span&gt;
                  &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;eu-west-1c&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;With all this, we would have our monitoring stack connected to a Discord channel, so you can be more vigilant in case anything happens, improving the visibility and reliability of your cluster.&lt;/p&gt;
&lt;h2 id=&quot;resources&quot; tabindex=&quot;-1&quot;&gt;Resources&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://grafana.com/docs/loki/latest/&quot;&gt;Loki Documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://grafana.com/docs/alloy/latest/&quot;&gt;Alloy Documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://prometheus.io/docs/alerting/latest/alertmanager/&quot;&gt;Alert Manager Documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://prometheus.io/&quot;&gt;Prometheus Documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://prometheus-operator.dev/&quot;&gt;Prometheus Operator Documentation&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</content:encoded></item><item><title>Vibe coding - The democratization of software development</title><link>https://resiz.es/blog/vibe-coding</link><guid isPermaLink="false">https://blog.resiz.es/vibe-coding</guid><pubDate>Thu, 20 Mar 2025 00:00:00 GMT</pubDate><description>The term &#39;vibe coding&#39; has been gaining a lot of attention lately. It has been trending in recent weeks, especially after a tweet from Andrej Karpathy, former Tesla AI director. For those unfamilia…</description><content:encoded>&lt;p&gt;The term &#39;&lt;em&gt;vibe coding&lt;/em&gt;&#39; has been gaining a lot of attention lately. It has been trending in recent weeks, especially after a &lt;a href=&quot;https://x.com/karpathy/status/1886192184808149383&quot;&gt;tweet&lt;/a&gt; from Andrej Karpathy, former Tesla AI director.&lt;/p&gt;
&lt;p&gt;For those unfamiliar with it, &lt;em&gt;vibe coding&lt;/em&gt; is a way of building applications where developers or even non-technical users describe what they want in plain language, and &lt;strong&gt;AI generates the code automatically&lt;/strong&gt;. Instead of manually writing code line by line, &lt;strong&gt;users delegate all the responsibility of coding&lt;/strong&gt; by interacting with an LLM (like ChatGPT, Claude, or Sonnet) and only refining the output as needed.&lt;/p&gt;
&lt;!--truncate--&gt;
&lt;p&gt;An increasing number of tools are making it possible for anyone to build applications &lt;strong&gt;without coding or technical expertise&lt;/strong&gt;. These platforms, often built on top of LLMs, enable individuals to develop digital solutions while reducing time and development costs.&lt;/p&gt;
&lt;p&gt;This is changing the &lt;strong&gt;software development paradigm&lt;/strong&gt;, don’t you think?&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Eventually, people will be coding in their native language, rather than a programming language.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;When AI started booming around 2021-2022 I was &lt;strong&gt;very skeptical&lt;/strong&gt; about using it for coding. My biggest concerns by that time were:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;I didn’t want to rely on AI for problem solving, I wanted to go through the entire process myself to &lt;strong&gt;avoid limiting my growth&lt;/strong&gt; as a developer.&lt;/li&gt;
&lt;li&gt;Depending too much on AI could &lt;strong&gt;weaken my critical thinking&lt;/strong&gt; in decision-making.&lt;/li&gt;
&lt;li&gt;I wasn’t sure if I could trust AI to provide the best solutions, or whether they followed performance and security best practices.&lt;/li&gt;
&lt;li&gt;I was unsure about how the IA handle my application&#39;s sensitive data, given the potential risks related to privacy and confidentiality.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For some of these reasons, I didn’t integrate AI into my day-to-day tasks until the last few months. While I still have those concerns, I’ve been using &lt;strong&gt;Cursor as an IDE&lt;/strong&gt; which has different LLMs built-in and while I often run into contradictions or inefficient solutions in AI-generated responses, my &lt;strong&gt;coding speed has drastically improved&lt;/strong&gt;. That’s probably what I like the most, the AI-powered autocomplete, which understands the project’s context, makes development significantly faster.&lt;/p&gt;
&lt;p&gt;That said, I still stick to follow as many &lt;strong&gt;best practices&lt;/strong&gt; as I can and I always ask myself a few key questions when using AI to solve a problem:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Do I &lt;strong&gt;really&lt;/strong&gt; need AI for this? Could I solve it myself?&lt;/li&gt;
&lt;li&gt;Why didn’t I come up with this solution myself? How can I improve my problem-solving skills?&lt;/li&gt;
&lt;li&gt;Is this the &lt;strong&gt;most efficient&lt;/strong&gt; solution? Does it fit the &lt;strong&gt;architecture patterns&lt;/strong&gt; I follow? Is it a &lt;strong&gt;modular&lt;/strong&gt; solution?&lt;/li&gt;
&lt;li&gt;What does the language/tool’s &lt;strong&gt;official documentation&lt;/strong&gt; say about this?&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;At &lt;strong&gt;Resizes Dash&lt;/strong&gt;, we think &lt;em&gt;vibe coding&lt;/em&gt; in its purest form can be useful for things like prototyping (POC), making simple apps, or focusing on functionality and time-to-market in the &lt;strong&gt;short term&lt;/strong&gt;. But when it comes to building &lt;strong&gt;strong and reliable&lt;/strong&gt; architectures, solid programming knowledge, experience, and critical thinking are crucial qualities that AI has but isn’t quite good to rely on (at least for now). We do suggest using AI to speed up development, fix errors, or find alternative solutions, but relying on it for all your code development can &lt;strong&gt;stop you from growing as a developer&lt;/strong&gt; and could lead to a point where the state of the application becomes unmanageable or reaches a &lt;strong&gt;point of no return&lt;/strong&gt;.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Sometimes it’s best to let the LLM handle the small details while we focus on the big picture.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;An example of this could be seeing in our product, Resizes Dash, where the team is taking advantage of &lt;strong&gt;Amazon Bedrock&lt;/strong&gt; service and its different foundation models to get the consumption of Cloud resources and calculating a &lt;strong&gt;carbon footprint&lt;/strong&gt; based on AI inputs from power consuption and instance capacity.&lt;/p&gt;
&lt;p&gt;So, in the end, we think developers should always be in charge of making sure the code follows best practices, is &lt;strong&gt;scalable&lt;/strong&gt; and stays &lt;strong&gt;secure&lt;/strong&gt;. AI should be a tool to &lt;strong&gt;help and support developers&lt;/strong&gt;, not take over. It’s important to use AI to make your job easier, but still keep your own critical thinking and knowledge in the process.&lt;/p&gt;
&lt;p&gt;Right now, most LLMs generate code based on patterns. They &lt;strong&gt;lack intuition and strategic decision-making&lt;/strong&gt;, meaning their solutions often &lt;strong&gt;don’t involve real critical thinking&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;I encourage everyone to &lt;strong&gt;find their own vibe coding style.&lt;/strong&gt; Without a doubt, AI is the present and the future of software development, but as software developers we should never lose our ability to &lt;strong&gt;think critically&lt;/strong&gt;. More often than not, &lt;strong&gt;that’s what truly makes the difference,&lt;/strong&gt; not just in writing code, but in evolving a product in the most efficient way possible.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;AI isn’t here to reinvent the wheel, it’s here to make you more productive.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
</content:encoded></item><item><title>SFTP server in Kubernetes with SFTPGo</title><link>https://resiz.es/blog/sftp-server-in-kubernetes-with-sftpgo</link><guid isPermaLink="false">https://blog.resiz.es/sftp-server-in-kubernetes-with-sftpgo</guid><pubDate>Mon, 17 Feb 2025 00:00:00 GMT</pubDate><description>Have you ever needed to create an SFTP server? How do you do it? For those who have created an SFTP server before, you probably know that it is not easy to create and maintain an SFTP server. There…</description><content:encoded>&lt;p&gt;Have you ever needed to create an SFTP server? How do you do it?&lt;/p&gt;
&lt;p&gt;For those who have created an SFTP server before, you probably know that it is not easy to create and maintain an SFTP server. There are many ways to do it, but in this case, we are going to install SFTPGo in our Kubernetes cluster.&lt;/p&gt;
&lt;p&gt;SFTPGo is an open-source SFTP server that allows users to securely transfer files over SSH. It is written in Go (Golang) and is designed to be lightweight, easy to configure, and highly customizable. It supports multiple storage backends, including local filesystems, cloud storage (like S3, Google Cloud Storage, etc.), and more.&lt;/p&gt;
&lt;p&gt;The deployment of SFTPGo on an EKS cluster begins with provisioning the required resources, so let&#39;s start by creating the necessary infrastructure with Terraform.&lt;/p&gt;
&lt;!--truncate--&gt;
&lt;h2 id=&quot;external-secret&quot; tabindex=&quot;-1&quot;&gt;External Secret&lt;/h2&gt;
&lt;p&gt;For managing secrets in EKS, we are using &lt;a href=&quot;https://external-secrets.io/&quot;&gt;External Secrets Operator&lt;/a&gt;. To store the secrets for our SFTP server, we will use AWS Secrets Manager. An external secret is a Kubernetes resource that allows you to manage secrets from an external secret manager, in this case, AWS Secrets Manager.&lt;/p&gt;
&lt;p&gt;Here is the code to create the secret in AWS Secrets Manager:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-hcl&quot;&gt;resource &quot;aws_secretsmanager_secret&quot; &quot;sftpgo&quot; {
  name        = &quot;sftpgo&quot;
  description = &quot;Secrets for sftpgo in EKS production cluster&quot;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Once created, we will need to enter the following secrets:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;SFTPGO_DEFAULT_ADMIN_USERNAME&lt;/code&gt;: example_user&lt;/li&gt;
&lt;li&gt;&lt;code&gt;SFTPGO_DEFAULT_ADMIN_PASSWORD&lt;/code&gt;: example_password&lt;/li&gt;
&lt;li&gt;&lt;code&gt;SFTPGO_DATA_PROVIDER__DRIVER&lt;/code&gt;: postgresql&lt;/li&gt;
&lt;li&gt;&lt;code&gt;SFTPGO_DATA_PROVIDER__NAME&lt;/code&gt;: sftpgo.db&lt;/li&gt;
&lt;li&gt;&lt;code&gt;SFTPGO_DATA_PROVIDER__HOST&lt;/code&gt;: sftpgo-postgresql.sftpgo.svc.cluster.local &lt;em&gt;(this might change, it depends on your needs!)&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;SFTPGO_DATA_PROVIDER__PORT&lt;/code&gt;: 5432&lt;/li&gt;
&lt;li&gt;&lt;code&gt;SFTPGO_DATA_PROVIDER__USERNAME&lt;/code&gt;: sftpgo&lt;/li&gt;
&lt;li&gt;&lt;code&gt;SFTPGO_DATA_PROVIDER__PASSWORD&lt;/code&gt;: sftpgo_pg_pwd&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;As you can see, we are using a PostgreSQL database to store the users and the configuration for our SFTP server. And of course, we need to create the database. We will do this in the next section.&lt;/p&gt;
&lt;h2 id=&quot;sftpgo-resources&quot; tabindex=&quot;-1&quot;&gt;SFTPGo resources&lt;/h2&gt;
&lt;p&gt;On the other hand, it is necessary to create any other resource related to this new SFTP (policies, IAM role, permissions, etc.).&lt;/p&gt;
&lt;p&gt;We will create one role to access the &lt;strong&gt;AWS Secrets Manager&lt;/strong&gt; and another to &lt;strong&gt;access an S3 bucket&lt;/strong&gt;.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The &lt;strong&gt;s3 bucket&lt;/strong&gt; is used for storing the documents managed in the SFTP. We can use a single bucket for everything, but it is possible to use multiple buckets. Each user inside the SFTP can have access to a different bucket, or even a different folder inside the same bucket.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Our code would look something like this:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-hcl&quot;&gt;data &quot;aws_iam_policy_document&quot; &quot;sftpgo&quot; {
  statement {
    actions = [
      &quot;secretsmanager:GetResourcePolicy&quot;,
      &quot;secretsmanager:GetSecretValue&quot;,
      &quot;secretsmanager:DescribeSecret&quot;,
      &quot;secretsmanager:ListSecretVersionIds&quot;
    ]
    resources = [aws_secretsmanager_secret.sftpgo.arn]
  }
}

resource &quot;aws_iam_policy&quot; &quot;sftpgo&quot; {
  name        = &quot;sftpgo&quot;
  path        = &quot;/&quot;
  description = &quot;Policy to get sftpgo secrets&quot;
  policy      = data.aws_iam_policy_document.sftpgo.json
}

resource &quot;aws_iam_role&quot; &quot;sftpgo&quot; {
  name = &quot;external-secrets-sftpgo&quot;

  assume_role_policy = jsonencode({
    Version = &quot;2012-10-17&quot;
    Statement = [
      {
        Action = &quot;sts:AssumeRole&quot;
        Effect = &quot;Allow&quot;
        Principal = {
          AWS = &quot;arn:aws:iam::${data.aws_caller_identity.current.account_id}:role/external-secrets&quot;
        }
      }
    ]
  })
}

resource &quot;aws_iam_policy_attachment&quot; &quot;sftpgo&quot; {
  name       = &quot;sftpgo&quot;
  roles      = [aws_iam_role.sftpgo.name]
  policy_arn = aws_iam_policy.sftpgo.arn
}

resource &quot;aws_s3_bucket&quot; &quot;sftpgo&quot; {
  bucket = &quot;sftpgo&quot; # TODO: change this to the name of the bucket you want to use
}

data &quot;aws_iam_policy_document&quot; &quot;s3_full_access&quot; {
  statement {
    actions = [
      &quot;s3:*&quot;,  
    ]
    resources = [
      aws_s3_bucket.sftpgo.arn, 
      &quot;${aws_s3_bucket.sftpgo.arn}/*&quot;,  
    ]
  }
}

resource &quot;aws_iam_policy&quot; &quot;s3_full_access&quot; {
  name   = &quot;S3AccessPolicy-${aws_s3_bucket.sftpgo.bucket}&quot;
  policy = data.aws_iam_policy_document.s3_full_access.json
}

resource &quot;aws_iam_role&quot; &quot;irsa_role&quot; {
  name = &quot;sftpgo&quot;

  assume_role_policy = jsonencode({
    Version = &quot;2012-10-17&quot;
    Statement = [
      {
        Effect = &quot;Allow&quot;
        Principal = {
          Federated = &quot;arn:aws:iam::${data.aws_caller_identity.current.account_id}:oidc-provider/${replace(data.aws_eks_cluster.cluster.identity[0].oidc[0].issuer, &quot;https://&quot;, &quot;&quot;)}&quot;
        }
        Action = &quot;sts:AssumeRoleWithWebIdentity&quot;
        Condition = {
          StringEquals = {
            &quot;${replace(data.aws_eks_cluster.cluster.identity[0].oidc[0].issuer, &quot;https://&quot;, &quot;&quot;)}:sub&quot; = &quot;system:serviceaccount:sftpgo:sftpgo&quot;
          }
        }
      }
    ]
  })
}

resource &quot;aws_iam_role_policy_attachment&quot; &quot;attach_s3_policy&quot; {
  role       = aws_iam_role.irsa_role.name
  policy_arn = aws_iam_policy.s3_full_access.arn
}

resource &quot;aws_s3_bucket_public_access_block&quot; &quot;sftpgo&quot; {
  bucket = aws_s3_bucket.sftpgo.id

  block_public_acls       = true
  block_public_policy     = true
  ignore_public_acls      = true
  restrict_public_buckets = true
}
&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;¿What´s the IRSA Role?&lt;/strong&gt;: This Terraform code creates an IAM role that can be assumed by a ServiceAccount in an EKS cluster via IRSA. The role has a policy attached to it that allows access to S3. This is useful for applications running on Kubernetes that need to access AWS resources, such as S3, securely and without needing to store credentials directly on the cluster.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;To continue, we must also add a new data reference to our EKS cluster in our &lt;code&gt;data.tf&lt;/code&gt;:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-hcl&quot;&gt;data &quot;aws_eks_cluster&quot; &quot;cluster&quot; {
  name = &quot;example_name_cluster&quot; # TODO: change this to the name of your cluster
}
&lt;/code&gt;&lt;/pre&gt;
&lt;hr&gt;
&lt;h2 id=&quot;sftpgo-helm-chart&quot; tabindex=&quot;-1&quot;&gt;SFTPGo Helm Chart&lt;/h2&gt;
&lt;p&gt;When everything mentioned above has been created, we can continue creating the necessary chart to set up our SFTP server in Kubernetes.&lt;/p&gt;
&lt;p&gt;Let&#39;s start by creating a new folder called &lt;code&gt;sftpgo&lt;/code&gt;. Inside this folder, we will begin by creating the two main files: &lt;code&gt;values.yaml&lt;/code&gt; and &lt;code&gt;Chart.yaml&lt;/code&gt;.&lt;/p&gt;
&lt;h3 id=&quot;chartyaml&quot; tabindex=&quot;-1&quot;&gt;Chart.yaml&lt;/h3&gt;
&lt;p&gt;here will be listed the different dependencies that we will be using and their versions. In this case, &lt;strong&gt;sftpgo&lt;/strong&gt; and &lt;strong&gt;postgresql&lt;/strong&gt;.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;PostgreSQL&lt;/strong&gt; is required to store the new users who will use this SFTP and the configuration for the SFTP server.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;It should look something like this:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-yml&quot;&gt;&lt;span class=&quot;hljs-attr&quot;&gt;apiVersion:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;v2&lt;/span&gt;
&lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;sftpgo&lt;/span&gt;
&lt;span class=&quot;hljs-attr&quot;&gt;description:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;SFTPGo&lt;/span&gt; &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;Secure&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;SFTP&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;Server&lt;/span&gt;
&lt;span class=&quot;hljs-attr&quot;&gt;type:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;application&lt;/span&gt; 
&lt;span class=&quot;hljs-attr&quot;&gt;version:&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;0.23&lt;/span&gt;&lt;span class=&quot;hljs-number&quot;&gt;.1&lt;/span&gt;
&lt;span class=&quot;hljs-attr&quot;&gt;appVersion:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;2.5.4&quot;&lt;/span&gt;
&lt;span class=&quot;hljs-attr&quot;&gt;dependencies:&lt;/span&gt;
  &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;sftpgo&lt;/span&gt;
    &lt;span class=&quot;hljs-attr&quot;&gt;version:&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;0.23&lt;/span&gt;&lt;span class=&quot;hljs-number&quot;&gt;.1&lt;/span&gt;
    &lt;span class=&quot;hljs-attr&quot;&gt;repository:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;https://charts.sagikazarmark.dev&quot;&lt;/span&gt;
  &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;postgresql&lt;/span&gt;
    &lt;span class=&quot;hljs-attr&quot;&gt;version:&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;16.4&lt;/span&gt;
    &lt;span class=&quot;hljs-attr&quot;&gt;repository:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;https://charts.bitnami.com/bitnami&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;valuesyaml&quot; tabindex=&quot;-1&quot;&gt;Values.yaml&lt;/h3&gt;
&lt;p&gt;On the other hand, there is the &lt;code&gt;values.yaml&lt;/code&gt;, where the ingress, the serviceAccount, variables (in this case, retrieved from a secret stored in AWS) etc. are collected.&lt;/p&gt;
&lt;p&gt;It should looks like this:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-yml&quot;&gt;&lt;span class=&quot;hljs-attr&quot;&gt;sftpgo:&lt;/span&gt;
  &lt;span class=&quot;hljs-attr&quot;&gt;config:&lt;/span&gt; 
    &lt;span class=&quot;hljs-attr&quot;&gt;common:&lt;/span&gt;
      &lt;span class=&quot;hljs-attr&quot;&gt;proxy_protocol:&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;
    &lt;span class=&quot;hljs-attr&quot;&gt;data_provider:&lt;/span&gt;
      &lt;span class=&quot;hljs-attr&quot;&gt;create_default_admin:&lt;/span&gt; &lt;span class=&quot;hljs-literal&quot;&gt;true&lt;/span&gt; 

  &lt;span class=&quot;hljs-attr&quot;&gt;envFrom:&lt;/span&gt;
  &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;secretRef:&lt;/span&gt;
      &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;sftpgo&lt;/span&gt;

  &lt;span class=&quot;hljs-attr&quot;&gt;serviceAccount:&lt;/span&gt;
    &lt;span class=&quot;hljs-attr&quot;&gt;annotations:&lt;/span&gt; 
      &lt;span class=&quot;hljs-attr&quot;&gt;eks.amazonaws.com/role-arn:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;arn:aws:iam::ACCOUNT_ID:role/sftpgo&lt;/span&gt; &lt;span class=&quot;hljs-comment&quot;&gt;# &lt;span class=&quot;hljs-doctag&quot;&gt;TODO:&lt;/span&gt; change this to the IRSA role&lt;/span&gt;

  &lt;span class=&quot;hljs-attr&quot;&gt;ui:&lt;/span&gt;
    &lt;span class=&quot;hljs-attr&quot;&gt;ingress:&lt;/span&gt;
      &lt;span class=&quot;hljs-attr&quot;&gt;enabled:&lt;/span&gt; &lt;span class=&quot;hljs-literal&quot;&gt;true&lt;/span&gt;
      &lt;span class=&quot;hljs-attr&quot;&gt;className:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;external&lt;/span&gt;
      &lt;span class=&quot;hljs-attr&quot;&gt;annotations:&lt;/span&gt;
        &lt;span class=&quot;hljs-attr&quot;&gt;kubernetes.io/external-dns.create:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;true&quot;&lt;/span&gt;
      &lt;span class=&quot;hljs-attr&quot;&gt;hosts:&lt;/span&gt;
      &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;host:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;sftpgo.example.com&lt;/span&gt; &lt;span class=&quot;hljs-comment&quot;&gt;# &lt;span class=&quot;hljs-doctag&quot;&gt;TODO:&lt;/span&gt; change this to the domain you want to use&lt;/span&gt;
        &lt;span class=&quot;hljs-attr&quot;&gt;paths:&lt;/span&gt;
        &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;path:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;/&lt;/span&gt;
          &lt;span class=&quot;hljs-attr&quot;&gt;pathType:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;ImplementationSpecific&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Once we have these two files, we will create the &lt;code&gt;Chart.lock&lt;/code&gt; and the &lt;code&gt;charts&lt;/code&gt; with the following command:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-sh&quot;&gt;helm dep up
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;With this, a folder with the Helm Chart dependencies called &lt;code&gt;charts&lt;/code&gt; and a &lt;code&gt;Chart.lock&lt;/code&gt; file should have been created inside our &lt;code&gt;sftpgo&lt;/code&gt; folder.&lt;/p&gt;
&lt;p&gt;A folder called &lt;strong&gt;templates&lt;/strong&gt; is also needed. There will be created both &lt;code&gt;externalsecret.yaml&lt;/code&gt; and &lt;code&gt;secretstore.yaml&lt;/code&gt;. This will allow us to manage the secrets we have previously stored in our &lt;strong&gt;AWS Secret Manager&lt;/strong&gt;.&lt;/p&gt;
&lt;h3 id=&quot;postgresql&quot; tabindex=&quot;-1&quot;&gt;postgresql&lt;/h3&gt;
&lt;p&gt;It&#39;s necessary to configure our postgres. To do so, access to the Postgres database is done through the &lt;code&gt;sftpgo-postgresql&lt;/code&gt; secret.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-sh&quot;&gt;kubectl &lt;span class=&quot;hljs-built_in&quot;&gt;exec&lt;/span&gt; -it sftpgo-postgresql-0 -- psql -U postgres
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Once inside,  write the configuration needed, in this case it is:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-sh&quot;&gt;CREATE USER &lt;span class=&quot;hljs-string&quot;&gt;&quot;sftpgo&quot;&lt;/span&gt; WITH ENCRYPTED PASSWORD &lt;span class=&quot;hljs-string&quot;&gt;&#39;sftpgo_pg_pwd&#39;&lt;/span&gt;;
CREATE DATABASE &lt;span class=&quot;hljs-string&quot;&gt;&quot;sftpgo.db&quot;&lt;/span&gt;;
GRANT ALL PRIVILEGES ON DATABASE &lt;span class=&quot;hljs-string&quot;&gt;&quot;sftpgo.db&quot;&lt;/span&gt; TO &lt;span class=&quot;hljs-string&quot;&gt;&quot;sftpgo&quot;&lt;/span&gt;;
CREATE TABLE schema_version (
    version INT NOT NULL
);
GRANT ALL PRIVILEGES ON SCHEMA public TO sftpgo;
SELECT grantee, privilege_type 
FROM information_schema.role_table_grants 
WHERE table_schema = &lt;span class=&quot;hljs-string&quot;&gt;&#39;public&#39;&lt;/span&gt;;
ALTER SCHEMA public OWNER TO sftpgo;
&lt;span class=&quot;hljs-built_in&quot;&gt;exit&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Subsequently,enter this time in the sftpgo specific database.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-sh&quot;&gt;kubectl &lt;span class=&quot;hljs-built_in&quot;&gt;exec&lt;/span&gt; -it sftpgo-postgresql-0 -- psql -U postgres -d sftpgo.db
GRANT ALL PRIVILEGES ON DATABASE &lt;span class=&quot;hljs-string&quot;&gt;&quot;sftpgo.db&quot;&lt;/span&gt; TO sftpgo;
GRANT USAGE, CREATE ON SCHEMA public TO sftpgo;
ALTER SCHEMA public OWNER TO sftpgo;
&lt;span class=&quot;hljs-built_in&quot;&gt;exit&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;With this we would already have the necessary configuration inside postgres.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Remember&lt;/strong&gt;: Each time the password and user are changed in the secret manager, we must (in addition to killing it in argocd) perform the above steps again inside postgres.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id=&quot;secretstoreyaml&quot; tabindex=&quot;-1&quot;&gt;secretstore.yaml&lt;/h3&gt;
&lt;p&gt;The secret store is necessary to be able to manage our secrets. Its code would look something like the following:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-yml&quot;&gt;&lt;span class=&quot;hljs-attr&quot;&gt;apiVersion:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;external-secrets.io/v1beta1&lt;/span&gt;
&lt;span class=&quot;hljs-attr&quot;&gt;kind:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;SecretStore&lt;/span&gt;
&lt;span class=&quot;hljs-attr&quot;&gt;metadata:&lt;/span&gt;
  &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;external-secrets-sftpgo&lt;/span&gt;
&lt;span class=&quot;hljs-attr&quot;&gt;spec:&lt;/span&gt;
  &lt;span class=&quot;hljs-attr&quot;&gt;provider:&lt;/span&gt;
    &lt;span class=&quot;hljs-attr&quot;&gt;aws:&lt;/span&gt;
      &lt;span class=&quot;hljs-attr&quot;&gt;service:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;SecretsManager&lt;/span&gt;
      &lt;span class=&quot;hljs-attr&quot;&gt;role:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;arn:aws:iam::ACCOUNT_ID:role/external-secrets-sftpgo&lt;/span&gt; &lt;span class=&quot;hljs-comment&quot;&gt;# &lt;span class=&quot;hljs-doctag&quot;&gt;TODO:&lt;/span&gt; change this to the IRSA role&lt;/span&gt;
      &lt;span class=&quot;hljs-attr&quot;&gt;region:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;us-east-1&lt;/span&gt; &lt;span class=&quot;hljs-comment&quot;&gt;# &lt;span class=&quot;hljs-doctag&quot;&gt;TODO:&lt;/span&gt; change this to the region of your cluster&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;externalsecretyaml&quot; tabindex=&quot;-1&quot;&gt;externalsecret.yaml&lt;/h3&gt;
&lt;p&gt;Finally, the &lt;code&gt;externalsecret.yaml&lt;/code&gt; file that contains all the secrets we mentioned earlier.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-yml&quot;&gt;&lt;span class=&quot;hljs-attr&quot;&gt;apiVersion:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;external-secrets.io/v1beta1&lt;/span&gt;
&lt;span class=&quot;hljs-attr&quot;&gt;kind:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;ExternalSecret&lt;/span&gt;

&lt;span class=&quot;hljs-attr&quot;&gt;metadata:&lt;/span&gt;
  &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;sftpgo&lt;/span&gt;
  &lt;span class=&quot;hljs-attr&quot;&gt;namespace:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;sftpgo&lt;/span&gt; 

&lt;span class=&quot;hljs-attr&quot;&gt;spec:&lt;/span&gt;
  &lt;span class=&quot;hljs-attr&quot;&gt;refreshInterval:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;10m&quot;&lt;/span&gt;
  &lt;span class=&quot;hljs-attr&quot;&gt;secretStoreRef:&lt;/span&gt;
    &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;external-secrets-sftpgo&lt;/span&gt;
    &lt;span class=&quot;hljs-attr&quot;&gt;kind:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;SecretStore&lt;/span&gt;

  &lt;span class=&quot;hljs-attr&quot;&gt;target:&lt;/span&gt;
    &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;sftpgo&lt;/span&gt;

  &lt;span class=&quot;hljs-attr&quot;&gt;dataFrom:&lt;/span&gt;
  &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;extract:&lt;/span&gt;
      &lt;span class=&quot;hljs-attr&quot;&gt;key:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;sftpgo&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;lets-test-it&quot; tabindex=&quot;-1&quot;&gt;Let&#39;s test it!&lt;/h2&gt;
&lt;p&gt;With all our resources created, we can prove that everything is going well with several steps:&lt;/p&gt;
&lt;h3 id=&quot;1-enter-the-sftpgo-host&quot; tabindex=&quot;-1&quot;&gt;1. Enter the SFTPGo host&lt;/h3&gt;
&lt;p&gt;We can enter the host that we created earlier in the &lt;code&gt;values.yaml&lt;/code&gt; file (sftpgo.example.com) and see a login screen like the one in the following image. With what we have done, it should be possible to log in as the admin user using the credentials stored in our AWS Secret Manager.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://resiz.es/assets/blog/posts/2025-02-17-sftp/sftpgo_login.png&quot; alt=&quot;Sftpgo Login&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;&lt;/p&gt;
&lt;h3 id=&quot;2-send-a-file-from-our-local-to-sftpgo&quot; tabindex=&quot;-1&quot;&gt;2. Send a file from our local to SFTPGo.&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Remember&lt;/strong&gt;: We are doing everything from a user login, so we first need to create a user in the SFTPGo UI.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;To save a test file in SFTPGo, go to our terminal and log in with the following command:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-sh&quot;&gt;sftp user@sftpgo.example.com
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Later, after creating a test .txt file, we will save it in SFTPGo inside a folder called &quot;example&quot; &lt;em&gt;(It&#39;s can also be saved directly in the root directory; it&#39;s just a test to see the possibility of navigating and organizing files within SFTPGo)&lt;/em&gt;.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-sh&quot;&gt;sftp&amp;gt; &lt;span class=&quot;hljs-built_in&quot;&gt;mkdir&lt;/span&gt; /example  
sftp&amp;gt; &lt;span class=&quot;hljs-built_in&quot;&gt;cd&lt;/span&gt; /home/example
sftp&amp;gt; put test_file.txt
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If everything has gone well, it should be possible to see our file in the SFTPGo UI and if you go to the S3 bucket, you should also be able to see the file stored there.&lt;/p&gt;
&lt;h2 id=&quot;resources&quot; tabindex=&quot;-1&quot;&gt;Resources&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://docs.sftpgo.com/latest/tutorials/postgresql-s3/&quot;&gt;SFTPGo Docs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://artifacthub.io/packages/helm/sagikazarmark/sftpgo&quot;&gt;SFTPGo Helm Chart&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</content:encoded></item><item><title>Reducing app image vulnerabilities to 0!</title><link>https://resiz.es/blog/image-vulnerabilities</link><guid isPermaLink="false">https://blog.resiz.es/image-vulnerabilities</guid><pubDate>Mon, 06 May 2024 00:00:00 GMT</pubDate><description>Do you know that you can reduce your application image vulnerabilities from more than 1000 to 0? Do you know that you can reduce your image application size more than 85%?</description><content:encoded>&lt;p&gt;Do you know that you can reduce your application image vulnerabilities from &lt;strong&gt;more than 1000 to 0&lt;/strong&gt;?&lt;/p&gt;
&lt;p&gt;Do you know that you can reduce your image application size &lt;strong&gt;more than 85%&lt;/strong&gt;?&lt;/p&gt;
&lt;!--truncate--&gt;
&lt;h2 id=&quot;introduction&quot; tabindex=&quot;-1&quot;&gt;Introduction&lt;/h2&gt;
&lt;p&gt;Any piece of software can be improved, there is no perfect software out there. We can improve our software with many different strategies such as:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Improving loops and specific programming language patterns&lt;/li&gt;
&lt;li&gt;Using algorithms like recursive functions&lt;/li&gt;
&lt;li&gt;Removing unused files or functions&lt;/li&gt;
&lt;li&gt;Removing unused dependencies as libraries&lt;/li&gt;
&lt;li&gt;etc.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In this case, we are going to focus on the application image we generate so the software is able to run on any system, like your local machine or your Kubernetes cluster. More specifically, we are going to focus on the vulnerabilities your image has and the image size of your image.&lt;/p&gt;
&lt;h2 id=&quot;prerequisites&quot; tabindex=&quot;-1&quot;&gt;Prerequisites&lt;/h2&gt;
&lt;p&gt;For this example, we need to have installed the following tools:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://docs.docker.com/engine/install/&quot;&gt;Docker&lt;/a&gt; or any other container runtime like &lt;a href=&quot;https://podman.io/docs/installation&quot;&gt;Podman&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/aquasecurity/trivy?tab=readme-ov-file#get-trivy&quot;&gt;Trivy&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;the-starting-point&quot; tabindex=&quot;-1&quot;&gt;The Starting Point&lt;/h2&gt;
&lt;p&gt;I&#39;ve been developing a Node.js application for a demo API. In order to create the image for my application, I was using the following &lt;code&gt;Dockerfile.vuln&lt;/code&gt;:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-dockerfile&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;FROM&lt;/span&gt; node:&lt;span class=&quot;hljs-number&quot;&gt;20&lt;/span&gt;

&lt;span class=&quot;hljs-comment&quot;&gt;# Set the working directory in the container&lt;/span&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;WORKDIR&lt;/span&gt;&lt;span class=&quot;language-bash&quot;&gt; /app&lt;/span&gt;

&lt;span class=&quot;hljs-comment&quot;&gt;# Copy the package.json and package-lock.json files to the container&lt;/span&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;COPY&lt;/span&gt;&lt;span class=&quot;language-bash&quot;&gt; package*.json ./&lt;/span&gt;

&lt;span class=&quot;hljs-comment&quot;&gt;# Install the dependencies&lt;/span&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;RUN&lt;/span&gt;&lt;span class=&quot;language-bash&quot;&gt; npm install&lt;/span&gt;

&lt;span class=&quot;hljs-comment&quot;&gt;# Copy the rest of the application code to the container&lt;/span&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;COPY&lt;/span&gt;&lt;span class=&quot;language-bash&quot;&gt; . .&lt;/span&gt;

&lt;span class=&quot;hljs-comment&quot;&gt;# Expose the port on which the application will run&lt;/span&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;EXPOSE&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;5200&lt;/span&gt;

&lt;span class=&quot;hljs-comment&quot;&gt;# Start the application&lt;/span&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;CMD&lt;/span&gt;&lt;span class=&quot;language-bash&quot;&gt; [&lt;span class=&quot;hljs-string&quot;&gt;&quot;npx&quot;&lt;/span&gt;, &lt;span class=&quot;hljs-string&quot;&gt;&quot;ts-node&quot;&lt;/span&gt;, &lt;span class=&quot;hljs-string&quot;&gt;&quot;src/server.ts&quot;&lt;/span&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;At this point, running:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;docker build -t demo-api . -f Dockerfile.vuln
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;the image size is 1.23GB:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://resiz.es/assets/blog/posts/2024-05-06-image-vuln.md/vuln-1.png&quot; alt=&quot;Image size&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;&lt;/p&gt;
&lt;h3 id=&quot;lets-check-the-vulnerabilities&quot; tabindex=&quot;-1&quot;&gt;Let&#39;s check the vulnerabilities&lt;/h3&gt;
&lt;p&gt;Running &lt;code&gt;trivy image demo-api&lt;/code&gt;, we can check the following vulnerabilities:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://resiz.es/assets/blog/posts/2024-05-06-image-vuln.md/vuln-2.png&quot; alt=&quot;Application image vulnerabilities&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;&lt;/p&gt;
&lt;p&gt;So we have &lt;strong&gt;1170 different vulnerabilities&lt;/strong&gt; and 5 of them are CRITICAL!!&lt;/p&gt;
&lt;p&gt;We have a problem. We need to solve it as soon as possible!&lt;/p&gt;
&lt;h2 id=&quot;the-solution&quot; tabindex=&quot;-1&quot;&gt;The Solution&lt;/h2&gt;
&lt;p&gt;To solve the problem, we can change the &lt;code&gt;Dockerfile.vuln&lt;/code&gt; so we rely on the &lt;a href=&quot;https://www.chainguard.dev/&quot;&gt;Chainguard&lt;/a&gt;&#39;s Node.js image for building the application and the Chainguard&#39;s Wolfi base image for running the application so the new &lt;code&gt;Dockerfile&lt;/code&gt; looks like this:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-dockerfile&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;FROM&lt;/span&gt; cgr.dev/chainguard/node:latest-dev as build

&lt;span class=&quot;hljs-keyword&quot;&gt;USER&lt;/span&gt; root

&lt;span class=&quot;hljs-keyword&quot;&gt;WORKDIR&lt;/span&gt;&lt;span class=&quot;language-bash&quot;&gt; /app&lt;/span&gt;

&lt;span class=&quot;hljs-keyword&quot;&gt;COPY&lt;/span&gt;&lt;span class=&quot;language-bash&quot;&gt; . .&lt;/span&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;RUN&lt;/span&gt;&lt;span class=&quot;language-bash&quot;&gt; npm install&lt;/span&gt;

&lt;span class=&quot;hljs-keyword&quot;&gt;FROM&lt;/span&gt; cgr.dev/chainguard/wolfi-base

&lt;span class=&quot;hljs-keyword&quot;&gt;RUN&lt;/span&gt;&lt;span class=&quot;language-bash&quot;&gt; apk update &amp;amp;&amp;amp; apk add nodejs tini&lt;/span&gt;

&lt;span class=&quot;hljs-keyword&quot;&gt;WORKDIR&lt;/span&gt;&lt;span class=&quot;language-bash&quot;&gt; /app&lt;/span&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;COPY&lt;/span&gt;&lt;span class=&quot;language-bash&quot;&gt; --from=build /app /app&lt;/span&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;ENV&lt;/span&gt; PATH=&lt;span class=&quot;hljs-string&quot;&gt;&quot;/app/node_modules/.bin:${PATH}&quot;&lt;/span&gt;

&lt;span class=&quot;hljs-keyword&quot;&gt;EXPOSE&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;5200&lt;/span&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;ENTRYPOINT&lt;/span&gt;&lt;span class=&quot;language-bash&quot;&gt; [&lt;span class=&quot;hljs-string&quot;&gt;&quot;tini&quot;&lt;/span&gt;, &lt;span class=&quot;hljs-string&quot;&gt;&quot;--&quot;&lt;/span&gt;, &lt;span class=&quot;hljs-string&quot;&gt;&quot;ts-node&quot;&lt;/span&gt;, &lt;span class=&quot;hljs-string&quot;&gt;&quot;src/server.ts&quot;&lt;/span&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now we can build the image and check the differences. Let&#39;s run &lt;code&gt;docker build -t demo-api . -f Dockerfile&lt;/code&gt;:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://resiz.es/assets/blog/posts/2024-05-06-image-vuln.md/vuln-3.png&quot; alt=&quot;Image size&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;&lt;/p&gt;
&lt;p&gt;So we have reduced the image size &lt;strong&gt;from 1.23GB to 189MB&lt;/strong&gt; which is more than &lt;strong&gt;85%&lt;/strong&gt;! That&#39;s crazy, right?&lt;/p&gt;
&lt;h3 id=&quot;lets-check-again-the-vulnerabilities&quot; tabindex=&quot;-1&quot;&gt;Let&#39;s check again the vulnerabilities&lt;/h3&gt;
&lt;p&gt;We can now run again &lt;code&gt;trivy image demo-api&lt;/code&gt; to check image vulnerabilities:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://resiz.es/assets/blog/posts/2024-05-06-image-vuln.md/vuln-4.png&quot; alt=&quot;Application image vulnerabilities&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;&lt;/p&gt;
&lt;p&gt;After running the trivy command, we can check we reduced the vulnerabilities &lt;strong&gt;from 1170 to 0&lt;/strong&gt;! Again, this is crazy! Marvelous!&lt;/p&gt;
&lt;h2 id=&quot;conclusion&quot; tabindex=&quot;-1&quot;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;In conclusion, optimizing application images not only enhances security but also improves efficiency. As demonstrated through the transformation of a Node.js application, we significantly reduced the vulnerabilities from an overwhelming number to none, and decreased the image size by more than 85%.&lt;/p&gt;
&lt;p&gt;This was achieved by utilizing best practices such as removing unused dependencies and files, and employing Chainguard&#39;s images which are free for the latest version, optimizing your supply chain security.&lt;/p&gt;
&lt;p&gt;Such practices are essential, especially in environments like Kubernetes clusters, where security and resource optimization are critical. By continually refining the application image, developers can ensure that their software remains robust, secure, and performs efficiently across various systems. This approach not only mitigates potential security risks but also contributes to a more sustainable and cost-effective software deployment.&lt;/p&gt;
&lt;h2 id=&quot;references&quot; tabindex=&quot;-1&quot;&gt;References&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=hfpVS-UP4Yw&quot;&gt;Adrian Mouat&#39;s video in Youtube&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</content:encoded></item><item><title>Resizes Docs Site is Live!</title><link>https://resiz.es/blog/resizes-docs</link><guid isPermaLink="false">https://blog.resiz.es/resizes-docs</guid><pubDate>Wed, 17 Apr 2024 00:00:00 GMT</pubDate><description>Historical announcement of the former Resizes documentation site, with current alternatives.</description><content:encoded>&lt;aside class=&quot;blog-callout info&quot;&gt;&lt;p&gt;&lt;strong&gt;Update — 17 September 2026:&lt;/strong&gt; The documentation site and contribution link announced here are no longer publicly available. Explore our &lt;a href=&quot;https://resiz.es/blog&quot;&gt;engineering articles&lt;/a&gt; or &lt;a href=&quot;https://resiz.es/contact&quot;&gt;contact the team&lt;/a&gt; for current guidance. This announcement is retained for historical context.&lt;/p&gt;&lt;/aside&gt;&lt;p&gt;Our new docs site is live! 📚
Now you can explore and contribute to topics on Platform Engineering. Dive in and level up your knowledge today.&lt;/p&gt;
&lt;p&gt;Plus, we welcome your contributions! Feel free to add your insights and suggestions to our public repository on GitHub. Let&#39;s collaborate and build together.&lt;/p&gt;
&lt;p&gt;Documentation site: https://docs.resiz.es/ (no longer publicly available)
GitHub repository: https://github.com/resizes/docs (no longer publicly available)&lt;/p&gt;
</content:encoded></item><item><title>Resizes Blog</title><link>https://resiz.es/blog/resizes-blog</link><guid isPermaLink="false">https://blog.resiz.es/resizes-blog</guid><pubDate>Tue, 27 Feb 2024 00:00:00 GMT</pubDate><description>How to create and publish the best blog ever! 🔝 From Resizes, we are committed to creating the best blog for our users. That&#39;s why we were looking for a platform that would allow us to create a bl…</description><content:encoded>&lt;h2 id=&quot;how-to-create-and-publish-the-best-blog-ever-&quot; tabindex=&quot;-1&quot;&gt;How to create and publish the best blog ever! 🔝&lt;/h2&gt;
&lt;p&gt;From Resizes, we are committed to creating the best blog for our users. That&#39;s why we were looking for a platform that would allow us to create a blog with a modern design, easy to use, and with the best performance.&lt;/p&gt;
&lt;p&gt;We have chosen Docusaurus, a modern static website generator. It is optimized for technical documentation and has great capabilities for creating blogs. It is built using React and Markdown, which makes it easy to use and customize. We think is a robust way to manage and publish content, leveraging modern development tools and practices.&lt;/p&gt;
&lt;!--truncate--&gt;
&lt;h2 id=&quot;step-1-setting-up-your-docusaurus-blog&quot; tabindex=&quot;-1&quot;&gt;Step 1: Setting Up Your Docusaurus Blog&lt;/h2&gt;
&lt;h3 id=&quot;initialize-your-docusaurus-project&quot; tabindex=&quot;-1&quot;&gt;Initialize Your Docusaurus Project&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Install Node.js&lt;/strong&gt;: Ensure you have Node.js installed on your system.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Create a New Docusaurus Site&lt;/strong&gt;: Run the following command in your terminal:&lt;/li&gt;
&lt;/ol&gt;
&lt;pre tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;npx create-docusaurus@latest blog classic
&lt;/code&gt;&lt;/pre&gt;
&lt;ol start=&quot;3&quot;&gt;
&lt;li&gt;&lt;strong&gt;Navigate to Your Project Directory&lt;/strong&gt;:&lt;/li&gt;
&lt;/ol&gt;
&lt;pre tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;hljs-built_in&quot;&gt;cd&lt;/span&gt; blog
&lt;/code&gt;&lt;/pre&gt;
&lt;ol start=&quot;4&quot;&gt;
&lt;li&gt;&lt;strong&gt;Start Your Development Server&lt;/strong&gt;: Run &lt;code&gt;npx docusaurus start&lt;/code&gt;. This command starts a local development server and opens up a browser window.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;You have now a Docusaurus site running on your local machine.&lt;/p&gt;
&lt;aside class=&quot;blog-callout note&quot;&gt;&lt;p class=&quot;callout-title&quot;&gt;note&lt;/p&gt;
&lt;p&gt;You can find more information about Docusaurus in the &lt;a href=&quot;https://docusaurus.io/docs&quot;&gt;official documentation&lt;/a&gt;.&lt;/p&gt;
&lt;/aside&gt;
&lt;h3 id=&quot;customize-your-blog&quot; tabindex=&quot;-1&quot;&gt;Customize Your Blog&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Edit &lt;code&gt;docusaurus.config.js&lt;/code&gt; to customize your site&#39;s layout, theme, and functionalities.&lt;/li&gt;
&lt;li&gt;Add blog posts by creating markdown files in the &lt;code&gt;/blog&lt;/code&gt; directory.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;step-2-deploying-your-blog-with-github-actions&quot; tabindex=&quot;-1&quot;&gt;Step 2: Deploying Your Blog with GitHub Actions&lt;/h2&gt;
&lt;h3 id=&quot;set-up-github-actions&quot; tabindex=&quot;-1&quot;&gt;Set Up GitHub Actions&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;In your GitHub repository, navigate to the &lt;strong&gt;Actions&lt;/strong&gt; tab and create a new workflow.&lt;/li&gt;
&lt;li&gt;Use the following template for your &lt;code&gt;.github/workflows/deployment.yml&lt;/code&gt;:&lt;/li&gt;
&lt;/ol&gt;
&lt;pre tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;&lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;Deploy&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;to&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;GitHub&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;Pages&lt;/span&gt;

&lt;span class=&quot;hljs-attr&quot;&gt;on:&lt;/span&gt;
  &lt;span class=&quot;hljs-attr&quot;&gt;push:&lt;/span&gt;
    &lt;span class=&quot;hljs-attr&quot;&gt;branches:&lt;/span&gt;
      &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;main&lt;/span&gt;

&lt;span class=&quot;hljs-attr&quot;&gt;permissions:&lt;/span&gt;
  &lt;span class=&quot;hljs-attr&quot;&gt;contents:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;read&lt;/span&gt;
  &lt;span class=&quot;hljs-attr&quot;&gt;pages:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;write&lt;/span&gt;
  &lt;span class=&quot;hljs-attr&quot;&gt;id-token:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;write&lt;/span&gt;

&lt;span class=&quot;hljs-attr&quot;&gt;jobs:&lt;/span&gt;
  &lt;span class=&quot;hljs-attr&quot;&gt;deploy:&lt;/span&gt;
    &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;Deploy&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;to&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;GitHub&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;Pages&lt;/span&gt;
    &lt;span class=&quot;hljs-attr&quot;&gt;runs-on:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;ubuntu-latest&lt;/span&gt;
    &lt;span class=&quot;hljs-attr&quot;&gt;environment:&lt;/span&gt;
      &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;github-pages&lt;/span&gt;
    &lt;span class=&quot;hljs-attr&quot;&gt;steps:&lt;/span&gt;
      &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;uses:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;actions/checkout@v4&lt;/span&gt;
      &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;uses:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;actions/setup-node@v4&lt;/span&gt;
        &lt;span class=&quot;hljs-attr&quot;&gt;with:&lt;/span&gt;
          &lt;span class=&quot;hljs-attr&quot;&gt;node-version:&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;18&lt;/span&gt;
          &lt;span class=&quot;hljs-attr&quot;&gt;cache:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;npm&lt;/span&gt;

      &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;Install&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;dependencies&lt;/span&gt;
        &lt;span class=&quot;hljs-attr&quot;&gt;run:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;npm&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;ci&lt;/span&gt;
      &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;Build&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;website&lt;/span&gt;
        &lt;span class=&quot;hljs-attr&quot;&gt;run:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;npm&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;run&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;build&lt;/span&gt;
      
      &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;Set&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;build&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;folder&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;artifact&lt;/span&gt;
        &lt;span class=&quot;hljs-attr&quot;&gt;uses:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;actions/upload-pages-artifact@v3&lt;/span&gt;
        &lt;span class=&quot;hljs-attr&quot;&gt;with:&lt;/span&gt;
          &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;github-pages&lt;/span&gt;
          &lt;span class=&quot;hljs-attr&quot;&gt;path:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;./build&lt;/span&gt;
      
      &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;uses:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;actions/deploy-pages@v4&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;ol start=&quot;3&quot;&gt;
&lt;li&gt;This workflow automatically builds and deploys your site to GitHub Pages whenever you push to the main branch.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&quot;step-3-configuring-a-custom-domain-with-amazon-route-53&quot; tabindex=&quot;-1&quot;&gt;Step 3: Configuring a Custom Domain with Amazon Route 53&lt;/h2&gt;
&lt;h3 id=&quot;register-your-domain&quot; tabindex=&quot;-1&quot;&gt;Register Your Domain&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;Go to the Amazon Route 53 console and register a new domain if you don&#39;t already have one.&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id=&quot;configure-dns-settings&quot; tabindex=&quot;-1&quot;&gt;Configure DNS Settings&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;After your domain is registered, navigate to the &lt;strong&gt;Hosted zones&lt;/strong&gt; in Route 53.&lt;/li&gt;
&lt;li&gt;Create a new record set for your domain:
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Name&lt;/strong&gt;: Your domain name&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Type&lt;/strong&gt;: A - IPv4 address&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Alias&lt;/strong&gt;: Yes&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Alias Target&lt;/strong&gt;: Your GitHub Pages URL&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Add a CNAME record if you are using a subdomain instead:
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Name&lt;/strong&gt;: blog&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Type&lt;/strong&gt;: CNAME&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Value&lt;/strong&gt;: Your GitHub Pages URL, e.g. &lt;code&gt;yourusername.github.io&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id=&quot;update-your-docusaurus-configuration&quot; tabindex=&quot;-1&quot;&gt;Update Your Docusaurus Configuration&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;In your &lt;code&gt;docusaurus.config.js&lt;/code&gt;, update the &lt;code&gt;url&lt;/code&gt; and &lt;code&gt;baseUrl&lt;/code&gt; fields with your custom domain.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&quot;step-4-enjoy-your-new-blog&quot; tabindex=&quot;-1&quot;&gt;Step 4: Enjoy Your New Blog!&lt;/h2&gt;
&lt;p&gt;You can now start customizing your blog. Adding blog posts, customizing the theme, and creating a great user experience for your readers. We hope you enjoy your new blog and find it useful for your projects.&lt;/p&gt;
&lt;h2 id=&quot;step-5-share-your-blog-with-the-world&quot; tabindex=&quot;-1&quot;&gt;Step 5: Share Your Blog with the World&lt;/h2&gt;
&lt;p&gt;We are very proud to write the meta blog post and share it inside our blog. Welcome to the Resizes Blog! 🚀&lt;/p&gt;
&lt;p&gt;If you find any issue or you want to contribute to our blog or even if you would like to copy our blog, feel free to do it! We are happy to share our knowledge with the community.&lt;/p&gt;
&lt;p&gt;Don&#39;t be shy and open a pull request in our &lt;a href=&quot;https://github.com/resizes/blog&quot;&gt;GitHub repository&lt;/a&gt;! 📝&lt;/p&gt;
&lt;p&gt;Here, we will share our thoughts, ideas, and experiences on a variety of topics, including platform engineering, DevOps, Cloud Native trends, tips and tricks about different technologies and tools and many more!&lt;/p&gt;
&lt;p&gt;Stay tuned for more content and updates. We hope you enjoy reading our blog as much as we enjoy writing it. 📚&lt;/p&gt;
</content:encoded></item><item><title>Kubernetes Most Used Commands</title><link>https://resiz.es/blog/kubernetes-commands</link><guid isPermaLink="false">https://blog.resiz.es/kubernetes-commands</guid><pubDate>Wed, 21 Feb 2024 00:00:00 GMT</pubDate><description>Kubernetes is an open-source container orchestration platform that automates the deployment, scaling, and management of containerized applications. It is widely used by many organizations to manage…</description><content:encoded>&lt;p&gt;Kubernetes is an open-source container orchestration platform that automates the deployment, scaling, and management of containerized applications. It is widely used by many organizations to manage their containerized applications and services. Kubernetes provides a rich set of commands that allow developers and operators to interact with the Kubernetes cluster and manage their applications and services. In this blog post, we will explore some of the most used Kubernetes commands that can help you streamline your Kubernetes deployments and efficiently manage your applications.&lt;/p&gt;
&lt;!--truncate--&gt;
&lt;h2 id=&quot;esential-commands-for-developers&quot; tabindex=&quot;-1&quot;&gt;Esential Commands for Developers&lt;/h2&gt;
&lt;h3 id=&quot;get-information&quot; tabindex=&quot;-1&quot;&gt;Get Information&lt;/h3&gt;
&lt;p&gt;Kubernetes provides a set of commands to get information about the resources running in the cluster. You can use these commands to get information about pods, services, deployments, and other resources.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;kubectl version &lt;span class=&quot;hljs-comment&quot;&gt;# Get the Kubernetes version&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;pre tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;kubectl cluster-info &lt;span class=&quot;hljs-comment&quot;&gt;# Display cluster info&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;pre tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;kubectl config view --minify --output &lt;span class=&quot;hljs-string&quot;&gt;&#39;jsonpath={..user}&#39;&lt;/span&gt; &lt;span class=&quot;hljs-comment&quot;&gt;# Get the current user&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;aside class=&quot;blog-callout tip&quot;&gt;&lt;p class=&quot;callout-title&quot;&gt;tip&lt;/p&gt;
&lt;p&gt;Try with &lt;code&gt;context&lt;/code&gt; and &lt;code&gt;cluster&lt;/code&gt; to get more information about the current context and cluster.&lt;/p&gt;
&lt;/aside&gt;
&lt;h3 id=&quot;gather-resources&quot; tabindex=&quot;-1&quot;&gt;Gather Resources&lt;/h3&gt;
&lt;p&gt;Kubernetes allows you to gather resources from the cluster. You can use these commands to get resources such as pods, services, deployments, and other resources.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;kubectl get pods &lt;span class=&quot;hljs-comment&quot;&gt;# List all pods&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;pre tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;kubectl get services &lt;span class=&quot;hljs-comment&quot;&gt;# List all services&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;pre tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;kubectl get deployments &lt;span class=&quot;hljs-comment&quot;&gt;# List all deployments&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;pre tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;kubectl get nodes &lt;span class=&quot;hljs-comment&quot;&gt;# List all nodes&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;pre tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;kubectl get namespaces &lt;span class=&quot;hljs-comment&quot;&gt;# List all namespaces&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;aside class=&quot;blog-callout tip&quot;&gt;&lt;p class=&quot;callout-title&quot;&gt;tip&lt;/p&gt;
&lt;p&gt;Try with other resources such as &lt;code&gt;configmaps&lt;/code&gt;, &lt;code&gt;secrets&lt;/code&gt;, &lt;code&gt;ingresses&lt;/code&gt;, &lt;code&gt;replicasets&lt;/code&gt;, &lt;code&gt;statefulsets&lt;/code&gt;, &lt;code&gt;daemonsets&lt;/code&gt;, &lt;code&gt;persistentvolumeclaims&lt;/code&gt;, &lt;code&gt;hpa&lt;/code&gt;, &lt;code&gt;jobs&lt;/code&gt;, &lt;code&gt;crd&lt;/code&gt;, etc.&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class=&quot;blog-callout tip&quot;&gt;&lt;p class=&quot;callout-title&quot;&gt;tip&lt;/p&gt;
&lt;p&gt;Use &lt;code&gt;kubectl get all&lt;/code&gt; to get all resources in the cluster.&lt;/p&gt;
&lt;/aside&gt;
&lt;h3 id=&quot;use-flags-to-filter&quot; tabindex=&quot;-1&quot;&gt;Use Flags to Filter&lt;/h3&gt;
&lt;p&gt;Kubernetes allows you to use flags to filter the resources. You can use these flags to filter the resources based on labels, fields, and other criteria.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;kubectl get pods -w -o wide -A --show-labels &lt;span class=&quot;hljs-comment&quot;&gt;# Watch all pods with wide output and labels&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;aside class=&quot;blog-callout tip&quot;&gt;&lt;p class=&quot;callout-title&quot;&gt;tip&lt;/p&gt;
&lt;p&gt;Use those flags wisely!&lt;/p&gt;
&lt;p&gt;&lt;code&gt;-w&lt;/code&gt; to watch for changes, &lt;code&gt;-o wide&lt;/code&gt; to get more information, &lt;code&gt;-A&lt;/code&gt; to get all resources, &lt;code&gt;--show-labels&lt;/code&gt; to show labels.&lt;/p&gt;
&lt;/aside&gt;
&lt;h3 id=&quot;debugging&quot; tabindex=&quot;-1&quot;&gt;Debugging&lt;/h3&gt;
&lt;p&gt;Kubernetes provides a set of commands to debug the resources running in the cluster. You can use these commands to debug pods, services, deployments, and other resources.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;kubectl describe pod &amp;lt;pod-name&amp;gt; &lt;span class=&quot;hljs-comment&quot;&gt;# Describe a pod&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;pre tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;kubectl logs &amp;lt;pod-name&amp;gt; &lt;span class=&quot;hljs-comment&quot;&gt;# Get logs from a pod&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;aside class=&quot;blog-callout tip&quot;&gt;&lt;p class=&quot;callout-title&quot;&gt;tip&lt;/p&gt;
&lt;p&gt;If you would like to follow the logs, use &lt;code&gt;-f&lt;/code&gt; flag.&lt;/p&gt;
&lt;/aside&gt;
&lt;h3 id=&quot;imperative-commands&quot; tabindex=&quot;-1&quot;&gt;Imperative Commands&lt;/h3&gt;
&lt;p&gt;Kubernetes allows you to run imperative commands to manage resources. You can use these commands to create, delete, and update resources.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;kubectl create deployment &amp;lt;name&amp;gt; --image=&amp;lt;image&amp;gt; &lt;span class=&quot;hljs-comment&quot;&gt;# Create a deployment&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;pre tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;kubectl expose deployment &amp;lt;name&amp;gt; --port=&amp;lt;port&amp;gt; --target-port=&amp;lt;target-port&amp;gt; --&lt;span class=&quot;hljs-built_in&quot;&gt;type&lt;/span&gt;=NodePort &lt;span class=&quot;hljs-comment&quot;&gt;# Expose a deployment&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;pre tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;kubectl scale deployment &amp;lt;name&amp;gt; --replicas=&amp;lt;replicas&amp;gt; &lt;span class=&quot;hljs-comment&quot;&gt;# Scale a deployment&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;pre tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;kubectl create secret generic &amp;lt;name&amp;gt; --from-literal=&amp;lt;key&amp;gt;=&amp;lt;value
&lt;/code&gt;&lt;/pre&gt;
&lt;aside class=&quot;blog-callout tip&quot;&gt;&lt;p class=&quot;callout-title&quot;&gt;tip&lt;/p&gt;
&lt;p&gt;Use &lt;code&gt;--dry-run=client&lt;/code&gt; and &lt;code&gt;-o yaml&lt;/code&gt; flags to generate the resource manifest.&lt;/p&gt;
&lt;/aside&gt;
&lt;h3 id=&quot;troubleshooting&quot; tabindex=&quot;-1&quot;&gt;Troubleshooting&lt;/h3&gt;
&lt;p&gt;Kubernetes provides a set of commands to troubleshoot the resources running in the cluster. You can use these commands to troubleshoot pods, services, deployments, and other resources.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;kubectl run &amp;lt;name&amp;gt; --image=&amp;lt;image&amp;gt; --restart=Never --&lt;span class=&quot;hljs-built_in&quot;&gt;rm&lt;/span&gt; -it -- sh &lt;span class=&quot;hljs-comment&quot;&gt;# Run a pod for troubleshooting&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;pre tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;kubectl &lt;span class=&quot;hljs-built_in&quot;&gt;exec&lt;/span&gt; -it &amp;lt;pod-name&amp;gt; -- sh &lt;span class=&quot;hljs-comment&quot;&gt;# Execute a command in a pod&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;aside class=&quot;blog-callout tip&quot;&gt;&lt;p class=&quot;callout-title&quot;&gt;tip&lt;/p&gt;
&lt;p&gt;You are now inside the pod, use the shell to run commands and troubleshoot.&lt;/p&gt;
&lt;/aside&gt;
&lt;h3 id=&quot;scale--update&quot; tabindex=&quot;-1&quot;&gt;Scale &amp;amp; Update&lt;/h3&gt;
&lt;p&gt;Kubernetes allows you to scale and update resources. You can use these commands to scale and update deployments, replicasets, and other resources.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;kubectl scale deployment &amp;lt;name&amp;gt; --replicas=&amp;lt;replicas&amp;gt; &lt;span class=&quot;hljs-comment&quot;&gt;# Scale a deployment&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;pre tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;kubectl &lt;span class=&quot;hljs-built_in&quot;&gt;set&lt;/span&gt; image deployment/&amp;lt;name&amp;gt; &amp;lt;container-name&amp;gt;=&amp;lt;new-image&amp;gt; &lt;span class=&quot;hljs-comment&quot;&gt;# Update a deployment&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;pre tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;kubectl rollout &lt;span class=&quot;hljs-built_in&quot;&gt;history&lt;/span&gt; deployment/&amp;lt;name&amp;gt; &lt;span class=&quot;hljs-comment&quot;&gt;# Get rollout history&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;pre tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;kubectl rollout undo deployment/&amp;lt;name&amp;gt; &lt;span class=&quot;hljs-comment&quot;&gt;# Undo a rollout&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;pre tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;kubectl rollout status deployment/&amp;lt;name&amp;gt; &lt;span class=&quot;hljs-comment&quot;&gt;# Get rollout status&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;pre tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;kubectl rollout restart deployment/&amp;lt;name&amp;gt; &lt;span class=&quot;hljs-comment&quot;&gt;# Restart a rollout&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;modify-resources&quot; tabindex=&quot;-1&quot;&gt;Modify Resources&lt;/h3&gt;
&lt;p&gt;Kubernetes allows you to modify resources. You can use these commands to modify resources such as pods, services, deployments, and other resources.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;kubectl edit pod &amp;lt;pod-name&amp;gt; &lt;span class=&quot;hljs-comment&quot;&gt;# Edit a pod&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;pre tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;kubectl apply -f &amp;lt;file&amp;gt; &lt;span class=&quot;hljs-comment&quot;&gt;# Apply a configuration file&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;pre tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;kubectl replace -f &amp;lt;file&amp;gt; &lt;span class=&quot;hljs-comment&quot;&gt;# Replace a configuration file&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;pre tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;kubectl delete -f &amp;lt;file&amp;gt; &lt;span class=&quot;hljs-comment&quot;&gt;# Delete a configuration file&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;pre tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;kubectl patch &amp;lt;resource&amp;gt; &amp;lt;name&amp;gt; -p &amp;lt;patch&amp;gt; &lt;span class=&quot;hljs-comment&quot;&gt;# Patch a resource&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;monitoring&quot; tabindex=&quot;-1&quot;&gt;Monitoring&lt;/h3&gt;
&lt;p&gt;Kubernetes provides a set of commands to monitor the resources running in the cluster. You can use these commands to monitor pods, services, deployments, and other resources.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;kubectl top nodes &lt;span class=&quot;hljs-comment&quot;&gt;# Show the top nodes&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;pre tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;kubectl top pods &lt;span class=&quot;hljs-comment&quot;&gt;# Show the top pods&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;aside class=&quot;blog-callout warning&quot;&gt;&lt;p class=&quot;callout-title&quot;&gt;warning&lt;/p&gt;
&lt;p&gt;You need to have the &lt;code&gt;metrics-server&lt;/code&gt; installed in your cluster to use these commands. Follow the &lt;a href=&quot;https://github.com/kubernetes-sigs/metrics-server&quot;&gt;official documentation&lt;/a&gt; to install the &lt;code&gt;metrics-server&lt;/code&gt;.&lt;/p&gt;
&lt;/aside&gt;
&lt;h3 id=&quot;connect-to-apps&quot; tabindex=&quot;-1&quot;&gt;Connect to Apps&lt;/h3&gt;
&lt;p&gt;Kubernetes allows you to connect to applications running in the cluster. You can use these commands to connect to pods, services, deployments, and other resources.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;kubectl port-forward &amp;lt;pod-name&amp;gt; &amp;lt;local-port&amp;gt;:&amp;lt;remote-port&amp;gt; &lt;span class=&quot;hljs-comment&quot;&gt;# Forward a port&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;pre tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;kubectl port-forward service/&amp;lt;service-name&amp;gt; &amp;lt;local-port&amp;gt;:&amp;lt;remote-port&amp;gt; &lt;span class=&quot;hljs-comment&quot;&gt;# Forward a port for a service&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;aside class=&quot;blog-callout tip&quot;&gt;&lt;p class=&quot;callout-title&quot;&gt;tip&lt;/p&gt;
&lt;p&gt;Open in your browser &lt;code&gt;http://localhost:&amp;lt;local-port&amp;gt;&lt;/code&gt; to play with your application.&lt;/p&gt;
&lt;/aside&gt;
&lt;h3 id=&quot;other-commands&quot; tabindex=&quot;-1&quot;&gt;Other Commands&lt;/h3&gt;
&lt;p&gt;Useful commands to manage your Kubernetes cluster and resources.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;kubectl get secret admin-secret -o jsonpath=&lt;span class=&quot;hljs-string&quot;&gt;&quot;{.data.password}&quot;&lt;/span&gt; | &lt;span class=&quot;hljs-built_in&quot;&gt;base64&lt;/span&gt; --decode &lt;span class=&quot;hljs-comment&quot;&gt;# Get a secret&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;pre tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;kubectl api-resources &lt;span class=&quot;hljs-comment&quot;&gt;# List all resources&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;pre tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;kubectl explain &amp;lt;resource&amp;gt; &lt;span class=&quot;hljs-comment&quot;&gt;# Explain a resource&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;tools&quot; tabindex=&quot;-1&quot;&gt;Tools&lt;/h3&gt;
&lt;p&gt;A great list of tools to manage your Kubernetes cluster and resources.&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;kubens &lt;span class=&quot;hljs-comment&quot;&gt;# Switch between namespaces&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;pre tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;kubectx &lt;span class=&quot;hljs-comment&quot;&gt;# Switch between contexts&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;pre tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;k9s &lt;span class=&quot;hljs-comment&quot;&gt;# Terminal-based UI to interact with your Kubernetes cluster&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;pre tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;stern &lt;span class=&quot;hljs-comment&quot;&gt;# Multi pod and container log tailing&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
</content:encoded></item><item><title>Microservices Architecture</title><link>https://resiz.es/blog/microservices-architecture</link><guid isPermaLink="false">https://blog.resiz.es/microservices-architecture</guid><pubDate>Wed, 14 Feb 2024 00:00:00 GMT</pubDate><description>In today&#39;s dynamic digital environment, the adoption of microservices architectures alongside container technologies like Docker and Kubernetes is not just innovative; it&#39;s transformative. This app…</description><content:encoded>&lt;p&gt;In today&#39;s dynamic digital environment, the adoption of microservices architectures alongside container technologies like Docker and Kubernetes is not just innovative; it&#39;s transformative. This approach is revolutionizing how applications are developed, deployed, and scaled, offering unprecedented agility and efficiency. Here&#39;s a deeper dive into the myriad benefits of this synergy and why Docker and Kubernetes stand out as the cornerstone technologies in this paradigm shift.&lt;/p&gt;
&lt;!--truncate--&gt;
&lt;h2 id=&quot;deep-dive-into-the-benefits&quot; tabindex=&quot;-1&quot;&gt;Deep-Dive into the Benefits&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Unmatched Scalability: Microservices architecture allows parts of an application to be scaled up or down independently, catering to demand without wasting resources. This granular scalability ensures that applications can handle peak loads efficiently, improving user experience and resource management.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Accelerated Development and Deployment: Breaking down applications into smaller, self-contained services enables teams to adopt agile development practices. This means faster iterations, quicker feedback loops, and more rapid deployment of features, keeping businesses ahead in competitive markets.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Enhanced Resilience and Reliability: Microservices promote resilience. By isolating services, failures are contained to the affected service, minimizing downtime and impact on the entire application. This isolation also simplifies troubleshooting and recovery, ensuring high availability and reliability.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Streamlined Management and Maintenance: With applications divided into microservices, updates, and maintenance can be performed on individual services without disrupting the entire application. This leads to a more manageable and less risky update process, allowing for continuous improvement and innovation.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Improved Resource Utilization: Containers, orchestrated by Kubernetes, encapsulate microservices in isolated environments. This not only ensures consistency across development, testing, and production environments but also optimizes resource use, reducing costs and improving performance.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&quot;spotlight-on-docker-and-kubernetes&quot; tabindex=&quot;-1&quot;&gt;Spotlight on Docker and Kubernetes&lt;/h2&gt;
&lt;p&gt;Docker: Docker has become synonymous with containerization, offering a comprehensive platform to build, share, and run applications as lightweight containers. These containers package code and dependencies together, ensuring that applications run seamlessly in any environment. Docker&#39;s simplicity and efficiency in creating and managing containers make it indispensable for developers aiming to leverage the benefits of microservices.&lt;/p&gt;
&lt;p&gt;Kubernetes: Kubernetes, or K8s, is the de facto standard for orchestrating containerized applications. It automates the deployment, scaling, and management of applications housed in containers, enabling robust cluster management. Kubernetes&#39; ability to manage service discovery, load balancing, and self-healing adds layers of efficiency and reliability that are critical in microservices architectures.&lt;/p&gt;
&lt;h2 id=&quot;conclusion&quot; tabindex=&quot;-1&quot;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;At Resizes we think container and Kubernetes are like the operative system of the cloud. Almost everything is built around them.&lt;/p&gt;
&lt;p&gt;The combination of microservices with Docker and Kubernetes represents a powerful paradigm for modern software development. This approach not only enhances scalability and flexibility but also streamlines the development process, enabling organizations to respond more swiftly to market changes and customer needs. By adopting these technologies, developers and organizations can build more resilient, scalable, and efficient applications, ready to meet the demands of the future.&lt;/p&gt;
&lt;p&gt;In the journey towards embracing microservices and containerization, Docker and Kubernetes stand out not just as tools, but as catalysts for change, driving innovation and efficiency in software development. As we continue to explore and harness their full potential, the possibilities for creating more agile, scalable, and robust applications are limitless.&lt;/p&gt;
</content:encoded></item><item><title>Infrastructure as Code</title><link>https://resiz.es/blog/iac</link><guid isPermaLink="false">https://blog.resiz.es/iac</guid><pubDate>Wed, 31 Jan 2024 00:00:00 GMT</pubDate><description>The Backbone of Modern DevOps Infrastructure as Code (IaC) has revolutionized the way organizations manage and provision their IT infrastructure. Emerging from the needs of agile development and th…</description><content:encoded>&lt;h2 id=&quot;the-backbone-of-modern-devops&quot; tabindex=&quot;-1&quot;&gt;The Backbone of Modern DevOps&lt;/h2&gt;
&lt;p&gt;Infrastructure as Code (IaC) has revolutionized the way organizations manage and provision their IT infrastructure. Emerging from the needs of agile development and the rise of cloud computing, IaC stands as a pivotal element in the DevOps toolbox, automating the provisioning of servers, storage, and networking in a reliable and repeatable manner.&lt;/p&gt;
&lt;!--truncate--&gt;
&lt;h2 id=&quot;why-infrastructure-as-code&quot; tabindex=&quot;-1&quot;&gt;Why Infrastructure as Code?&lt;/h2&gt;
&lt;h3 id=&quot;consistency&quot; tabindex=&quot;-1&quot;&gt;Consistency&lt;/h3&gt;
&lt;p&gt;IaC allows you to provision infrastructure in a consistent manner. This means that you can provision infrastructure in the same way every time, ensuring that your infrastructure is always consistent and predictable. Uniformity across environments is essential to avoid configuration drift.&lt;/p&gt;
&lt;h3 id=&quot;speed&quot; tabindex=&quot;-1&quot;&gt;Speed&lt;/h3&gt;
&lt;p&gt;IaC&#39;s automated nature means infrastructure can be spun up in minutes, not days. This rapid deployment is key for businesses scaling up or requiring quick rollouts, like e-commerce platforms during high-traffic events.&lt;/p&gt;
&lt;h3 id=&quot;safety&quot; tabindex=&quot;-1&quot;&gt;Safety&lt;/h3&gt;
&lt;p&gt;Automating infrastructure setup reduces the risk of human error. IaC&#39;s use of version control ensures changes are trackable and reversible, leading to safer and more secure environments.&lt;/p&gt;
&lt;h3 id=&quot;cost&quot; tabindex=&quot;-1&quot;&gt;Cost&lt;/h3&gt;
&lt;p&gt;By automating the infrastructure, companies save on the labor costs associated with manual setup and maintenance. IaC also optimizes resource utilization, reducing overall expenses.&lt;/p&gt;
&lt;h2 id=&quot;infrastructure-as-code-tools&quot; tabindex=&quot;-1&quot;&gt;Infrastructure as Code Tools&lt;/h2&gt;
&lt;p&gt;Some of the most popular IaC tools include Terraform, Pulumi, AWS CloudFormation, and OpenTofu.&lt;/p&gt;
&lt;h3 id=&quot;terraform&quot; tabindex=&quot;-1&quot;&gt;Terraform&lt;/h3&gt;
&lt;p&gt;Terraform is an open-source infrastructure as code software tool that enables you to safely and predictably create, change, and improve infrastructure. Terraform can manage existing and popular service providers as well as custom in-house solutions.&lt;/p&gt;
&lt;h3 id=&quot;pulumi&quot; tabindex=&quot;-1&quot;&gt;Pulumi&lt;/h3&gt;
&lt;p&gt;Pulumi is unique in its support for mainstream programming languages like Python, JavaScript, and C#. This approach allows developers to use familiar syntax and tools for infrastructure management.&lt;/p&gt;
&lt;h3 id=&quot;aws-cloudformation&quot; tabindex=&quot;-1&quot;&gt;AWS CloudFormation&lt;/h3&gt;
&lt;p&gt;AWS CloudFormation, specifically designed for AWS services, offers seamless integration and management for AWS deployments. It uses JSON or YAML templates for resource description, catering to AWS-centric environments.&lt;/p&gt;
&lt;h3 id=&quot;opentofu&quot; tabindex=&quot;-1&quot;&gt;OpenTofu&lt;/h3&gt;
&lt;p&gt;OpenTofu is a lesser-known but emerging tool in the IaC space. It’s known for being a fork of Terraform. OpenTofu is also open-source, allowing for community contributions and improvements.&lt;/p&gt;
&lt;h2 id=&quot;overcoming-iac-challenges&quot; tabindex=&quot;-1&quot;&gt;Overcoming IaC Challenges&lt;/h2&gt;
&lt;p&gt;While IaC offers numerous benefits, it&#39;s not without challenges. Common issues include managing complex dependencies and maintaining state files in tools like Terraform. Best practices, such as modularizing code and using state backends, can mitigate these issues.&lt;/p&gt;
&lt;h2 id=&quot;terraform-a-getting-started-guide&quot; tabindex=&quot;-1&quot;&gt;Terraform: A Getting Started Guide&lt;/h2&gt;
&lt;h3 id=&quot;step-1-install-terraform&quot; tabindex=&quot;-1&quot;&gt;Step 1: Install Terraform&lt;/h3&gt;
&lt;p&gt;Terraform is available for download on Windows, Mac, and Linux. You can download the latest version of Terraform from the &lt;a href=&quot;https://www.terraform.io/downloads.html&quot;&gt;Terraform website&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Unzip and Install: Extract the downloaded file and install it. Ensure that the &lt;code&gt;terraform&lt;/code&gt; binary is available in your system&#39;s PATH.&lt;/p&gt;
&lt;h3 id=&quot;step-2-set-up-your-first-terraform-project&quot; tabindex=&quot;-1&quot;&gt;Step 2: Set Up Your First Terraform Project&lt;/h3&gt;
&lt;p&gt;Create a directory for your Terraform project. This directory will contain all the Terraform files for your project. Navigate to the directory:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;hljs-built_in&quot;&gt;mkdir&lt;/span&gt; my-terraform-project
&lt;span class=&quot;hljs-built_in&quot;&gt;cd&lt;/span&gt; my-terraform-project
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Create a file named &lt;code&gt;main.tf&lt;/code&gt;. This file will contain the Terraform code for your project. Open the file in your favorite text editor and add the following code:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-terraform&quot;&gt;provider &quot;aws&quot; {
  region = &quot;us-east-1&quot;
}

resource &quot;aws_instance&quot; &quot;example&quot; {
  ami           = &quot;ami-0c55b159cbfafe1f0&quot;
  instance_type = &quot;t2.micro&quot;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This code will create an AWS EC2 instance in the &lt;code&gt;us-east-1&lt;/code&gt; region. The instance will use the &lt;code&gt;ami-0c55b159cbfafe1f0&lt;/code&gt; AMI and will be of type &lt;code&gt;t2.micro&lt;/code&gt;.&lt;/p&gt;
&lt;h3 id=&quot;step-3-initialize-terraform&quot; tabindex=&quot;-1&quot;&gt;Step 3: Initialize Terraform&lt;/h3&gt;
&lt;p&gt;Initialize Terraform in your project directory:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;terraform init
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This command will download the AWS provider plugin and initialize your Terraform project.&lt;/p&gt;
&lt;h3 id=&quot;step-4-create-a-terraform-plan&quot; tabindex=&quot;-1&quot;&gt;Step 4: Create a Terraform Plan&lt;/h3&gt;
&lt;p&gt;Create a Terraform plan for your project:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;terraform plan
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This command will create an execution plan for your project. It will show you what Terraform will do when you apply your project. It will also show you any errors or warnings in your project.&lt;/p&gt;
&lt;h3 id=&quot;step-5-apply-your-terraform-project&quot; tabindex=&quot;-1&quot;&gt;Step 5: Apply Your Terraform Project&lt;/h3&gt;
&lt;p&gt;Apply your Terraform project:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;terraform apply
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This command will apply your Terraform project. It will create the AWS EC2 instance in the &lt;code&gt;us-east-1&lt;/code&gt; region. It will also create a state file for your project.&lt;/p&gt;
&lt;h3 id=&quot;step-6-destroy-your-terraform-project&quot; tabindex=&quot;-1&quot;&gt;Step 6: Destroy Your Terraform Project&lt;/h3&gt;
&lt;p&gt;Destroy your Terraform project:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;terraform destroy
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This command will destroy your Terraform project. It will delete the AWS EC2 instance in the &lt;code&gt;us-east-1&lt;/code&gt; region. It will also delete the state file for your project.&lt;/p&gt;
&lt;h2 id=&quot;terraform-a-best-practices-guide&quot; tabindex=&quot;-1&quot;&gt;Terraform: A Best Practices Guide&lt;/h2&gt;
&lt;h3 id=&quot;use-a-version-control-system&quot; tabindex=&quot;-1&quot;&gt;Use a Version Control System&lt;/h3&gt;
&lt;p&gt;Use a version control system like Git to manage your Terraform code. This will allow you to track changes to your code and revert to previous versions if needed.&lt;/p&gt;
&lt;h3 id=&quot;terraform-versions&quot; tabindex=&quot;-1&quot;&gt;Terraform Versions&lt;/h3&gt;
&lt;p&gt;Always be aware of the version of Terraform you are using, as syntax can change between versions.&lt;/p&gt;
&lt;h3 id=&quot;provider-documentation&quot; tabindex=&quot;-1&quot;&gt;Provider Documentation&lt;/h3&gt;
&lt;p&gt;Always refer to the provider documentation when writing Terraform code. This will ensure that you are using the correct syntax and that your code will work as expected.&lt;/p&gt;
&lt;h3 id=&quot;terraform-modules&quot; tabindex=&quot;-1&quot;&gt;Terraform Modules&lt;/h3&gt;
&lt;p&gt;Use Terraform modules to organize your code into reusable components. This will make your code more readable and maintainable.&lt;/p&gt;
&lt;h3 id=&quot;state-file-security&quot; tabindex=&quot;-1&quot;&gt;State File Security&lt;/h3&gt;
&lt;p&gt;Always keep your state file secure. This file contains sensitive information about your infrastructure, so it should not be accessible to anyone except you.&lt;/p&gt;
&lt;h2 id=&quot;future-trends-and-conclusion&quot; tabindex=&quot;-1&quot;&gt;Future Trends and Conclusion&lt;/h2&gt;
&lt;p&gt;IaC is continually evolving, with trends pointing towards more integration with AI and machine learning for predictive analysis and enhanced security measures. The future of IaC is not just automation, but intelligent automation.&lt;/p&gt;
&lt;p&gt;In summary, IaC is an indispensable part of modern IT infrastructure, pivotal for organizations aiming for efficiency, speed, and consistency. As technology evolves, so will the tools and practices of IaC, further embedding it into the fabric of DevOps and Platform Engineering.&lt;/p&gt;
</content:encoded></item><item><title>Helm Most Used Commands</title><link>https://resiz.es/blog/helm-commands</link><guid isPermaLink="false">https://blog.resiz.es/helm-commands</guid><pubDate>Mon, 29 Jan 2024 00:00:00 GMT</pubDate><description>Helm is a package manager for Kubernetes that allows developers and operators to more easily package, configure, and deploy applications and services onto Kubernetes clusters. Helm is the most popu…</description><content:encoded>&lt;p&gt;Helm is a package manager for Kubernetes that allows developers and operators to more easily package, configure, and deploy applications and services onto Kubernetes clusters. Helm is the most popular package manager for Kubernetes and is widely used by many organizations.&lt;/p&gt;
&lt;p&gt;Dive into the world of Helm commands - your gateway to simplified Kubernetes deployments and efficient package management. Uncover the power to streamline, deploy, and manage applications effortlessly. Ready to elevate your container orchestration game? 🚀📦&lt;/p&gt;
&lt;!--truncate--&gt;
&lt;h2 id=&quot;installation&quot; tabindex=&quot;-1&quot;&gt;Installation&lt;/h2&gt;
&lt;p&gt;Begin your Helm journey by installing the Helm client on your local machine. You can install Helm using the following command:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;brew install helm
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;app-install--uninstall&quot; tabindex=&quot;-1&quot;&gt;App Install &amp;amp; Uninstall&lt;/h2&gt;
&lt;p&gt;Helm allows you to install and uninstall applications on your Kubernetes cluster. You can install an application using these commands:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;helm create &amp;lt;name&amp;gt; &lt;span class=&quot;hljs-comment&quot;&gt;# Create a new default chart with the given name&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;pre tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;helm install &amp;lt;name&amp;gt; &amp;lt;chart&amp;gt; [--namespace &amp;lt;name&amp;gt;] [--values &amp;lt;file&amp;gt;] &lt;span class=&quot;hljs-comment&quot;&gt;# Install the chart with the given release name&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;pre tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;helm uninstall &amp;lt;name&amp;gt; &lt;span class=&quot;hljs-comment&quot;&gt;# Uninstall the given release name&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;get-information&quot; tabindex=&quot;-1&quot;&gt;Get Information&lt;/h2&gt;
&lt;p&gt;Helm allows you to get information about your applications and releases. You can get information using these commands:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;helm list [--all-namespaces] &lt;span class=&quot;hljs-comment&quot;&gt;# List releases&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;pre tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;helm status &amp;lt;release&amp;gt; &lt;span class=&quot;hljs-comment&quot;&gt;# Show the status of the named release&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;pre tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;helm &lt;span class=&quot;hljs-built_in&quot;&gt;history&lt;/span&gt; &amp;lt;release&amp;gt; &lt;span class=&quot;hljs-comment&quot;&gt;# Fetch release history&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;change-app-version&quot; tabindex=&quot;-1&quot;&gt;Change App Version&lt;/h2&gt;
&lt;p&gt;Helm allows you to change the version of your applications. You can change the version using these commands:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;helm upgrade &amp;lt;release&amp;gt; &amp;lt;chart&amp;gt; [--atomic &amp;lt;file&amp;gt;] [--version &amp;lt;version&amp;gt;] &lt;span class=&quot;hljs-comment&quot;&gt;# Upgrade the release to a new version of the chart&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;pre tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;helm rollback &amp;lt;release&amp;gt; &amp;lt;revision&amp;gt; &lt;span class=&quot;hljs-comment&quot;&gt;# Rollback to a previous revision&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;chart-management&quot; tabindex=&quot;-1&quot;&gt;Chart Management&lt;/h2&gt;
&lt;p&gt;Helm allows you to manage your charts. You can manage your charts using these commands:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;helm lint &amp;lt;chart&amp;gt; &lt;span class=&quot;hljs-comment&quot;&gt;# Lint the chart&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;pre tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;helm template &amp;lt;name&amp;gt; &amp;lt;directory&amp;gt; &lt;span class=&quot;hljs-comment&quot;&gt;# Render chart templates locally and display the output&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;pre tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;helm show values &amp;lt;chart&amp;gt; &lt;span class=&quot;hljs-comment&quot;&gt;# Show the values file of the given chart&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;pre tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;helm dependencies update &lt;span class=&quot;hljs-comment&quot;&gt;# Update the dependencies of the given chart&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;repo-management&quot; tabindex=&quot;-1&quot;&gt;Repo Management&lt;/h2&gt;
&lt;p&gt;Helm allows you to manage your repositories. You can manage your repositories using these commands:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;helm repo list &lt;span class=&quot;hljs-comment&quot;&gt;# List chart repositories&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;pre tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;helm repo add &amp;lt;name&amp;gt; &amp;lt;url&amp;gt; &lt;span class=&quot;hljs-comment&quot;&gt;# Add a chart repository&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;pre tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;helm repo remove &amp;lt;name&amp;gt; &lt;span class=&quot;hljs-comment&quot;&gt;# Remove a chart repository&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;pre tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;helm search repo &amp;lt;name&amp;gt; &lt;span class=&quot;hljs-comment&quot;&gt;# Search for a specific chart&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
</content:encoded></item><item><title>Enhancing Developer Experience 👩🏾‍💻</title><link>https://resiz.es/blog/devex</link><guid isPermaLink="false">https://blog.resiz.es/devex</guid><pubDate>Tue, 23 Jan 2024 00:00:00 GMT</pubDate><description>As a platform engineer, the primary goal is to streamline and optimize the developer experience. In a world where technology is ever-evolving, it&#39;s crucial that we provide developers with tools and…</description><content:encoded>&lt;p&gt;As a platform engineer, the primary goal is to streamline and optimize the developer experience. In a world where technology is ever-evolving, it&#39;s crucial that we provide developers with tools and environments that not only simplify their workflows but also inspire innovation.&lt;/p&gt;
&lt;h3 id=&quot;why-focus-on-developer-experience-&quot; tabindex=&quot;-1&quot;&gt;Why Focus on Developer Experience? 🤩&lt;/h3&gt;
&lt;!--truncate--&gt;
&lt;p&gt;💪🏼 &lt;strong&gt;Productivity&lt;/strong&gt;: By automating repetitive tasks and reducing setup times, we enable developers to focus more on creative problem-solving rather than getting bogged down by repetitive tasks.&lt;/p&gt;
&lt;p&gt;🆕 &lt;strong&gt;Innovation&lt;/strong&gt;: A good developer experience fosters an environment where innovation is not just encouraged but facilitated. This means having the freedom to experiment without the fear of disrupting existing systems.&lt;/p&gt;
&lt;p&gt;👯 &lt;strong&gt;Collaboration&lt;/strong&gt;: Effective platform engineering promotes a culture of collaboration. By providing unified tools and processes, we ensure that teams can work seamlessly across different parts of a project.&lt;/p&gt;
&lt;h3 id=&quot;resizes-approach-to-enhancing-developer-experience-&quot; tabindex=&quot;-1&quot;&gt;Resizes Approach to Enhancing Developer Experience 😍&lt;/h3&gt;
&lt;p&gt;🚚 &lt;strong&gt;Streamlined Environments&lt;/strong&gt;: We’ve invested in creating standardized development environments that can be easily spun up. This ensures that every developer works in a consistent, well-understood environment, reducing the &quot;it works on my machine&quot; syndrome.&lt;/p&gt;
&lt;p&gt;🎮 &lt;strong&gt;Self-Service Infrastructure&lt;/strong&gt;: Implementing infrastructure as code and self-service portals, Resizes empower developers to provision what they need, when they need it, without delays.&lt;/p&gt;
&lt;p&gt;🏁 &lt;strong&gt;Continuous Integration and Continuous Deployment (CI/CD)&lt;/strong&gt;: Our robust CI/CD pipelines automate testing and deployment, allowing developers to integrate and deliver features faster and more reliably.&lt;/p&gt;
&lt;p&gt;🖥️ &lt;strong&gt;Monitoring and Feedback Loops&lt;/strong&gt;: Real-time monitoring tools provide immediate feedback to developers, allowing them to understand the impact of their changes in a production-like environment.&lt;/p&gt;
&lt;h3 id=&quot;looking-ahead-&quot; tabindex=&quot;-1&quot;&gt;Looking Ahead 🔮&lt;/h3&gt;
&lt;p&gt;As we continue to evolve our platform engineering strategies, our focus remains steadfast on enhancing the developer experience. Resizes is committed to exploring new technologies and methodologies that further this goal.&lt;/p&gt;
&lt;p&gt;We are excited about the future of platform engineering and its impact on developer productivity and innovation. Let&#39;s continue to build tools and processes that not only meet but exceed the needs of our developers.&lt;/p&gt;
</content:encoded></item><item><title>High Level Technology Stack</title><link>https://resiz.es/blog/high-level-technology-stack</link><guid isPermaLink="false">https://blog.resiz.es/high-level-technology-stack</guid><pubDate>Thu, 18 Jan 2024 00:00:00 GMT</pubDate><description>High Level Technology Stack At Resizes, we&#39;re pioneering the future of DevOps and Platform Engineering with cutting-edge Cloud Native technologies. Our mission is to empower you with DevOps experti…</description><content:encoded>&lt;h2 id=&quot;high-level-technology-stack&quot; tabindex=&quot;-1&quot;&gt;High Level Technology Stack&lt;/h2&gt;
&lt;p&gt;At Resizes, we&#39;re pioneering the future of DevOps and Platform Engineering with cutting-edge Cloud Native technologies. Our mission is to empower you with DevOps expertise, crafting a top-tier Internal Developer Platform (IDP) essential for your success. Our approach uniquely combines open-source and proprietary tools, tailoring a platform that perfectly aligns with your business needs.&lt;/p&gt;
&lt;p&gt;In this article, we&#39;ll explore our high-level technology stack, highlighting the most important tools and services we use to build your IDP.&lt;/p&gt;
&lt;!--truncate--&gt;
&lt;h2 id=&quot;version-control-system&quot; tabindex=&quot;-1&quot;&gt;Version Control System&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;The Heart of Software Development&lt;/strong&gt;: A Version Control System (VCS) is where the magic of code comes to life. Utilizing Git, the world&#39;s leading distributed VCS, we enable rapid branching and merging, ideal for large-scale projects. With its dominance in the industry, evidenced by over 100 million repositories on GitHub, Git is the cornerstone of our VCS strategy.&lt;/p&gt;
&lt;h3 id=&quot;git&quot; tabindex=&quot;-1&quot;&gt;Git&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://git-scm.com/&quot;&gt;Git&lt;/a&gt; stands out as a free, open-source distributed VCS, renowned for handling projects of all sizes with remarkable speed and efficiency. Its user-friendly nature, minimal footprint, and superior performance outshine traditional SCM tools like Subversion or CVS, offering features like inexpensive local branching and convenient staging areas.&lt;/p&gt;
&lt;h3 id=&quot;github&quot; tabindex=&quot;-1&quot;&gt;GitHub&lt;/h3&gt;
&lt;p&gt;Our choice for Git cloud hosting is &lt;a href=&quot;https://github.com/&quot;&gt;GitHub&lt;/a&gt;, a platform that revolutionizes the way we work. From open source to business projects, GitHub is the hub for code hosting, project management, and collaborative software development with millions of developers worldwide. At Resizes, GitHub is our collaborative canvas, enabling code sharing, issue tracking, and seamless pull request management.&lt;/p&gt;
&lt;aside class=&quot;blog-callout note&quot;&gt;&lt;p class=&quot;callout-title&quot;&gt;note&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Open to Alternatives&lt;/strong&gt;: While GitHub is our primary choice, we&#39;re flexible with &lt;a href=&quot;https://gitlab.com/&quot;&gt;GitLab&lt;/a&gt;, &lt;a href=&quot;https://bitbucket.org/&quot;&gt;Bitbucket&lt;/a&gt;, or any Git-based VCS, and can integrate with your existing VCS setup.&lt;/p&gt;
&lt;/aside&gt;
&lt;h2 id=&quot;public-cloud&quot; tabindex=&quot;-1&quot;&gt;Public Cloud&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Hosting with the Best&lt;/strong&gt;: Resizes leverages public cloud services for our infrastructure needs. This approach provides scalable, internet-accessible computing resources.&lt;/p&gt;
&lt;h3 id=&quot;amazon-web-services&quot; tabindex=&quot;-1&quot;&gt;Amazon Web Services&lt;/h3&gt;
&lt;p&gt;Our primary hosting service is &lt;a href=&quot;https://aws.amazon.com/&quot;&gt;AWS&lt;/a&gt;, a leader in on-demand cloud computing platforms and APIs. AWS&#39;s global reach, offering over 175 comprehensive services, makes it our choice for robust and scalable cloud infrastructure.&lt;/p&gt;
&lt;aside class=&quot;blog-callout note&quot;&gt;&lt;p class=&quot;callout-title&quot;&gt;note&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Flexible Cloud Solutions&lt;/strong&gt;: We&#39;re also equipped to work with other public cloud providers like &lt;a href=&quot;https://cloud.google.com/&quot;&gt;Google Cloud Platform&lt;/a&gt; or &lt;a href=&quot;https://azure.microsoft.com/&quot;&gt;Microsoft Azure&lt;/a&gt;, adapting to your preferred infrastructure.&lt;/p&gt;
&lt;/aside&gt;
&lt;h2 id=&quot;infrastructure-as-code&quot; tabindex=&quot;-1&quot;&gt;Infrastructure as Code&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Automated and Efficient&lt;/strong&gt;: Infrastructure as Code (IaC) is our methodology for managing and provisioning cloud resources via machine-readable definition files. This modern approach replaces traditional physical hardware configuration, emphasizing declarative formats.&lt;/p&gt;
&lt;h3 id=&quot;terraform&quot; tabindex=&quot;-1&quot;&gt;Terraform&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://www.terraform.io/&quot;&gt;Terraform&lt;/a&gt; is our go-to tool for IaC, allowing us to safely and predictably manage cloud infrastructure. This open-source tool excels in creating, changing, and versioning infrastructure efficiently, supporting a wide range of service providers and custom solutions.&lt;/p&gt;
&lt;aside class=&quot;blog-callout note&quot;&gt;&lt;p class=&quot;callout-title&quot;&gt;note&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Studying Alternatives&lt;/strong&gt;: While Terraform is our primary choice, we&#39;re currently considering &lt;a href=&quot;https://opentofu.org/&quot;&gt;OpenTofu&lt;/a&gt; as a potential alternative, following its recent release.&lt;/p&gt;
&lt;/aside&gt;
&lt;h2 id=&quot;container-orchestration&quot; tabindex=&quot;-1&quot;&gt;Container Orchestration&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Streamlining Application Deployment&lt;/strong&gt;: Containers provide a lightweight, portable solution for packaging applications and their dependencies. Our container orchestration process manages their lifecycle, encompassing provisioning, deployment, scaling, and monitoring.&lt;/p&gt;
&lt;h3 id=&quot;docker&quot; tabindex=&quot;-1&quot;&gt;Docker&lt;/h3&gt;
&lt;p&gt;We use &lt;a href=&quot;https://www.docker.com/&quot;&gt;Docker&lt;/a&gt; to encapsulate our applications and dependencies, ensuring consistent and repeatable deployments. Docker simplifies the process of creating, deploying, and running applications with its container technology.&lt;/p&gt;
&lt;h3 id=&quot;kubernetes&quot; tabindex=&quot;-1&quot;&gt;Kubernetes&lt;/h3&gt;
&lt;p&gt;For orchestration, we rely on &lt;a href=&quot;https://kubernetes.io/&quot;&gt;Kubernetes&lt;/a&gt;, an open-source system that automates the deployment, scaling, and management of containerized applications. Its ability to group containers into logical units eases management and discovery, building on Google&#39;s 15 years of production workload experience.&lt;/p&gt;
&lt;h3 id=&quot;helm&quot; tabindex=&quot;-1&quot;&gt;Helm&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://helm.sh/&quot;&gt;Helm&lt;/a&gt; enhances our Kubernetes application management. It&#39;s akin to a package manager for Kubernetes, streamlining the installation and management of applications. Helm Charts provide a simple yet powerful way to define, install, and upgrade even the most complex Kubernetes applications.&lt;/p&gt;
&lt;h2 id=&quot;continuous-integration-and-delivery&quot; tabindex=&quot;-1&quot;&gt;Continuous Integration and Delivery&lt;/h2&gt;
&lt;p&gt;Seamless Software Lifecycle Management: Continuous Integration (CI) and Continuous Delivery (CD) are pivotal in our workflow. CI automates code build and testing with each version control commit, promoting frequent code integration. CD automates software deployment, making releases predictable and repeatable.&lt;/p&gt;
&lt;h3 id=&quot;github-actions&quot; tabindex=&quot;-1&quot;&gt;GitHub Actions&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://docs.github.com/en/actions&quot;&gt;GitHub Actions&lt;/a&gt; is our tool of choice for automating both CI and CD processes. This platform facilitates software workflows, enabling us to build, test, and deploy code directly from GitHub, streamlining branch management and code reviews.&lt;/p&gt;
&lt;aside class=&quot;blog-callout note&quot;&gt;&lt;p class=&quot;callout-title&quot;&gt;note&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Adaptable CI/CD Tools&lt;/strong&gt;: We&#39;re also equipped to work with other CI/CD tools like &lt;a href=&quot;https://www.jenkins.io/&quot;&gt;Jenkins&lt;/a&gt; or &lt;a href=&quot;https://docs.gitlab.com/ee/ci/&quot;&gt;GitLab CI&lt;/a&gt;, tailoring our approach to your existing setup.&lt;/p&gt;
&lt;/aside&gt;
&lt;h3 id=&quot;gitops-and-argocd&quot; tabindex=&quot;-1&quot;&gt;GitOps and ArgoCD&lt;/h3&gt;
&lt;p&gt;GitOps, using Git as a single source of truth for declarative infrastructure and applications, guides our CD practices. &lt;a href=&quot;https://argo-cd.readthedocs.io/en/stable/&quot;&gt;ArgoCD&lt;/a&gt;, a GitOps tool for Kubernetes, automates application deployment and ensures alignment with the Git repository.&lt;/p&gt;
&lt;h2 id=&quot;observability&quot; tabindex=&quot;-1&quot;&gt;Observability&lt;/h2&gt;
&lt;p&gt;Observability is the ability to understand the internal state of a system by examining its outputs. It is a measure of how well a system can be understood from the outside.&lt;/p&gt;
&lt;h3 id=&quot;mimir&quot; tabindex=&quot;-1&quot;&gt;Mimir&lt;/h3&gt;
&lt;p&gt;At Resizes, we&#39;re using &lt;a href=&quot;https://grafana.com/oss/mimir/&quot;&gt;Mimir&lt;/a&gt; to monitor our infrastructure. Mimir is a monitoring tool that helps you monitor with the help of the &lt;a href=&quot;https://grafana.com/oss/agent/&quot;&gt;Grafana Agent&lt;/a&gt;. It&#39;s a lightweight, open-source, and easy-to-use monitoring solution that helps you monitor your infrastructure and applications. It&#39;s built on top of &lt;a href=&quot;https://prometheus.io/&quot;&gt;Prometheus&lt;/a&gt; and Grafana, and it&#39;s designed to be easy to use and easy to deploy. Also it&#39;s designed to be use as a long term storage solution for metrics.&lt;/p&gt;
&lt;h3 id=&quot;loki&quot; tabindex=&quot;-1&quot;&gt;Loki&lt;/h3&gt;
&lt;p&gt;We&#39;re using &lt;a href=&quot;https://grafana.com/oss/loki/&quot;&gt;Loki&lt;/a&gt; to store our logs. Loki is a horizontally-scalable, highly-available, multi-tenant log aggregation system inspired by Prometheus. It is designed to be very cost-effective and easy to operate. It does not index the contents of the logs, but rather a set of labels for each log stream.&lt;/p&gt;
&lt;h3 id=&quot;grafana&quot; tabindex=&quot;-1&quot;&gt;Grafana&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://grafana.com/grafana/&quot;&gt;Grafana&lt;/a&gt; is our tool to visualize our metrics and logs. Grafana is an open-source, general-purpose dashboard and graph composer. It is most commonly used for visualizing time series data for infrastructure and application analytics, but many use it in other domains including industrial sensors, home automation, weather, and process control.&lt;/p&gt;
&lt;h2 id=&quot;secrets-management&quot; tabindex=&quot;-1&quot;&gt;Secrets Management&lt;/h2&gt;
&lt;p&gt;Secrets Management is the process of managing secrets, such as passwords, API keys, and other sensitive information.&lt;/p&gt;
&lt;h3 id=&quot;external-secrets&quot; tabindex=&quot;-1&quot;&gt;External Secrets&lt;/h3&gt;
&lt;p&gt;At Resizes, we&#39;re using &lt;a href=&quot;https://external-secrets.io/&quot;&gt;External Secrets&lt;/a&gt; to manage our secrets. External Secrets is a Kubernetes operator that manages the lifecycle of secrets stored in external secret stores, such as HashiCorp Vault, AWS Secrets Manager, Azure Key Vault, and Google Cloud Secret Manager. It allows you to store secrets in a secure, centralized location and then reference them in your Kubernetes manifests.&lt;/p&gt;
&lt;h2 id=&quot;load-balancing&quot; tabindex=&quot;-1&quot;&gt;Load Balancing&lt;/h2&gt;
&lt;p&gt;Load Balancing is the process of distributing network traffic across multiple servers. It is used to improve the performance, reliability, and scalability of applications.&lt;/p&gt;
&lt;h3 id=&quot;external-dns&quot; tabindex=&quot;-1&quot;&gt;External DNS&lt;/h3&gt;
&lt;p&gt;We&#39;re using &lt;a href=&quot;https://kubernetes-sigs.github.io/external-dns/&quot;&gt;External DNS&lt;/a&gt; to manage our DNS records. External DNS is a Kubernetes operator that manages the lifecycle of DNS records stored in external DNS providers, such as AWS Route 53, Google Cloud DNS, and Azure DNS. It allows you to store DNS records in a secure, centralized location and then reference them in your Kubernetes manifests.&lt;/p&gt;
&lt;h3 id=&quot;nginx-ingress-controller&quot; tabindex=&quot;-1&quot;&gt;NGINX Ingress Controller&lt;/h3&gt;
&lt;p&gt;At Resizes, we&#39;re using &lt;a href=&quot;https://kubernetes.github.io/ingress-nginx/&quot;&gt;NGINX Ingress Controller&lt;/a&gt; to manage our ingress traffic. NGINX Ingress Controller is a Kubernetes operator that manages the lifecycle of ingress traffic. It allows you to manage ingress traffic following the Kubernetes Ingress specification.&lt;/p&gt;
&lt;h2 id=&quot;autoscaling&quot; tabindex=&quot;-1&quot;&gt;Autoscaling&lt;/h2&gt;
&lt;p&gt;Autoscaling is the process of automatically scaling up or down the number of servers in a cluster based on the current load. It is used to improve the performance, reliability, and scalability of applications.&lt;/p&gt;
&lt;h3 id=&quot;karpenter&quot; tabindex=&quot;-1&quot;&gt;Karpenter&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://karpenter.sh/&quot;&gt;Karpenter&lt;/a&gt; is our tool to manage node autoscaling. Karpenter is a Kubernetes operator that manages the lifecycle of autoscaling. It allows you to manage autoscaling performing the scaling up or down of the number of servers in a cluster based on the current load using directly the AWS APIs.&lt;/p&gt;
</content:encoded></item><item><title>DORA Metrics</title><link>https://resiz.es/blog/dora-metrics</link><guid isPermaLink="false">https://blog.resiz.es/dora-metrics</guid><pubDate>Wed, 10 Jan 2024 00:00:00 GMT</pubDate><description>📌 Elevate your team&#39;s performance with DORA Metrics! 📊 Unlock insights into lead time, deployment frequency, mean time to recovery and change failure rate. Learn how to optimize your DevOps pract…</description><content:encoded>&lt;p&gt;📌 Elevate your team&#39;s performance with DORA Metrics! 📊&lt;/p&gt;
&lt;p&gt;Unlock insights into lead time, deployment frequency, mean time to recovery and change failure rate. Learn how to optimize your DevOps practices for success. 💡&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://resiz.es/assets/blog/posts/2024-01-10-dora-metrics/dora-1.png&quot; alt=&quot;Dora Metrics&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;&lt;/p&gt;
&lt;!--truncate--&gt;
&lt;p&gt;&lt;img src=&quot;https://resiz.es/assets/blog/posts/2024-01-10-dora-metrics/dora-2.png&quot; alt=&quot;Lead Time For Changes&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://resiz.es/assets/blog/posts/2024-01-10-dora-metrics/dora-3.png&quot; alt=&quot;Deployment Frequency&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://resiz.es/assets/blog/posts/2024-01-10-dora-metrics/dora-4.png&quot; alt=&quot;Mean Time To Recovery&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://resiz.es/assets/blog/posts/2024-01-10-dora-metrics/dora-5.png&quot; alt=&quot;Change Failure Rate&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://resiz.es/assets/blog/posts/2024-01-10-dora-metrics/dora-6.png&quot; alt=&quot;Dora Metrics&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;&lt;/p&gt;
&lt;p&gt;🚀 DORA Metrics: The Key to DevOps Success 🚀&lt;/p&gt;
</content:encoded></item><item><title>CI/CD with OIDC</title><link>https://resiz.es/blog/cicd-oidc</link><guid isPermaLink="false">https://blog.resiz.es/cicd-oidc</guid><pubDate>Wed, 03 Jan 2024 00:00:00 GMT</pubDate><description>🚀 Leveraging OIDC for Enhanced Security and Efficiency Between GitHub Actions/GitLab CI and AWS 🔒 In the rapidly evolving landscape of DevOps and cloud computing, the integration of GitHub Action…</description><content:encoded>&lt;p&gt;🚀 Leveraging OIDC for Enhanced Security and Efficiency Between GitHub Actions/GitLab CI and AWS 🔒&lt;/p&gt;
&lt;p&gt;In the rapidly evolving landscape of DevOps and cloud computing, the integration of GitHub Actions or GitLab CI with AWS using OpenID Connect (OIDC) stands out as a game changer. Here&#39;s why embracing OIDC can significantly benefit your CI/CD pipelines:&lt;/p&gt;
&lt;!--truncate--&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Enhanced Security: OIDC eliminates the need to store long-lived credentials like AWS access keys in your GitHub or GitLab repositories. This reduces the risk of credential leakage and enhances the overall security of your deployment processes.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Seamless Identity Federation: OIDC allows AWS to trust GitHub Actions or GitLab CI to authenticate users, streamlining the identity verification process. This simplifies user management and ensures a more secure and efficient authentication mechanism.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Automated Role Assumption: With OIDC, specific AWS roles can be assumed directly in GitHub Actions or GitLab CI pipelines. This facilitates granular permission control and ensures that only necessary permissions are granted for each task, enhancing both security and compliance, following the principle of least privilege.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Scalability and Flexibility: OIDC enables a more scalable and flexible approach to managing cloud resources. As your project grows, it&#39;s easy to update and manage permissions without altering the underlying infrastructure.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Cost-Effective: By leveraging OIDC, there&#39;s a reduction in the management overhead associated with credential rotation and management, potentially leading to cost savings and reduced operational complexity.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;🔗 Integrating OIDC with your CI/CD pipelines in GitHub Actions or GitLab CI not only fortifies your security posture but also streamlines your operational workflows. It&#39;s a win-win for teams looking to enhance their cloud capabilities in a secure and efficient manner.&lt;/p&gt;
&lt;aside class=&quot;blog-callout info&quot;&gt;&lt;p class=&quot;callout-title&quot;&gt;Official Documentation&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://docs.github.com/en/actions/deployment/security-hardening-your-deployments/configuring-openid-connect-in-amazon-web-services&quot;&gt;GitHub Actions OIDC Integration&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://docs.gitlab.com/ee/ci/cloud_services/aws&quot;&gt;GitLab CI OIDC Integration&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/aside&gt;
&lt;p&gt;Note that other cloud providers like Azure or GCP have also OIDC integrations with GitHub Actions or GitLab CI. And other CI/CD tools like Azure DevOps may have OIDC integrations with cloud providers. Find your best combination!&lt;/p&gt;
&lt;p&gt;If you are using GitHub Actions and AWS, you can use our &lt;a href=&quot;https://github.com/resizes/platform-terraform-module-github-oidc-aws-role&quot;&gt;open sourced Terraform module&lt;/a&gt; to create IAM related resources and handle permissions for different branches or tags:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-terraform&quot;&gt;module &quot;github-oidc-aws-role&quot; {
  source            = &quot;github.com/resizes/platform-terraform-module-github-oidc-aws-role?ref=main&quot;
  name              = ${ROLE_NAME}
  org_name          = ${ORG_NAME}
  condition_test    = ${CONDITION_TEST}
  actions = [ ${ALLOWED_ACTIONS} ]
  assume_role_policy_condition_values = [
    &quot;repo:${ORG_NAME}/${REPO}:ref:refs/heads/${BRANCH}&quot;,
    &quot;repo:${ORG_NAME}/${REPO}:ref:refs/tags/${TAG}&quot;
  ]
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If you like our repository, please give us a star ⭐️ and follow us on &lt;a href=&quot;https://github.com/resizes&quot;&gt;GitHub&lt;/a&gt;!&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/resizes/platform-terraform-module-github-oidc-aws-role&quot;&gt;View platform-terraform-module-github-oidc-aws-role on GitHub&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/resizes&quot;&gt;Follow Resizes on GitHub&lt;/a&gt;&lt;/p&gt;</content:encoded></item><item><title>IDPs and Platform Engineering</title><link>https://resiz.es/blog/idp-and-platform-engineering</link><guid isPermaLink="false">https://blog.resiz.es/idp-and-platform-engineering</guid><pubDate>Tue, 26 Dec 2023 00:00:00 GMT</pubDate><description>🚀 Embracing Innovation in Tech: The Power of Platform Engineering and Internal Developer Platforms (IDPs) 🌟 In the rapidly evolving landscape of technology, two game-changers have emerged as key …</description><content:encoded>&lt;p&gt;🚀 Embracing Innovation in Tech: The Power of Platform Engineering and Internal Developer Platforms (IDPs) 🌟&lt;/p&gt;
&lt;p&gt;In the rapidly evolving landscape of technology, two game-changers have emerged as key players: Platform Engineering and Internal Developer Platforms (IDPs). These innovative approaches are reshaping how we build, deploy, and manage software. Let&#39;s dive into their transformative benefits:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Streamlined Development Process: IDPs provide a unified platform for development teams, significantly reducing the complexity involved in software creation. This streamlined approach accelerates development cycles, enabling quicker deployment and faster time-to-market.&lt;/li&gt;
&lt;/ul&gt;
&lt;!--truncate--&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Enhanced Collaboration: Platform Engineering fosters a collaborative environment where developers, operations teams, and other stakeholders can work seamlessly together. This synergy not only boosts productivity but also enhances the quality of the end product.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Scalability and Flexibility: With the scalability offered by Platform Engineering, businesses can effortlessly adapt to changing demands. IDPs complement this by offering flexible tools that cater to various development needs, ensuring that scalability does not compromise performance.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Consistency and Standardization: IDPs establish standardized processes and toolsets across projects, leading to consistency in development practices. This uniformity is crucial for maintaining quality and reliability in software products.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Empowering Developers: By abstracting away the complexities of infrastructure management, IDPs allow developers to focus on what they do best – coding. This empowerment leads to higher job satisfaction and increased innovation.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Cost-Effective Solutions: Platform Engineering can lead to significant cost savings by optimizing resource utilization and reducing the overhead associated with managing disparate systems and tools.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Enhanced Security and Compliance: With a centralized platform, enforcing security protocols and compliance standards becomes more manageable, ensuring that all development activities adhere to the highest security norms.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;🌐 Looking Ahead: As we embrace these technologies, the potential for innovation is boundless. Platform Engineering and IDPs are not just tools; they represent a paradigm shift in how we approach software development, promising a future of efficiency, collaboration, and excellence in technology.&lt;/p&gt;
</content:encoded></item><item><title>Resizes Mission</title><link>https://resiz.es/blog/resizes-mission</link><guid isPermaLink="false">https://blog.resiz.es/resizes-mission</guid><pubDate>Tue, 19 Dec 2023 00:00:00 GMT</pubDate><description>🚀 Embracing DevOps and Platform Engineering for Modern Businesses 🚀 In the ever-evolving tech landscape, DevOps is more alive than ever. At Resizes, we&#39;re harnessing the power of DevOps methodolo…</description><content:encoded>&lt;p&gt;🚀 Embracing DevOps and Platform Engineering for Modern Businesses 🚀&lt;/p&gt;
&lt;p&gt;In the ever-evolving tech landscape, DevOps is more alive than ever. At Resizes, we&#39;re harnessing the power of DevOps methodologies and best practices to revolutionize Internal Developer Platforms (IDPs) and implement Platform Engineering across companies of all sizes.&lt;/p&gt;
&lt;!--truncate--&gt;
&lt;p&gt;🔑 Our goal? To fulfill the original DevOps promise: “you build it, you run it”.&lt;/p&gt;
&lt;p&gt;💡 Enhancing Developer Experience with Cloud Native Tech: With the latest in Cloud Native technologies, we&#39;re here to dramatically improve your Developer Experience (DevEx). Our approach ensures that your development teams are not bogged down by repetitive tasks, fostering high performance and reducing dependency on Ops teams.&lt;/p&gt;
&lt;p&gt;🌟 The Secret to High-Performing Teams? Teams that excel have one thing in common: they&#39;ve built an Internal Developer Platform that&#39;s pivotal to their DevOps success. These platforms not only boost developer experience and productivity but also utilize a blend of open-source and proprietary tools, treating the platform as a critical product.&lt;/p&gt;
&lt;p&gt;🛠️ Build or Be Built: Remember, if you don&#39;t proactively build your platform, it will inevitably build itself. The real question is whether you standardize this process or leave it to chance.&lt;/p&gt;
&lt;p&gt;📊 DORA Metrics in Focus: We&#39;re keeping a keen eye on key DORA metrics like deployment frequency, change lead time, change failure rate, and MTTR (service production restoration time) to ensure peak performance.&lt;/p&gt;
&lt;p&gt;📦 Containerization: The Scale Game-Changer: In our journey, containerization has emerged as the essential element for scaling apps efficiently.&lt;/p&gt;
&lt;p&gt;Join us at Resizes in shaping the future of DevOps and Platform Engineering. Let&#39;s create systems that not only work but excel in the modern digital era.&lt;/p&gt;
</content:encoded></item></channel></rss>