<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>Deployment on IT Comparison</title><link>https://comparison.metacog.co.kr/tags/deployment/</link><description>Recent content in Deployment on IT Comparison</description><generator>Hugo</generator><language>en-us</language><lastBuildDate>Mon, 03 Aug 2026 05:23:54 +0900</lastBuildDate><atom:link href="https://comparison.metacog.co.kr/tags/deployment/index.xml" rel="self" type="application/rss+xml"/><item><title>StatefulSet vs Deployment: Stable Identity vs Stateless Replicas</title><link>https://comparison.metacog.co.kr/posts/2026-08-03-statefulset-vs-deployment-stable-identity-vs-stateless-repli/</link><pubDate>Mon, 03 Aug 2026 05:23:54 +0900</pubDate><guid>https://comparison.metacog.co.kr/posts/2026-08-03-statefulset-vs-deployment-stable-identity-vs-stateless-repli/</guid><description>&lt;h2 id="overview"&gt;Overview&lt;/h2&gt;
&lt;p&gt;Both are Kubernetes controllers that manage sets of pods from a template, but they solve different problems: a &lt;strong class="kw"&gt;Deployment&lt;/strong&gt; treats pods as interchangeable, disposable replicas, while a &lt;strong class="kw"&gt;StatefulSet&lt;/strong&gt; gives each pod a stable name, network identity, and persistent storage that survives rescheduling. The choice matters because workloads like databases or clustered systems break if pod identity or storage isn&amp;rsquo;t preserved across restarts.&lt;/p&gt;
&lt;h2 id="comparison-diagram"&gt;Comparison Diagram&lt;/h2&gt;
&lt;div class="compare-diagram"&gt;
&lt;svg viewBox="0 0 640 360" xmlns="http://www.w3.org/2000/svg"&gt;&lt;text x="160" y="30" text-anchor="middle" font-size="18" font-weight="bold" style="fill:var(--primary)"&gt;Deployment&lt;/text&gt;&lt;text x="480" y="30" text-anchor="middle" font-size="18" font-weight="bold" style="fill:var(--primary)"&gt;StatefulSet&lt;/text&gt;&lt;line x1="320" y1="45" x2="320" y2="330" style="stroke:var(--border)" stroke-width="1" stroke-dasharray="4 4"/&gt;&lt;rect x="55" y="70" width="190" height="50" rx="6" style="fill:var(--compare-a-soft);stroke:var(--compare-a)" stroke-width="1.5"/&gt;&lt;text x="150" y="100" text-anchor="middle" font-size="13" style="fill:var(--content)"&gt;web-7f9d4c&lt;/text&gt;&lt;rect x="55" y="150" width="190" height="50" rx="6" style="fill:var(--compare-a-soft);stroke:var(--compare-a)" stroke-width="1.5"/&gt;&lt;text x="150" y="180" text-anchor="middle" font-size="13" style="fill:var(--content)"&gt;web-x9y8z2&lt;/text&gt;&lt;rect x="55" y="230" width="190" height="50" rx="6" style="fill:var(--compare-a-soft);stroke:var(--compare-a)" stroke-width="1.5"/&gt;&lt;text x="150" y="260" text-anchor="middle" font-size="13" style="fill:var(--content)"&gt;web-m4n5p6&lt;/text&gt;&lt;path d="M245,95 C280,110 280,160 245,175" fill="none" style="stroke:var(--compare-a)" stroke-width="1.5" stroke-dasharray="3 3"/&gt;&lt;path d="M245,175 C280,190 280,240 245,255" fill="none" style="stroke:var(--compare-a)" stroke-width="1.5" stroke-dasharray="3 3"/&gt;&lt;text x="150" y="315" text-anchor="middle" font-size="12" style="fill:var(--secondary)"&gt;interchangeable, no stable identity&lt;/text&gt;&lt;rect x="395" y="70" width="150" height="50" rx="6" style="fill:var(--compare-b-soft);stroke:var(--compare-b)" stroke-width="1.5"/&gt;&lt;text x="470" y="100" text-anchor="middle" font-size="13" style="fill:var(--content)"&gt;web-0&lt;/text&gt;&lt;rect x="395" y="150" width="150" height="50" rx="6" style="fill:var(--compare-b-soft);stroke:var(--compare-b)" stroke-width="1.5"/&gt;&lt;text x="470" y="180" text-anchor="middle" font-size="13" style="fill:var(--content)"&gt;web-1&lt;/text&gt;&lt;rect x="395" y="230" width="150" height="50" rx="6" style="fill:var(--compare-b-soft);stroke:var(--compare-b)" stroke-width="1.5"/&gt;&lt;text x="470" y="260" text-anchor="middle" font-size="13" style="fill:var(--content)"&gt;web-2&lt;/text&gt;&lt;line x1="470" y1="120" x2="470" y2="146" style="stroke:var(--compare-b)" stroke-width="1.5"/&gt;&lt;polygon points="470,150 465,140 475,140" style="fill:var(--compare-b)"/&gt;&lt;line x1="470" y1="200" x2="470" y2="226" style="stroke:var(--compare-b)" stroke-width="1.5"/&gt;&lt;polygon points="470,230 465,220 475,220" style="fill:var(--compare-b)"/&gt;&lt;line x1="545" y1="95" x2="565" y2="95" style="stroke:var(--compare-b)" stroke-width="1.5"/&gt;&lt;ellipse cx="590" cy="80" rx="22" ry="6" style="fill:var(--compare-b-soft);stroke:var(--compare-b)" stroke-width="1.5"/&gt;&lt;rect x="568" y="80" width="44" height="30" style="fill:var(--compare-b-soft);stroke:var(--compare-b)" stroke-width="1.5"/&gt;&lt;ellipse cx="590" cy="110" rx="22" ry="6" style="fill:var(--compare-b-soft);stroke:var(--compare-b)" stroke-width="1.5"/&gt;&lt;text x="590" y="99" text-anchor="middle" font-size="9" style="fill:var(--content)"&gt;pvc-0&lt;/text&gt;&lt;line x1="545" y1="175" x2="565" y2="175" style="stroke:var(--compare-b)" stroke-width="1.5"/&gt;&lt;ellipse cx="590" cy="160" rx="22" ry="6" style="fill:var(--compare-b-soft);stroke:var(--compare-b)" stroke-width="1.5"/&gt;&lt;rect x="568" y="160" width="44" height="30" style="fill:var(--compare-b-soft);stroke:var(--compare-b)" stroke-width="1.5"/&gt;&lt;ellipse cx="590" cy="190" rx="22" ry="6" style="fill:var(--compare-b-soft);stroke:var(--compare-b)" stroke-width="1.5"/&gt;&lt;text x="590" y="179" text-anchor="middle" font-size="9" style="fill:var(--content)"&gt;pvc-1&lt;/text&gt;&lt;line x1="545" y1="255" x2="565" y2="255" style="stroke:var(--compare-b)" stroke-width="1.5"/&gt;&lt;ellipse cx="590" cy="240" rx="22" ry="6" style="fill:var(--compare-b-soft);stroke:var(--compare-b)" stroke-width="1.5"/&gt;&lt;rect x="568" y="240" width="44" height="30" style="fill:var(--compare-b-soft);stroke:var(--compare-b)" stroke-width="1.5"/&gt;&lt;ellipse cx="590" cy="270" rx="22" ry="6" style="fill:var(--compare-b-soft);stroke:var(--compare-b)" stroke-width="1.5"/&gt;&lt;text x="590" y="259" text-anchor="middle" font-size="9" style="fill:var(--content)"&gt;pvc-2&lt;/text&gt;&lt;text x="470" y="315" text-anchor="middle" font-size="12" style="fill:var(--secondary)"&gt;stable name, network ID &amp;amp; storage per pod&lt;/text&gt;&lt;/svg&gt;
&lt;/div&gt;
&lt;h2 id="comparison-table"&gt;Comparison Table&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Aspect&lt;/th&gt;
&lt;th&gt;Deployment&lt;/th&gt;
&lt;th&gt;StatefulSet&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Pod naming&lt;/td&gt;
&lt;td&gt;Random hash suffix per replica (web-7f9d4c-x2z9p), changes on every recreation&lt;/td&gt;
&lt;td&gt;Stable ordinal index (web-0, web-1, web-2) fixed for the pod&amp;rsquo;s lifetime&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Network identity&lt;/td&gt;
&lt;td&gt;Pods share a single Service VIP/DNS; individual pods have no predictable DNS name&lt;/td&gt;
&lt;td&gt;Requires a headless Service; each pod gets a stable DNS entry (web-0.svc.namespace)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Storage&lt;/td&gt;
&lt;td&gt;PVCs, if used, aren&amp;rsquo;t guaranteed to reattach to the same pod on recreation&lt;/td&gt;
&lt;td&gt;volumeClaimTemplates provision a dedicated PVC per pod that persists and reattaches&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Scaling&lt;/td&gt;
&lt;td&gt;Creates or removes pods in parallel, in any order&lt;/td&gt;
&lt;td&gt;Scales one pod at a time in strict ordinal order (0, 1, 2, &amp;hellip;)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Rolling updates&lt;/td&gt;
&lt;td&gt;Replaces pods per maxSurge/maxUnavailable, order not guaranteed&lt;/td&gt;
&lt;td&gt;Updates pods one at a time in reverse ordinal order (N-1 down to 0) by default&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Failure recovery&lt;/td&gt;
&lt;td&gt;Replacement pod gets a new name and no guaranteed storage continuity&lt;/td&gt;
&lt;td&gt;Replacement pod keeps the same name/identity and reattaches its original PVC&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Typical workload&lt;/td&gt;
&lt;td&gt;Stateless web servers, APIs, workers that scale horizontally&lt;/td&gt;
&lt;td&gt;Databases, message queues, and clustered systems needing stable peers&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id="key-differences"&gt;Key Differences&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Deployment pods get &lt;strong class="kw"&gt;random names&lt;/strong&gt; on every recreation, while StatefulSet pods keep a fixed &lt;strong class="kw"&gt;ordinal name&lt;/strong&gt; for life&lt;/li&gt;
&lt;li&gt;Only StatefulSet supports &lt;strong class="kw"&gt;volumeClaimTemplates&lt;/strong&gt;, giving each pod its own persistent volume that survives rescheduling&lt;/li&gt;
&lt;li&gt;StatefulSet requires a &lt;strong class="kw"&gt;headless Service&lt;/strong&gt; to give each pod a resolvable, stable DNS entry&lt;/li&gt;
&lt;li&gt;StatefulSet scales and updates pods in strict &lt;strong class="kw"&gt;ordinal order&lt;/strong&gt;; Deployment does both in parallel&lt;/li&gt;
&lt;li&gt;On node failure, Deployment pods lose their identity entirely, while StatefulSet pods are recreated with the &lt;strong class="kw"&gt;same identity&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="when-to-use-each"&gt;When to Use Each&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Deployment&lt;/strong&gt;&lt;/p&gt;</description></item><item><title>Immutable vs Mutable Infrastructure: Replace vs Patch</title><link>https://comparison.metacog.co.kr/posts/2026-08-03-immutable-vs-mutable-infrastructure-replace-vs-patch/</link><pubDate>Mon, 03 Aug 2026 05:18:27 +0900</pubDate><guid>https://comparison.metacog.co.kr/posts/2026-08-03-immutable-vs-mutable-infrastructure-replace-vs-patch/</guid><description>&lt;h2 id="overview"&gt;Overview&lt;/h2&gt;
&lt;p&gt;Immutable infrastructure treats servers as disposable artifacts — every change ships as a brand-new &lt;strong class="kw"&gt;image&lt;/strong&gt; that replaces the running instance rather than editing it. Mutable infrastructure instead &lt;strong class="kw"&gt;updates in place&lt;/strong&gt;, applying patches and config changes directly to long-lived servers. The choice determines how predictable, auditable, and drift-resistant your environments are.&lt;/p&gt;
&lt;h2 id="comparison-diagram"&gt;Comparison Diagram&lt;/h2&gt;
&lt;div class="compare-diagram"&gt;
&lt;svg viewBox="0 0 640 360" xmlns="http://www.w3.org/2000/svg"&gt;&lt;defs&gt;&lt;marker id="arrowA" markerWidth="8" markerHeight="8" refX="6" refY="4" orient="auto"&gt;&lt;path d="M0,0 L8,4 L0,8 z" style="fill:var(--compare-a)"/&gt;&lt;/marker&gt;&lt;marker id="arrowB" markerWidth="8" markerHeight="8" refX="6" refY="4" orient="auto"&gt;&lt;path d="M0,0 L8,4 L0,8 z" style="fill:var(--compare-b)"/&gt;&lt;/marker&gt;&lt;marker id="arrowN" markerWidth="8" markerHeight="8" refX="6" refY="4" orient="auto"&gt;&lt;path d="M0,0 L8,4 L0,8 z" style="fill:var(--secondary)"/&gt;&lt;/marker&gt;&lt;/defs&gt;&lt;line x1="320" y1="20" x2="320" y2="335" style="stroke:var(--border)" stroke-width="1" stroke-dasharray="4 4"/&gt;&lt;text x="160" y="30" text-anchor="middle" style="fill:var(--primary)" font-size="15" font-weight="bold"&gt;Immutable Infrastructure&lt;/text&gt;&lt;text x="480" y="30" text-anchor="middle" style="fill:var(--primary)" font-size="15" font-weight="bold"&gt;Mutable Infrastructure&lt;/text&gt;&lt;rect x="45" y="55" width="100" height="38" rx="4" style="fill:var(--compare-a-soft);stroke:var(--compare-a)" stroke-width="1.5"/&gt;&lt;text x="95" y="78" text-anchor="middle" style="fill:var(--content)" font-size="12"&gt;Image v1&lt;/text&gt;&lt;line x1="95" y1="93" x2="95" y2="118" style="stroke:var(--compare-a)" stroke-width="1.5" marker-end="url(#arrowA)"/&gt;&lt;rect x="45" y="120" width="100" height="50" rx="4" style="fill:var(--compare-a-soft);stroke:var(--compare-a)" stroke-width="1.5"/&gt;&lt;text x="95" y="149" text-anchor="middle" style="fill:var(--content)" font-size="12"&gt;Server v1&lt;/text&gt;&lt;line x1="95" y1="170" x2="95" y2="195" style="stroke:var(--secondary)" stroke-width="1.5" marker-end="url(#arrowN)"/&gt;&lt;rect x="45" y="197" width="100" height="34" rx="4" style="fill:none;stroke:var(--border)" stroke-width="1.5" stroke-dasharray="3 3"/&gt;&lt;text x="95" y="218" text-anchor="middle" style="fill:var(--secondary)" font-size="11"&gt;terminated&lt;/text&gt;&lt;rect x="175" y="55" width="100" height="38" rx="4" style="fill:var(--compare-a-soft);stroke:var(--compare-a)" stroke-width="1.5"/&gt;&lt;text x="225" y="78" text-anchor="middle" style="fill:var(--content)" font-size="12"&gt;Image v2&lt;/text&gt;&lt;line x1="225" y1="93" x2="225" y2="118" style="stroke:var(--compare-a)" stroke-width="1.5" marker-end="url(#arrowA)"/&gt;&lt;rect x="175" y="120" width="100" height="50" rx="4" style="fill:var(--compare-a-soft);stroke:var(--compare-a)" stroke-width="1.5"/&gt;&lt;text x="225" y="149" text-anchor="middle" style="fill:var(--content)" font-size="12"&gt;Server v2&lt;/text&gt;&lt;line x1="225" y1="170" x2="225" y2="195" style="stroke:var(--compare-a)" stroke-width="1.5" marker-end="url(#arrowA)"/&gt;&lt;rect x="175" y="197" width="100" height="34" rx="4" style="fill:var(--compare-a-soft);stroke:var(--compare-a)" stroke-width="1.5"/&gt;&lt;text x="225" y="218" text-anchor="middle" style="fill:var(--content)" font-size="11"&gt;live traffic&lt;/text&gt;&lt;text x="160" y="255" text-anchor="middle" style="fill:var(--secondary)" font-size="11"&gt;change = build new image,&lt;/text&gt;&lt;text x="160" y="270" text-anchor="middle" style="fill:var(--secondary)" font-size="11"&gt;deploy new instance, discard old&lt;/text&gt;&lt;rect x="410" y="130" width="140" height="80" rx="4" style="fill:var(--compare-b-soft);stroke:var(--compare-b)" stroke-width="1.5"/&gt;&lt;text x="480" y="160" text-anchor="middle" style="fill:var(--content)" font-size="12"&gt;Server&lt;/text&gt;&lt;text x="480" y="180" text-anchor="middle" style="fill:var(--content)" font-size="11"&gt;v1 &amp;#8594; v1.1 &amp;#8594; v1.2&lt;/text&gt;&lt;path d="M 460 130 A 40 30 0 1 1 500 130" style="fill:none;stroke:var(--compare-b)" stroke-width="1.5" marker-end="url(#arrowB)"/&gt;&lt;text x="480" y="95" text-anchor="middle" style="fill:var(--content)" font-size="11"&gt;patch in place&lt;/text&gt;&lt;text x="480" y="255" text-anchor="middle" style="fill:var(--secondary)" font-size="11"&gt;change = SSH in / run config&lt;/text&gt;&lt;text x="480" y="270" text-anchor="middle" style="fill:var(--secondary)" font-size="11"&gt;management, edit same instance&lt;/text&gt;&lt;/svg&gt;
&lt;/div&gt;
&lt;h2 id="comparison-table"&gt;Comparison Table&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Aspect&lt;/th&gt;
&lt;th&gt;Immutable Infrastructure&lt;/th&gt;
&lt;th&gt;Mutable Infrastructure&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Initial provisioning&lt;/td&gt;
&lt;td&gt;Instance built once from a versioned image or template&lt;/td&gt;
&lt;td&gt;Instance provisioned once, then edited repeatedly over its life&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Applying a change&lt;/td&gt;
&lt;td&gt;Rebuild the image with the change baked in&lt;/td&gt;
&lt;td&gt;SSH in, or run a config-management tool, against the live server&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Deployment mechanism&lt;/td&gt;
&lt;td&gt;Orchestrator replaces old instances with new ones (rolling/blue-green)&lt;/td&gt;
&lt;td&gt;Update scripts or agents (Ansible, Chef, Puppet) mutate the running instance&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Configuration drift&lt;/td&gt;
&lt;td&gt;Cannot occur — every instance matches its source image exactly&lt;/td&gt;
&lt;td&gt;Accumulates over time as ad hoc changes diverge from documented state&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Rollback&lt;/td&gt;
&lt;td&gt;Redeploy the prior image version, deterministic and fast&lt;/td&gt;
&lt;td&gt;Manually reverse changes on the server, often incomplete or unreliable&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Emergency hotfixes&lt;/td&gt;
&lt;td&gt;Requires rebuilding and redeploying an image, slower to react&lt;/td&gt;
&lt;td&gt;Can be patched directly on the box in seconds&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Auditability &amp;amp; reproducibility&lt;/td&gt;
&lt;td&gt;Image is a versioned artifact; environment is fully reproducible&lt;/td&gt;
&lt;td&gt;True state only knowable by inspecting the live server&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Pipeline &amp;amp; storage overhead&lt;/td&gt;
&lt;td&gt;Needs an image build pipeline and artifact/image registry&lt;/td&gt;
&lt;td&gt;Lower tooling overhead, no build pipeline required&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id="key-differences"&gt;Key Differences&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Immutable instances are never touched after launch; mutable servers are &lt;strong class="kw"&gt;patched in place&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Immutable infrastructure eliminates &lt;strong class="kw"&gt;configuration drift&lt;/strong&gt; by construction.&lt;/li&gt;
&lt;li&gt;Rolling back immutable infra just means redeploying a prior &lt;strong class="kw"&gt;image version&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Mutable infra depends on ongoing &lt;strong class="kw"&gt;config management&lt;/strong&gt; tooling to keep state converged.&lt;/li&gt;
&lt;li&gt;Immutable workflows require an &lt;strong class="kw"&gt;image build pipeline&lt;/strong&gt; and registry that mutable setups skip.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="when-to-use-each"&gt;When to Use Each&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Immutable Infrastructure&lt;/strong&gt;&lt;/p&gt;</description></item></channel></rss>